]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branches 'asoc/topic/adsp', 'asoc/topic/atmel', 'asoc/topic...
authorMark Brown <broonie@linaro.org>
Thu, 16 Jan 2014 12:44:01 +0000 (12:44 +0000)
committerMark Brown <broonie@linaro.org>
Thu, 16 Jan 2014 12:44:01 +0000 (12:44 +0000)
1571 files changed:
CREDITS
Documentation/Changes
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/media/v4l/vidioc-expbuf.xml
Documentation/assoc_array.txt
Documentation/block/null_blk.txt [new file with mode: 0644]
Documentation/device-mapper/cache.txt
Documentation/devicetree/bindings/arm/omap/mpu.txt
Documentation/devicetree/bindings/arm/pmu.txt
Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
Documentation/devicetree/bindings/clock/exynos4-clock.txt
Documentation/devicetree/bindings/clock/exynos5250-clock.txt
Documentation/devicetree/bindings/clock/exynos5420-clock.txt
Documentation/devicetree/bindings/clock/exynos5440-clock.txt
Documentation/devicetree/bindings/gpio/8xxx_gpio.txt
Documentation/devicetree/bindings/i2c/i2c-omap.txt
Documentation/devicetree/bindings/mmc/ti-omap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/davinci_emac.txt
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Documentation/devicetree/bindings/rng/qcom,prng.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/adi,axi-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs42l52.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
Documentation/devicetree/bindings/sound/fsl,esai.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/fsl,ssi.txt
Documentation/devicetree/bindings/sound/fsl-sai.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/hdmi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/max98090.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/simple-card.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/tlv320aic3x.txt
Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt [deleted file]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/gpio/00-INDEX [new file with mode: 0644]
Documentation/gpio/board.txt [new file with mode: 0644]
Documentation/gpio/consumer.txt [new file with mode: 0644]
Documentation/gpio/driver.txt [new file with mode: 0644]
Documentation/gpio/gpio-legacy.txt [moved from Documentation/gpio.txt with 100% similarity]
Documentation/gpio/gpio.txt [new file with mode: 0644]
Documentation/gpio/sysfs.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/mic/mpssd/mpssd.c
Documentation/module-signing.txt [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
Documentation/networking/packet_mmap.txt
Documentation/sound/alsa/soc/overview.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/include/uapi/asm/unistd.h
arch/arc/kernel/perf_event.c
arch/arm/Kconfig
arch/arm/boot/dts/am335x-base0033.dts
arch/arm/boot/dts/am335x-igep0033.dtsi
arch/arm/boot/dts/am3517-evm.dts
arch/arm/boot/dts/am3517.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-xp-mv78230.dtsi
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/at91sam9x5_usart3.dtsi
arch/arm/boot/dts/bcm2835.dtsi
arch/arm/boot/dts/cros5250-common.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
arch/arm/boot/dts/omap-zoom-common.dtsi
arch/arm/boot/dts/omap2.dtsi
arch/arm/boot/dts/omap2420.dtsi
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap3-beagle-xm.dts
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020.dts
arch/arm/boot/dts/omap3-igep0030.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap34xx-hs.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap36xx-hs.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/memory.h
arch/arm/include/asm/pgtable.h
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/process.c
arch/arm/kernel/relocate_kernel.S
arch/arm/kernel/setup.c
arch/arm/kernel/sigreturn_codes.S
arch/arm/kernel/stacktrace.c
arch/arm/kernel/traps.c
arch/arm/lib/delay-loop.S
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/sama5d3.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/ebsa285.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/dss-common.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/omap-secure.h
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_device.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/prm44xx_54xx.h
arch/arm/mach-pxa/include/mach/lubbock.h
arch/arm/mach-pxa/reset.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/common.h
arch/arm/mach-s3c64xx/dma.c [deleted file]
arch/arm/mach-s3c64xx/include/mach/dma.h
arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
arch/arm/mach-s3c64xx/pl080.c [new file with mode: 0644]
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-tegra/fuse.c
arch/arm/mach-ux500/board-mop500-audio.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-vexpress/spc.c
arch/arm/mach-vexpress/spc.h
arch/arm/mach-vexpress/tc2_pm.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/mm/mmap.c
arch/arm/mm/pgd.c
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/xen/enlighten.c
arch/arm/xen/p2m.c
arch/arm64/Kconfig
arch/arm64/boot/dts/foundation-v8.dts
arch/arm64/include/asm/io.h
arch/arm64/include/asm/irqflags.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/xen/page-coherent.h
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/head.S
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/smp.c
arch/arm64/mm/proc.S
arch/avr32/boards/favr-32/setup.c
arch/avr32/configs/atngw100_defconfig
arch/avr32/configs/atngw100_evklcd100_defconfig
arch/avr32/configs/atngw100_evklcd101_defconfig
arch/avr32/configs/atngw100_mrmt_defconfig
arch/avr32/configs/atngw100mkii_defconfig
arch/avr32/configs/atngw100mkii_evklcd100_defconfig
arch/avr32/configs/atngw100mkii_evklcd101_defconfig
arch/avr32/configs/atstk1002_defconfig
arch/avr32/configs/atstk1003_defconfig
arch/avr32/configs/atstk1004_defconfig
arch/avr32/configs/atstk1006_defconfig
arch/avr32/configs/favr-32_defconfig
arch/avr32/configs/hammerhead_defconfig
arch/avr32/configs/merisc_defconfig
arch/avr32/configs/mimc200_defconfig
arch/avr32/kernel/time.c
arch/avr32/mach-at32ap/pm.c
arch/parisc/configs/c3000_defconfig
arch/parisc/configs/c8000_defconfig
arch/parisc/configs/generic-64bit_defconfig
arch/parisc/include/asm/serial.h
arch/parisc/kernel/hardware.c
arch/parisc/kernel/head.S
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/unwind.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
arch/powerpc/Makefile
arch/powerpc/boot/dts/mpc5121.dtsi
arch/powerpc/boot/dts/xcalibur1501.dts
arch/powerpc/boot/dts/xpedite5301.dts
arch/powerpc/boot/dts/xpedite5330.dts
arch/powerpc/boot/dts/xpedite5370.dts
arch/powerpc/boot/util.S
arch/powerpc/configs/52xx/cm5200_defconfig
arch/powerpc/configs/52xx/lite5200b_defconfig
arch/powerpc/configs/52xx/motionpro_defconfig
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/pgalloc-32.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/include/asm/timex.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/nvram_64.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/vdso32/gettimeofday.S
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/mm/hugetlbpage-book3e.c
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/powernv/opal-lpc.c
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/lparcfg.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/nvram.c
arch/powerpc/platforms/pseries/pci.c
arch/powerpc/sysdev/ppc4xx_ocm.c
arch/s390/Kconfig
arch/s390/crypto/aes_s390.c
arch/s390/include/asm/page.h
arch/s390/include/asm/sclp.h
arch/s390/include/asm/vdso.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/pgm_check.S
arch/s390/kernel/signal.c
arch/s390/kernel/time.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso32/gettimeofday.S
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kernel/vdso64/gettimeofday.S
arch/s390/lib/uaccess_pt.c
arch/sh/lib/Makefile
arch/sparc/include/asm/pgtable_64.h
arch/um/Makefile
arch/um/kernel/sysrq.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/Makefile
arch/x86/boot/compressed/Makefile
arch/x86/crypto/Makefile
arch/x86/crypto/aesni-intel_glue.c
arch/x86/crypto/camellia_aesni_avx2_glue.c
arch/x86/crypto/camellia_aesni_avx_glue.c
arch/x86/crypto/cast5_avx_glue.c
arch/x86/crypto/cast6_avx_glue.c
arch/x86/crypto/serpent_avx2_glue.c
arch/x86/crypto/serpent_avx_glue.c
arch/x86/crypto/serpent_sse2_glue.c
arch/x86/crypto/sha256_ssse3_glue.c
arch/x86/crypto/twofish_avx_glue.c
arch/x86/include/asm/atomic.h
arch/x86/include/asm/atomic64_64.h
arch/x86/include/asm/bitops.h
arch/x86/include/asm/local.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/preempt.h
arch/x86/include/asm/rmwcc.h
arch/x86/include/asm/simd.h [new file with mode: 0644]
arch/x86/include/asm/trace/irq_vectors.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/reboot.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/x86.c
arch/x86/mm/gup.c
arch/x86/platform/efi/early_printk.c
arch/x86/platform/efi/efi.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/realmode/rm/Makefile
block/blk-cgroup.h
block/blk-flush.c
block/blk-mq-sysfs.c
block/blk-mq.c
crypto/Kconfig
crypto/Makefile
crypto/ablk_helper.c [moved from arch/x86/crypto/ablk_helper.c with 95% similarity]
crypto/ablkcipher.c
crypto/algif_hash.c
crypto/algif_skcipher.c
crypto/ansi_cprng.c
crypto/asymmetric_keys/rsa.c
crypto/asymmetric_keys/x509_public_key.c
crypto/authenc.c
crypto/authencesn.c
crypto/ccm.c
crypto/gcm.c
crypto/memneq.c [new file with mode: 0644]
crypto/tcrypt.c
crypto/testmgr.c
drivers/acpi/Kconfig
drivers/acpi/acpi_lpss.c
drivers/acpi/acpica/acresrc.h
drivers/acpi/acpica/nsalloc.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/rscalc.c
drivers/acpi/acpica/rscreate.c
drivers/acpi/acpica/rsutils.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/apei/Kconfig
drivers/acpi/apei/erst.c
drivers/acpi/nvs.c
drivers/acpi/pci_root.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/ata/ahci.c
drivers/ata/ahci_imx.c
drivers/ata/ahci_platform.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/libata-zpodd.c
drivers/ata/pata_arasan_cf.c
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap.c
drivers/block/null_blk.c
drivers/block/skd_main.c
drivers/block/xen-blkfront.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/Makefile
drivers/char/hw_random/msm-rng.c [new file with mode: 0644]
drivers/char/hw_random/omap3-rom-rng.c [new file with mode: 0644]
drivers/char/hw_random/pseries-rng.c
drivers/char/hw_random/via-rng.c
drivers/char/i8k.c
drivers/clk/clk-s2mps11.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clocksource/Kconfig
drivers/clocksource/clksrc-of.c
drivers/clocksource/dw_apb_timer_of.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/sh_tmu.c
drivers/clocksource/sun4i_timer.c
drivers/clocksource/time-armada-370-xp.c
drivers/cpufreq/at32ap-cpufreq.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/exynos4210-cpufreq.c
drivers/cpufreq/exynos4x12-cpufreq.c
drivers/cpufreq/exynos5250-cpufreq.c
drivers/cpufreq/tegra-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/crypto/caam/Kconfig
drivers/crypto/caam/Makefile
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamhash.c
drivers/crypto/caam/caamrng.c
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/desc.h
drivers/crypto/caam/intern.h
drivers/crypto/caam/jr.c
drivers/crypto/caam/jr.h
drivers/crypto/caam/regs.h
drivers/crypto/caam/sg_sw_sec4.h
drivers/crypto/dcp.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/mv_cesa.c
drivers/crypto/omap-aes.c
drivers/crypto/omap-sham.c
drivers/crypto/picoxcell_crypto.c
drivers/crypto/sahara.c
drivers/crypto/talitos.c
drivers/crypto/tegra-aes.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/mmp_pdma.c
drivers/dma/mv_xor.c
drivers/dma/of-dma.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/s3c24xx-dma.c
drivers/dma/sh/rcar-hpbdma.c
drivers/dma/txx9dmac.c
drivers/edac/sb_edac.c
drivers/extcon/extcon-arizona.c
drivers/extcon/extcon-class.c
drivers/firmware/Makefile
drivers/firmware/efi/Kconfig
drivers/firmware/efi/Makefile
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/efivars.c
drivers/firmware/efi/vars.c
drivers/gpio/gpio-bcm-kona.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-msm-v2.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-tb10x.c
drivers/gpio/gpio-twl4030.c
drivers/gpio/gpio-ucb1400.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/armada/armada_drm.h
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/armada/armada_fbdev.c
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_hwmon.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/qxl/Kconfig
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_release.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_i2c.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_trace.h
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/hw/cdma_hw.c
drivers/gpu/host1x/hw/debug_hw.c
drivers/hid/Kconfig
drivers/hid/hid-appleir.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-kye.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/hid-wiimote-core.c
drivers/hid/uhid.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/hih6130.c
drivers/hwmon/lm78.c
drivers/hwmon/lm90.c
drivers/hwmon/sis5595.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83l786ng.c
drivers/i2c/busses/i2c-bcm-kona.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-diolan-u2c.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/i2c-mux.c
drivers/idle/intel_idle.c
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/accel/kxsd9.c
drivers/iio/adc/ad7887.c
drivers/iio/adc/at91_adc.c
drivers/iio/adc/mcp3422.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/common/hid-sensors/Kconfig
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/common/hid-sensors/hid-sensor-trigger.h
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/imu/adis16400_core.c
drivers/iio/light/Kconfig
drivers/iio/light/cm36651.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/magnetometer/Kconfig
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/iio/magnetometer/mag3110.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/bf54x-keys.c
drivers/input/misc/adxl34x.c
drivers/input/misc/hp_sdc_rtc.c
drivers/input/misc/pcf8574_keypad.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/elantech.c
drivers/input/serio/serio.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/atmel-wm97xx.c
drivers/input/touchscreen/cyttsp4_core.c
drivers/input/touchscreen/sur40.c [new file with mode: 0644]
drivers/input/touchscreen/usbtouchscreen.c
drivers/iommu/arm-smmu.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/leds/leds-pwm.c
drivers/macintosh/Makefile
drivers/md/bcache/alloc.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/movinggc.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/util.c
drivers/md/bcache/util.h
drivers/md/bcache/writeback.c
drivers/md/dm-bufio.c
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-target.c
drivers/md/dm-delay.c
drivers/md/dm-snap.c
drivers/md/dm-stats.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/persistent-data/dm-array.c
drivers/md/persistent-data/dm-block-manager.c
drivers/md/persistent-data/dm-block-manager.h
drivers/md/persistent-data/dm-space-map-common.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/raid5.c
drivers/media/common/siano/smscoreapi.h
drivers/media/common/siano/smsdvb.h
drivers/media/dvb-core/dvb_demux.c
drivers/media/dvb-frontends/af9033.c
drivers/media/dvb-frontends/cxd2820r_c.c
drivers/media/dvb-frontends/dib8000.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/dvb-frontends/rtl2830.c
drivers/media/i2c/adv7183_regs.h
drivers/media/i2c/adv7604.c
drivers/media/i2c/adv7842.c
drivers/media/i2c/ir-kbd-i2c.c
drivers/media/i2c/m5mols/m5mols_controls.c
drivers/media/i2c/mt9p031.c
drivers/media/i2c/s5c73m3/s5c73m3-core.c
drivers/media/i2c/s5c73m3/s5c73m3.h
drivers/media/i2c/saa7115.c
drivers/media/i2c/soc_camera/ov5642.c
drivers/media/i2c/ths7303.c
drivers/media/i2c/wm8775.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/cx18/cx18-driver.h
drivers/media/pci/cx23885/cx23885-417.c
drivers/media/pci/pluto2/pluto2.c
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/platform/coda.c
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/platform/exynos4-is/media-dev.c
drivers/media/platform/marvell-ccic/mmp-driver.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s5p-mfc/regs-mfc.h
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/platform/s5p-tv/mixer.h
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/soc_camera/omap1_camera.c
drivers/media/platform/vivi.c
drivers/media/platform/vsp1/vsp1_drv.c
drivers/media/platform/vsp1/vsp1_video.c
drivers/media/radio/radio-shark.c
drivers/media/radio/radio-shark2.c
drivers/media/radio/radio-si476x.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/tef6862.c
drivers/media/rc/imon.c
drivers/media/rc/redrat3.c
drivers/media/tuners/mt2063.c
drivers/media/tuners/tuner-xc2028-types.h
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/mxl111sf.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/em28xx/em28xx-video.c
drivers/media/usb/gspca/gl860/gl860.c
drivers/media/usb/gspca/pac207.c
drivers/media/usb/gspca/pac7302.c
drivers/media/usb/gspca/stk1135.c
drivers/media/usb/gspca/stv0680.c
drivers/media/usb/gspca/sunplus.c
drivers/media/usb/gspca/zc3xx.c
drivers/media/usb/pwc/pwc-if.c
drivers/media/usb/usbtv/usbtv.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/mfd/Kconfig
drivers/mfd/lpc_ich.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/ti-ssp.c
drivers/mfd/twl-core.c
drivers/mfd/twl6040.c
drivers/mfd/wm5110-tables.c
drivers/misc/enclosure.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mic/card/mic_virtio.c
drivers/misc/mic/card/mic_virtio.h
drivers/misc/mic/host/mic_boot.c
drivers/misc/mic/host/mic_virtio.c
drivers/misc/mic/host/mic_x100.c
drivers/mmc/host/omap.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/c_can/c_can.c
drivers/net/can/flexcan.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/usb/ems_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/intel/e1000/e1000.h
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_selftest.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi.h
drivers/net/ethernet/sfc/mcdi_mon.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvtap.c
drivers/net/phy/micrel.c
drivers/net/phy/vitesse.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/ntb/ntb_hw.c
drivers/ntb/ntb_hw.h
drivers/ntb/ntb_regs.h
drivers/ntb/ntb_transport.c
drivers/pci/host/pci-mvebu.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/pinctrl/pinctrl-abx500.c
drivers/pinctrl/pinctrl-abx500.h
drivers/pinctrl/pinctrl-baytrail.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/sh-pfc/pfc-r8a7740.c
drivers/pinctrl/sh-pfc/pfc-sh7372.c
drivers/pinctrl/sh-pfc/sh_pfc.h
drivers/platform/Kconfig
drivers/platform/Makefile
drivers/platform/chrome/Kconfig [new file with mode: 0644]
drivers/platform/chrome/Makefile [new file with mode: 0644]
drivers/platform/chrome/chromeos_laptop.c [moved from drivers/platform/x86/chromeos_laptop.c with 100% similarity]
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/topstar-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/pnp/driver.c
drivers/powercap/intel_rapl.c
drivers/powercap/powercap_sys.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3722-regulator.c
drivers/regulator/core.c
drivers/regulator/gpio-regulator.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-s5m.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_genhd.c
drivers/s390/char/sclp_early.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/aacraid/linit.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfad_attr.c
drivers/scsi/gdth.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_hwi.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/pm8001/pm80xx_hwi.h
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/sd.c
drivers/scsi/storvsc_drv.c
drivers/spi/Kconfig
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mxs.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-txx9.c
drivers/spi/spi.c
drivers/staging/btmtk_usb/btmtk_usb.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/pcl730.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/comedi/drivers/vmk80xx.c
drivers/staging/ft1000/ft1000-usb/ft1000_download.c
drivers/staging/iio/magnetometer/Kconfig
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/imx-drm/Makefile
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-tve.c
drivers/staging/imx-drm/ipu-v3/ipu-common.c
drivers/staging/lustre/lustre/ptlrpc/pinger.c
drivers/staging/media/go7007/go7007-usb.c
drivers/staging/nvec/nvec.c
drivers/staging/rtl8188eu/core/rtw_ap.c
drivers/staging/tidspbridge/Kconfig
drivers/staging/tidspbridge/rmgr/drv_interface.c
drivers/staging/vt6655/hostap.c
drivers/staging/vt6656/baseband.c
drivers/staging/vt6656/hostap.c
drivers/staging/vt6656/rndis.h
drivers/staging/zram/zram_drv.c
drivers/staging/zsmalloc/zsmalloc-main.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_file.h
drivers/target/target_core_tpg.c
drivers/tty/amiserial.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_io.c
drivers/tty/tty_ldsem.c
drivers/uio/uio.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hub.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/storage_common.h
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/gadget/zero.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_gadget.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-am335x.c
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-generic.h
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-rcar-gen2-usb.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/phy/phy-twl6030-usb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/generic.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/zte_ev.c
drivers/usb/wusbcore/devconnect.c
drivers/usb/wusbcore/security.c
drivers/usb/wusbcore/wusbhc.h
drivers/video/atmel_lcdfb.c
drivers/video/kyro/fbdev.c
drivers/video/offb.c
drivers/video/omap2/displays-new/panel-sony-acx565akm.c
drivers/video/sh_mobile_meram.c
drivers/video/vt8500lcdfb.c
drivers/virtio/virtio_balloon.c
drivers/watchdog/bcm2835_wdt.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/ie6xx_wdt.c
drivers/watchdog/jz4740_wdt.c
drivers/watchdog/kempld_wdt.c
drivers/watchdog/max63xx_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/rt2880_wdt.c
drivers/watchdog/sc1200wdt.c
drivers/watchdog/shwdt.c
drivers/watchdog/softdog.c
drivers/watchdog/stmp3xxx_rtc_wdt.c
drivers/watchdog/txx9wdt.c
drivers/watchdog/ux500_wdt.c
drivers/xen/balloon.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
drivers/xen/swiotlb-xen.c
fs/affs/Changes
fs/aio.c
fs/btrfs/check-integrity.c
fs/btrfs/check-integrity.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/ceph/addr.c
fs/ceph/cache.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/cifs/cifsglob.h
fs/cifs/ioctl.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2proto.h
fs/cifs/smbfsctl.h
fs/dcache.c
fs/eventpoll.c
fs/ext2/super.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/hfsplus/wrapper.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/transaction.c
fs/logfs/dev_bdev.c
fs/namei.c
fs/nfs/blocklayout/blocklayout.h
fs/nfs/blocklayout/extents.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfsd/nfscache.c
fs/pipe.c
fs/proc/inode.c
fs/pstore/platform.c
fs/squashfs/file_direct.c
fs/sysfs/file.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_ioctl32.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_trans_buf.c
include/acpi/acconfig.h
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/asm-generic/pgtable.h
include/asm-generic/preempt.h
include/asm-generic/simd.h [new file with mode: 0644]
include/asm-generic/word-at-a-time.h
include/crypto/ablk_helper.h [moved from arch/x86/include/asm/crypto/ablk_helper.h with 100% similarity]
include/crypto/algapi.h
include/crypto/authenc.h
include/crypto/scatterwalk.h
include/linux/assoc_array.h
include/linux/auxvec.h
include/linux/compiler-intel.h
include/linux/dcache.h
include/linux/dmaengine.h
include/linux/efi.h
include/linux/ftrace_event.h
include/linux/gpio/driver.h
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/hugetlb.h
include/linux/i2c/twl.h
include/linux/ipv6.h
include/linux/irqreturn.h
include/linux/kernel.h
include/linux/kexec.h
include/linux/libata.h
include/linux/lockref.h
include/linux/math64.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/samsung/core.h
include/linux/micrel_phy.h
include/linux/migrate.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/net.h
include/linux/netdevice.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/padata.h
include/linux/pci.h
include/linux/percpu-defs.h
include/linux/platform_data/asoc-ti-mcbsp.h
include/linux/platform_data/asoc-ux500-msp.h
include/linux/platform_data/davinci_asp.h
include/linux/pstore.h
include/linux/reboot.h
include/linux/sched.h
include/linux/shmem_fs.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/tegra-powergate.h
include/linux/tracepoint.h
include/linux/usb.h
include/linux/usb/wusb.h
include/media/videobuf2-core.h
include/net/ip.h
include/net/ipv6.h
include/net/ping.h
include/net/sctp/structs.h
include/net/sock.h
include/rdma/ib_verbs.h
include/scsi/scsi_host.h
include/sound/cs42l52.h
include/sound/dmaengine_pcm.h
include/sound/hda_verbs.h [new file with mode: 0644]
include/sound/memalloc.h
include/sound/pcm.h
include/sound/pcm_params.h
include/sound/rcar_snd.h
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/spear_dma.h
include/target/target_core_base.h
include/trace/ftrace.h
include/uapi/drm/vmwgfx_drm.h
include/uapi/linux/eventpoll.h
include/uapi/linux/genetlink.h
include/uapi/linux/if_link.h
include/uapi/linux/input.h
include/uapi/linux/mic_common.h
include/uapi/linux/netlink_diag.h
include/uapi/linux/packet_diag.h
include/uapi/linux/perf_event.h
include/uapi/linux/unix_diag.h
include/uapi/sound/compress_offload.h
include/uapi/sound/compress_params.h
include/xen/interface/io/blkif.h
init/Kconfig
kernel/.gitignore
kernel/Makefile
kernel/bounds.c
kernel/cgroup.c
kernel/cpuset.c
kernel/events/core.c
kernel/extable.c
kernel/fork.c
kernel/freezer.c
kernel/futex.c
kernel/irq/pm.c
kernel/kexec.c
kernel/padata.c
kernel/power/console.c
kernel/rcu/tree_plugin.h
kernel/reboot.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/system_certificates.S
kernel/system_keyring.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_events.c
kernel/trace/trace_syscalls.c
kernel/user.c
kernel/workqueue.c
lib/assoc_array.c
lib/lockref.c
mm/Kconfig
mm/compaction.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mprotect.c
mm/page_alloc.c
mm/pgtable-generic.c
mm/rmap.c
mm/shmem.c
net/bridge/br_private.h
net/bridge/br_stp_bpdu.c
net/compat.c
net/core/drop_monitor.c
net/core/neighbour.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ipv6.c
net/hsr/hsr_framereg.c
net/hsr/hsr_netlink.c
net/ipv4/fib_rules.c
net/ipv4/ip_sockglue.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/netfilter/nft_reject_ipv4.c
net/ipv4/ping.c
net/ipv4/protocol.c
net/ipv4/raw.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_memcontrol.c
net/ipv4/tcp_offload.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_output.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/ping.c
net/ipv6/protocol.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/tcpv6_offload.c
net/ipv6/udp.c
net/l2tp/l2tp_ip6.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/spectmgmt.c
net/mac80211/util.c
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/nf_tables_api.c
net/netfilter/xt_hashlimit.c
net/netlink/genetlink.c
net/packet/af_packet.c
net/rds/ib_send.c
net/sched/act_api.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/sch_htb.c
net/sched/sch_netem.c
net/sched/sch_tbf.c
net/sctp/associola.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/probe.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/transport.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/tipc/core.c
net/tipc/handler.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/ibss.c
net/wireless/nl80211.c
scripts/link-vmlinux.sh
scripts/recordmcount.pl
scripts/sortextable.c
security/integrity/digsig.c
security/integrity/ima/Kconfig
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c
security/integrity/ima/ima_crypto.c
security/integrity/ima/ima_fs.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_template.c
security/integrity/ima/ima_template_lib.c
security/integrity/integrity.h
security/keys/big_key.c
security/keys/key.c
security/keys/keyring.c
security/selinux/hooks.c
security/selinux/include/xfrm.h
security/selinux/ss/services.c
security/selinux/xfrm.c
sound/arm/aaci.c
sound/atmel/abdac.c
sound/core/Makefile
sound/core/compress_offload.c
sound/core/memalloc.c
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_misc.c
sound/firewire/amdtp.c
sound/firewire/dice.c
sound/oss/dmabuf.c
sound/oss/dmasound/dmasound.h
sound/oss/dmasound/dmasound_core.c
sound/oss/midibuf.c
sound/oss/msnd_pinnacle.c
sound/oss/sequencer.c
sound/oss/sleep.h [new file with mode: 0644]
sound/oss/swarm_cs4297a.c
sound/oss/vwsnd.c
sound/pci/Kconfig
sound/pci/cs46xx/cs46xx.h
sound/pci/cs46xx/cs46xx_image.h [deleted file]
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs46xx/imgs/cwc4630.h [deleted file]
sound/pci/cs46xx/imgs/cwcasync.h [deleted file]
sound/pci/cs46xx/imgs/cwcbinhack.h [deleted file]
sound/pci/cs46xx/imgs/cwcdma.asp [deleted file]
sound/pci/cs46xx/imgs/cwcdma.h [deleted file]
sound/pci/cs46xx/imgs/cwcsnoop.h [deleted file]
sound/pci/cs5535audio/cs5535audio.c
sound/pci/ctxfi/ctatc.c
sound/pci/es1968.c
sound/pci/hda/Kconfig
sound/pci/hda/Makefile
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/hda/thinkpad_helper.c [new file with mode: 0644]
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/rme9652.c
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/adi/Kconfig [new file with mode: 0644]
sound/soc/adi/Makefile [new file with mode: 0644]
sound/soc/adi/axi-i2s.c [new file with mode: 0644]
sound/soc/adi/axi-spdif.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm-dma.c
sound/soc/atmel/atmel-pcm-pdc.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/sam9x5_wm8731.c
sound/soc/au1x/dbdma2.c
sound/soc/au1x/dma.c
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/cirrus/edb93xx.c
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/cirrus/ep93xx-pcm.h [new file with mode: 0644]
sound/soc/cirrus/simone.c
sound/soc/cirrus/snappercl15.c
sound/soc/codecs/Kconfig
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad193x.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/alc5632.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/da7210.c
sound/soc/codecs/da7213.c
sound/soc/codecs/da732x.c
sound/soc/codecs/da9055.c
sound/soc/codecs/hdmi.c
sound/soc/codecs/isabelle.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98090.c
sound/soc/codecs/max98095.c
sound/soc/codecs/max9850.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/ssm2518.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8990.h
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8991.h
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8997.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.h
sound/soc/davinci/Kconfig
sound/soc/davinci/Makefile
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_esai.c [new file with mode: 0644]
sound/soc/fsl/fsl_esai.h [new file with mode: 0644]
sound/soc/fsl/fsl_sai.c [new file with mode: 0644]
sound/soc/fsl/fsl_sai.h [new file with mode: 0644]
sound/soc/fsl/fsl_spdif.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.h
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm.h
sound/soc/fsl/imx-spdif.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/imx-ssi.h
sound/soc/fsl/imx-wm8962.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/fsl/mpc5200_psc_i2s.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/generic/simple-card.c
sound/soc/intel/Kconfig [moved from sound/soc/mid-x86/Kconfig with 100% similarity]
sound/soc/intel/Makefile [moved from sound/soc/mid-x86/Makefile with 100% similarity]
sound/soc/intel/mfld_machine.c [moved from sound/soc/mid-x86/mfld_machine.c with 100% similarity]
sound/soc/intel/sst_dsp.h [moved from sound/soc/mid-x86/sst_dsp.h with 100% similarity]
sound/soc/intel/sst_platform.c [moved from sound/soc/mid-x86/sst_platform.c with 98% similarity]
sound/soc/intel/sst_platform.h [moved from sound/soc/mid-x86/sst_platform.h with 97% similarity]
sound/soc/jz4740/Kconfig
sound/soc/jz4740/jz4740-i2s.c
sound/soc/jz4740/jz4740-pcm.c [deleted file]
sound/soc/jz4740/jz4740-pcm.h [deleted file]
sound/soc/jz4740/qi_lb60.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-pcm.h
sound/soc/mxs/mxs-saif.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/mcbsp.c
sound/soc/omap/n810.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c
sound/soc/pxa/Kconfig
sound/soc/pxa/mmp-pcm.c
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/Kconfig
sound/soc/samsung/Makefile
sound/soc/samsung/ac97.c
sound/soc/samsung/dma.c
sound/soc/samsung/dma.h
sound/soc/samsung/dmaengine.c [new file with mode: 0644]
sound/soc/samsung/i2s.c
sound/soc/samsung/idma.c
sound/soc/samsung/pcm.c
sound/soc/samsung/regs-ac97.h
sound/soc/samsung/regs-iis.h
sound/soc/sh/Kconfig
sound/soc/sh/dma-sh7760.c
sound/soc/sh/fsi.c
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/scu.c
sound/soc/sh/rcar/ssi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-io.c
sound/soc/soc-pcm.c
sound/soc/soc-utils.c
sound/soc/spear/spdif_in.c
sound/soc/spear/spdif_out.c
sound/soc/spear/spear_pcm.c
sound/soc/spear/spear_pcm.h [new file with mode: 0644]
sound/soc/tegra/Kconfig
sound/soc/tegra/Makefile
sound/soc/tegra/tegra20_ac97.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra_max98090.c [new file with mode: 0644]
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_wm9712.c
sound/soc/txx9/txx9aclc.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_dai.c
sound/soc/ux500/ux500_msp_i2s.c
sound/soc/ux500/ux500_msp_i2s.h
sound/soc/ux500/ux500_pcm.c
sound/spi/at73c213.c
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/hiface/pcm.c
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/lib/traceevent/event-parse.c
tools/perf/util/header.c
tools/perf/util/thread.c
tools/power/cpupower/man/cpupower-idle-info.1
tools/power/cpupower/man/cpupower-idle-set.1 [new file with mode: 0644]
tools/power/cpupower/utils/cpupower-set.c
tools/power/cpupower/utils/helpers/sysfs.c
tools/usb/Makefile
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 4fc997d58ab2640a4b94fdcb1f363935f8a13395..4c7738f493570eb9d0c70e6db67c527bcbe6e691 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -655,6 +655,11 @@ S: Stanford University
 S: Stanford, California 94305
 S: USA
 
+N: Carlos Chinea
+E: carlos.chinea@nokia.com
+E: cch.devel@gmail.com
+D: Author of HSI Subsystem
+
 N: Randolph Chung
 E: tausq@debian.org
 D: Linux/PA-RISC hacker
index b1758088527339466c5d5eb8be6151eabe02952d..07c75d18154e7608f9368caaf6fbbca2baa6aafd 100644 (file)
@@ -196,13 +196,6 @@ chmod 0644 /dev/cpu/microcode
 as root before you can use this.  You'll probably also want to
 get the user-space microcode_ctl utility to use with this.
 
-Powertweak
-----------
-
-If you are running v0.1.17 or earlier, you should upgrade to
-version v0.99.0 or higher. Running old versions may cause problems
-with programs using shared memory.
-
 udev
 ----
 udev is a userspace application for populating /dev dynamically with
@@ -366,10 +359,6 @@ Intel P6 microcode
 ------------------
 o  <http://www.urbanmyth.org/microcode/>
 
-Powertweak
-----------
-o  <http://powertweak.sourceforge.net/>
-
 udev
 ----
 o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
index 6c9d9d37c83a30e24cce3ed25abf484e1bbd18f1..f5170082bdb3738eb409d67dfedd2851b683d2b6 100644 (file)
@@ -58,7 +58,7 @@
      </sect1>
      <sect1><title>Wait queues and Wake events</title>
 !Iinclude/linux/wait.h
-!Ekernel/wait.c
+!Ekernel/sched/wait.c
      </sect1>
      <sect1><title>High-resolution timers</title>
 !Iinclude/linux/ktime.h
index e287c8fc803b437ce34550ba88777183f66ca0cc..4165e7bfa4ff7560c0283213e53a54b1575ab2e8 100644 (file)
@@ -73,7 +73,8 @@ range from zero to the maximal number of valid planes for the currently active
 format. For the single-planar API, applications must set <structfield> plane
 </structfield> to zero.  Additional flags may be posted in the <structfield>
 flags </structfield> field.  Refer to a manual for open() for details.
-Currently only O_CLOEXEC is supported.  All other fields must be set to zero.
+Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported.  All
+other fields must be set to zero.
 In the case of multi-planar API, every plane is exported separately using
 multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
 
@@ -170,8 +171,9 @@ multi-planar API. Otherwise this value must be set to zero. </entry>
            <entry>__u32</entry>
            <entry><structfield>flags</structfield></entry>
            <entry>Flags for the newly created file, currently only <constant>
-O_CLOEXEC </constant> is supported, refer to the manual of open() for more
-details.</entry>
+O_CLOEXEC </constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY
+</constant>, and <constant>O_RDWR</constant> are supported, refer to the manual
+of open() for more details.</entry>
          </row>
          <row>
            <entry>__s32</entry>
index f4faec0f66e400dc18c176eb7c567dd2aa18f761..2f2c6cdd73c0c24ab29dcd3f68034f99f17c3125 100644 (file)
@@ -164,10 +164,10 @@ This points to a number of methods, all of which need to be provided:
 
  (4) Diff the index keys of two objects.
 
-       int (*diff_objects)(const void *a, const void *b);
+       int (*diff_objects)(const void *object, const void *index_key);
 
-     Return the bit position at which the index keys of two objects differ or
-     -1 if they are the same.
+     Return the bit position at which the index key of the specified object
+     differs from the given index key or -1 if they are the same.
 
 
  (5) Free an object.
diff --git a/Documentation/block/null_blk.txt b/Documentation/block/null_blk.txt
new file mode 100644 (file)
index 0000000..b2830b4
--- /dev/null
@@ -0,0 +1,72 @@
+Null block device driver
+================================================================================
+
+I. Overview
+
+The null block device (/dev/nullb*) is used for benchmarking the various
+block-layer implementations. It emulates a block device of X gigabytes in size.
+The following instances are possible:
+
+  Single-queue block-layer
+    - Request-based.
+    - Single submission queue per device.
+    - Implements IO scheduling algorithms (CFQ, Deadline, noop).
+  Multi-queue block-layer
+    - Request-based.
+    - Configurable submission queues per device.
+  No block-layer (Known as bio-based)
+    - Bio-based. IO requests are submitted directly to the device driver.
+    - Directly accepts bio data structure and returns them.
+
+All of them have a completion queue for each core in the system.
+
+II. Module parameters applicable for all instances:
+
+queue_mode=[0-2]: Default: 2-Multi-queue
+  Selects which block-layer the module should instantiate with.
+
+  0: Bio-based.
+  1: Single-queue.
+  2: Multi-queue.
+
+home_node=[0--nr_nodes]: Default: NUMA_NO_NODE
+  Selects what CPU node the data structures are allocated from.
+
+gb=[Size in GB]: Default: 250GB
+  The size of the device reported to the system.
+
+bs=[Block size (in bytes)]: Default: 512 bytes
+  The block size reported to the system.
+
+nr_devices=[Number of devices]: Default: 2
+  Number of block devices instantiated. They are instantiated as /dev/nullb0,
+  etc.
+
+irq_mode=[0-2]: Default: 1-Soft-irq
+  The completion mode used for completing IOs to the block-layer.
+
+  0: None.
+  1: Soft-irq. Uses IPI to complete IOs across CPU nodes. Simulates the overhead
+     when IOs are issued from another CPU node than the home the device is
+     connected to.
+  2: Timer: Waits a specific period (completion_nsec) for each IO before
+     completion.
+
+completion_nsec=[ns]: Default: 10.000ns
+  Combined with irq_mode=2 (timer). The time each completion event must wait.
+
+submit_queues=[0..nr_cpus]:
+  The number of submission queues attached to the device driver. If unset, it
+  defaults to 1 on single-queue and bio-based instances. For multi-queue,
+  it is ignored when use_per_node_hctx module parameter is 1.
+
+hw_queue_depth=[0..qdepth]: Default: 64
+  The hardware queue depth of the device.
+
+III: Multi-queue specific parameters
+
+use_per_node_hctx=[0/1]: Default: 0
+  0: The number of submit queues are set to the value of the submit_queues
+     parameter.
+  1: The multi-queue block layer is instantiated with a hardware dispatch
+     queue for each CPU node in the system.
index 274752f8bdf963b0f1757f2df446f6c5a503c6a5..719320b5ed3f36f476bd019781b774c3b4b8ace6 100644 (file)
@@ -266,10 +266,12 @@ E.g.
 Invalidation is removing an entry from the cache without writing it
 back.  Cache blocks can be invalidated via the invalidate_cblocks
 message, which takes an arbitrary number of cblock ranges.  Each cblock
-must be expressed as a decimal value, in the future a variant message
-that takes cblock ranges expressed in hexidecimal may be needed to
-better support efficient invalidation of larger caches.  The cache must
-be in passthrough mode when invalidate_cblocks is used.
+range's end value is "one past the end", meaning 5-10 expresses a range
+of values from 5 to 9.  Each cblock must be expressed as a decimal
+value, in the future a variant message that takes cblock ranges
+expressed in hexidecimal may be needed to better support efficient
+invalidation of larger caches.  The cache must be in passthrough mode
+when invalidate_cblocks is used.
 
    invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
 
index 1a5a42ce21bb0ac7480b07ca9aced96914c33910..83f405bde138a35f824f19ad27873982f8bc0325 100644 (file)
@@ -7,10 +7,18 @@ The MPU contain CPUs, GIC, L2 cache and a local PRCM.
 Required properties:
 - compatible : Should be "ti,omap3-mpu" for OMAP3
                Should be "ti,omap4-mpu" for OMAP4
+              Should be "ti,omap5-mpu" for OMAP5
 - ti,hwmods: "mpu"
 
 Examples:
 
+- For an OMAP5 SMP system:
+
+mpu {
+    compatible = "ti,omap5-mpu";
+    ti,hwmods = "mpu"
+};
+
 - For an OMAP4 SMP system:
 
 mpu {
index 343781b9f246773ce880f9427623ebbd12202f32..3e1e498fea96b357ff990f6fbb682dd43f5254cc 100644 (file)
@@ -7,6 +7,7 @@ representation in the device tree should be done as under:-
 Required properties:
 
 - compatible : should be one of
+       "arm,armv8-pmuv3"
        "arm,cortex-a15-pmu"
        "arm,cortex-a9-pmu"
        "arm,cortex-a8-pmu"
index 47ada1dff2165bfb836600e606adfd79ac7eca3a..5d49f2b37f68dfbd0f63e7e930c3a00b0ad5ac74 100644 (file)
@@ -49,7 +49,7 @@ adc@12D10000 {
        /* NTC thermistor is a hwmon device */
        ncp15wb473@0 {
                compatible = "ntc,ncp15wb473";
-               pullup-uV = <1800000>;
+               pullup-uv = <1800000>;
                pullup-ohm = <47000>;
                pulldown-ohm = <0>;
                io-channels = <&adc 4>;
index c6bf8a6c8f52856b95af14e1e85134a246c1a44b..a2ac2d9ac71a7d0e4566dbc872dc5d4bb771407b 100644 (file)
@@ -6,7 +6,7 @@ SoC's in the Exynos4 family.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
   - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
 
index 24765c146e31d52ea4c732812c420ccdb5d3e670..46f5c791ea0df6e94e2ea6bd8ef26436231f8ebe 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5250 SoC.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
 
 - reg: physical base address of the controller and length of memory mapped
index 32aa34ecad364f6d3d0c613c471ec5752096b6ba..458f34789e5d1aa6c6b6944d37f5dad4cfc22cf9 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5420 SoC.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos5420-clock" - controller compatible with Exynos5420 SoC.
 
 - reg: physical base address of the controller and length of memory mapped
index 4499e9966bc9727db13c46d1976db830690625a2..9955dc9c7d969f5cb0888dc8a6c352dc037d81cf 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5440 SoC.
 
 Required Properties:
 
-- comptible: should be "samsung,exynos5440-clock".
+- compatible: should be "samsung,exynos5440-clock".
 
 - reg: physical base address of the controller and length of memory mapped
   region.
index b0019eb5330ee8bdd0ee825255f1a26f13039980..798cfc9d3839c9a24405419a35c935e370a51967 100644 (file)
@@ -5,16 +5,42 @@ This is for the non-QE/CPM/GUTs GPIO controllers as found on
 
 Every GPIO controller node must have #gpio-cells property defined,
 this information will be used to translate gpio-specifiers.
+See bindings/gpio/gpio.txt for details of how to specify GPIO
+information for devices.
+
+The GPIO module usually is connected to the SoC's internal interrupt
+controller, see bindings/interrupt-controller/interrupts.txt (the
+interrupt client nodes section) for details how to specify this GPIO
+module's interrupt.
+
+The GPIO module may serve as another interrupt controller (cascaded to
+the SoC's internal interrupt controller).  See the interrupt controller
+nodes section in bindings/interrupt-controller/interrupts.txt for
+details.
 
 Required properties:
-- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
-  83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
- - interrupts : Interrupt mapping for GPIO IRQ.
- - interrupt-parent : Phandle for the interrupt controller that
-   services interrupts for this device.
-- gpio-controller : Marks the port as GPIO controller.
+- compatible:          "fsl,<chip>-gpio" followed by "fsl,mpc8349-gpio"
+                       for 83xx, "fsl,mpc8572-gpio" for 85xx, or
+                       "fsl,mpc8610-gpio" for 86xx.
+- #gpio-cells:         Should be two. The first cell is the pin number
+                       and the second cell is used to specify optional
+                       parameters (currently unused).
+- interrupt-parent:    Phandle for the interrupt controller that
+                       services interrupts for this device.
+- interrupts:          Interrupt mapping for GPIO IRQ.
+- gpio-controller:     Marks the port as GPIO controller.
+
+Optional properties:
+- interrupt-controller:        Empty boolean property which marks the GPIO
+                       module as an IRQ controller.
+- #interrupt-cells:    Should be two.  Defines the number of integer
+                       cells required to specify an interrupt within
+                       this interrupt controller.  The first cell
+                       defines the pin number, the second cell
+                       defines additional flags (trigger type,
+                       trigger polarity).  Note that the available
+                       set of trigger conditions supported by the
+                       GPIO module depends on the actual SoC.
 
 Example of gpio-controller nodes for a MPC8347 SoC:
 
@@ -22,39 +48,27 @@ Example of gpio-controller nodes for a MPC8347 SoC:
                #gpio-cells = <2>;
                compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
                reg = <0xc00 0x100>;
-               interrupts = <74 0x8>;
                interrupt-parent = <&ipic>;
+               interrupts = <74 0x8>;
                gpio-controller;
+               interrupt-controller;
+               #interrupt-cells = <2>;
        };
 
        gpio2: gpio-controller@d00 {
                #gpio-cells = <2>;
                compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
                reg = <0xd00 0x100>;
-               interrupts = <75 0x8>;
                interrupt-parent = <&ipic>;
+               interrupts = <75 0x8>;
                gpio-controller;
        };
 
-See booting-without-of.txt for details of how to specify GPIO
-information for devices.
-
-To use GPIO pins as interrupt sources for peripherals, specify the
-GPIO controller as the interrupt parent and define GPIO number +
-trigger mode using the interrupts property, which is defined like
-this:
-
-interrupts = <number trigger>, where:
- - number: GPIO pin (0..31)
- - trigger: trigger mode:
-       2 = trigger on falling edge
-       3 = trigger on both edges
-
-Example of device using this is:
+Example of a peripheral using the GPIO module as an IRQ controller:
 
        funkyfpga@0 {
                compatible = "funky-fpga";
                ...
-               interrupts = <4 3>;
                interrupt-parent = <&gpio1>;
+               interrupts = <4 3>;
        };
index 56564aa4b444addcf9b770bfd4dbe6476f2b3d4d..7e49839d41249ca5168b0de1ea02781a2798486d 100644 (file)
@@ -1,7 +1,8 @@
 I2C for OMAP platforms
 
 Required properties :
-- compatible : Must be "ti,omap3-i2c" or "ti,omap4-i2c"
+- compatible : Must be "ti,omap2420-i2c", "ti,omap2430-i2c", "ti,omap3-i2c"
+  or "ti,omap4-i2c"
 - ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
 - #address-cells = <1>;
 - #size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap.txt b/Documentation/devicetree/bindings/mmc/ti-omap.txt
new file mode 100644 (file)
index 0000000..8de5799
--- /dev/null
@@ -0,0 +1,54 @@
+* TI MMC host controller for OMAP1 and 2420
+
+The MMC Host Controller on TI OMAP1 and 2420 family provides
+an interface for MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap mmc driver.
+
+Note that this driver will not work with omap2430 or later omaps,
+please see the omap hsmmc driver for the current omaps.
+
+Required properties:
+- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
+- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
+  instance starting 1
+
+Examples:
+
+       msdi1: mmc@4809c000 {
+               compatible = "ti,omap2420-mmc";
+               ti,hwmods = "msdi1";
+               reg = <0x4809c000 0x80>;
+               interrupts = <83>;
+               dmas = <&sdma 61 &sdma 62>;
+               dma-names = "tx", "rx";
+       };
+
+* TI MMC host controller for OMAP1 and 2420
+
+The MMC Host Controller on TI OMAP1 and 2420 family provides
+an interface for MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap mmc driver.
+
+Note that this driver will not work with omap2430 or later omaps,
+please see the omap hsmmc driver for the current omaps.
+
+Required properties:
+- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
+- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
+  instance starting 1
+
+Examples:
+
+       msdi1: mmc@4809c000 {
+               compatible = "ti,omap2420-mmc";
+               ti,hwmods = "msdi1";
+               reg = <0x4809c000 0x80>;
+               interrupts = <83>;
+               dmas = <&sdma 61 &sdma 62>;
+               dma-names = "tx", "rx";
+       };
+
index 48b259e29e873f71f3ccfd0a6877bffa609ebd39..bad381faf036e936d9d99a6baff5d1e053cc2cdd 100644 (file)
@@ -4,7 +4,7 @@ This file provides information, what the device node
 for the davinci_emac interface contains.
 
 Required properties:
-- compatible: "ti,davinci-dm6467-emac";
+- compatible: "ti,davinci-dm6467-emac" or "ti,am3517-emac"
 - reg: Offset and length of the register set for the device
 - ti,davinci-ctrl-reg-offset: offset to control register
 - ti,davinci-ctrl-mod-reg-offset: offset to control module register
index d5363922140322913e171fac6c98f7df2d0b0665..845ff848d8950b546e7243fbc9568847ed2f87ab 100644 (file)
@@ -15,6 +15,7 @@ Optional properties:
   only if property "phy-reset-gpios" is available.  Missing the property
   will have the duration be 1 millisecond.  Numbers greater than 1000 are
   invalid and 1 millisecond will be used instead.
+- phy-supply: regulator that powers the Ethernet PHY.
 
 Example:
 
@@ -25,4 +26,5 @@ ethernet@83fec000 {
        phy-mode = "mii";
        phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
        local-mac-address = [00 04 9F 01 1B B9];
+       phy-supply = <&reg_fec_supply>;
 };
index 953049b4248a71f4c242d56432730e5ae4c7fbc3..5a41a8658daa12087678a7d81f5f60038cbeddf8 100644 (file)
@@ -8,3 +8,7 @@ Required properties:
 Optional properties:
 - phy-device : phandle to Ethernet phy
 - local-mac-address : Ethernet mac address to use
+- reg-io-width : Mask of sizes (in bytes) of the IO accesses that
+  are supported on the device.  Valid value for SMSC LAN91c111 are
+  1, 2 or 4.  If it's omitted or invalid, the size would be 2 meaning
+  16-bit access only.
diff --git a/Documentation/devicetree/bindings/rng/qcom,prng.txt b/Documentation/devicetree/bindings/rng/qcom,prng.txt
new file mode 100644 (file)
index 0000000..8e5853c
--- /dev/null
@@ -0,0 +1,17 @@
+Qualcomm MSM pseudo random number generator.
+
+Required properties:
+
+- compatible  : should be "qcom,prng"
+- reg         : specifies base physical address and size of the registers map
+- clocks      : phandle to clock-controller plus clock-specifier pair
+- clock-names : "core" clocks all registers, FIFO and circuits in PRNG IP block
+
+Example:
+
+       rng@f9bff000 {
+               compatible = "qcom,prng";
+               reg = <0xf9bff000 0x200>;
+               clocks = <&clock GCC_PRNG_AHB_CLK>;
+               clock-names = "core";
+       };
diff --git a/Documentation/devicetree/bindings/sound/adi,axi-i2s.txt b/Documentation/devicetree/bindings/sound/adi,axi-i2s.txt
new file mode 100644 (file)
index 0000000..5875ca4
--- /dev/null
@@ -0,0 +1,31 @@
+ADI AXI-I2S controller
+
+Required properties:
+ - compatible : Must be "adi,axi-i2s-1.00.a"
+ - reg : Must contain I2S core's registers location and length
+ - clocks : Pairs of phandle and specifier referencing the controller's clocks.
+   The controller expects two clocks, the clock used for the AXI interface and
+   the clock used as the sampling rate reference clock sample.
+ - clock-names : "axi" for the clock to the AXI interface, "ref" for the sample
+   rate reference clock.
+ - dmas: Pairs of phandle and specifier for the DMA channels that are used by
+   the core. The core expects two dma channels, one for transmit and one for
+   receive.
+ - dma-names : "tx" for the transmit channel, "rx" for the receive channel.
+
+For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
+please check:
+       * resource-names.txt
+       * clock/clock-bindings.txt
+       * dma/dma.txt
+
+Example:
+
+       i2s: i2s@0x77600000 {
+               compatible = "adi,axi-i2s-1.00.a";
+               reg = <0x77600000 0x1000>;
+               clocks = <&clk 15>, <&audio_clock>;
+               clock-names = "axi", "ref";
+               dmas = <&ps7_dma 0>, <&ps7_dma 1>;
+               dma-names = "tx", "rx";
+       };
diff --git a/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt b/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt
new file mode 100644 (file)
index 0000000..46f3449
--- /dev/null
@@ -0,0 +1,30 @@
+ADI AXI-SPDIF controller
+
+Required properties:
+ - compatible : Must be "adi,axi-spdif-1.00.a"
+ - reg : Must contain SPDIF core's registers location and length
+ - clocks : Pairs of phandle and specifier referencing the controller's clocks.
+   The controller expects two clocks, the clock used for the AXI interface and
+   the clock used as the sampling rate reference clock sample.
+ - clock-names: "axi" for the clock to the AXI interface, "ref" for the sample
+   rate reference clock.
+ - dmas: Pairs of phandle and specifier for the DMA channel that is used by
+   the core. The core expects one dma channel for transmit.
+ - dma-names : Must be "tx"
+
+For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
+please check:
+       * resource-names.txt
+       * clock/clock-bindings.txt
+       * dma/dma.txt
+
+Example:
+
+       spdif: spdif@0x77400000 {
+               compatible = "adi,axi-spdif-tx-1.00.a";
+               reg = <0x77600000 0x1000>;
+               clocks = <&clk 15>, <&audio_clock>;
+               clock-names = "axi", "ref";
+               dmas = <&ps7_dma 0>;
+               dma-names = "tx";
+       };
diff --git a/Documentation/devicetree/bindings/sound/cs42l52.txt b/Documentation/devicetree/bindings/sound/cs42l52.txt
new file mode 100644 (file)
index 0000000..bc03c93
--- /dev/null
@@ -0,0 +1,46 @@
+CS42L52 audio CODEC
+
+Required properties:
+
+  - compatible : "cirrus,cs42l52"
+
+  - reg : the I2C address of the device for I2C
+
+Optional properties:
+
+  - cirrus,reset-gpio : GPIO controller's phandle and the number
+  of the GPIO used to reset the codec.
+
+  - cirrus,chgfreq-divisor : Values used to set the Charge Pump Frequency.
+  Allowable values of 0x00 through 0x0F. These are raw values written to the
+  register, not the actual frequency. The frequency is determined by the following.
+  Frequency = (64xFs)/(N+2)
+  N = chgfreq_val
+  Fs = Sample Rate (variable)
+
+  - cirrus,mica-differential-cfg : boolean, If present, then the MICA input is configured
+  as a differential input. If not present then the MICA input is configured as
+  Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
+
+  - cirrus,micb-differential-cfg : boolean, If present, then the MICB input is configured
+  as a differential input. If not present then the MICB input is configured as
+  Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
+
+  - cirrus,micbias-lvl: Set the output voltage level on the MICBIAS Pin
+  0 = 0.5 x VA
+  1 = 0.6 x VA
+  2 = 0.7 x VA
+  3 = 0.8 x VA
+  4 = 0.83 x VA
+  5 = 0.91 x VA
+
+Example:
+
+codec: codec@4a {
+       compatible = "cirrus,cs42l52";
+       reg = <0x4a>;
+       reset-gpio = <&gpio 10 0>;
+       cirrus,chgfreq-divisor = <0x05>;
+       cirrus.mica-differential-cfg;
+       cirrus,micbias-lvl = <5>;
+};
index ed785b3f67beacb6973ff1758b1b0d5b9b5f16dd..569b26c4a81ee25e1f141329f90903dcb28ab4e4 100644 (file)
@@ -4,7 +4,8 @@ Required properties:
 - compatible :
        "ti,dm646x-mcasp-audio" : for DM646x platforms
        "ti,da830-mcasp-audio"  : for both DA830 & DA850 platforms
-       "ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, TI81xx)
+       "ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
+       "ti,dra7-mcasp-audio"   : for DRA7xx platforms
 
 - reg : Should contain reg specifiers for the entries in the reg-names property.
 - reg-names : Should contain:
@@ -36,7 +37,8 @@ Optional properties:
 - pinctrl-0: Should specify pin control group used for this controller.
 - pinctrl-names: Should contain only one value - "default", for more details
                 please refer to pinctrl-bindings.txt
-  
+- fck_parent : Should contain a valid clock name which will be used as parent
+              for the McASP fck
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt
new file mode 100644 (file)
index 0000000..d7b99fa
--- /dev/null
@@ -0,0 +1,50 @@
+Freescale Enhanced Serial Audio Interface (ESAI) Controller
+
+The Enhanced Serial Audio Interface (ESAI) provides a full-duplex serial port
+for serial communication with a variety of serial devices, including industry
+standard codecs, Sony/Phillips Digital Interface (S/PDIF) transceivers, and
+other DSPs. It has up to six transmitters and four receivers.
+
+Required properties:
+
+  - compatible : Compatible list, must contain "fsl,imx35-esai".
+
+  - reg : Offset and length of the register set for the device.
+
+  - interrupts : Contains the spdif interrupt.
+
+  - dmas : Generic dma devicetree binding as described in
+  Documentation/devicetree/bindings/dma/dma.txt.
+
+  - dma-names : Two dmas have to be defined, "tx" and "rx".
+
+  - clocks: Contains an entry for each entry in clock-names.
+
+  - clock-names : Includes the following entries:
+       "core"          The core clock used to access registers
+       "extal"         The esai baud clock for esai controller used to derive
+                       HCK, SCK and FS.
+       "fsys"          The system clock derived from ahb clock used to derive
+                       HCK, SCK and FS.
+
+  - fsl,fifo-depth: The number of elements in the transmit and receive FIFOs.
+    This number is the maximum allowed value for TFCR[TFWM] or RFCR[RFWM].
+
+  - fsl,esai-synchronous: This is a boolean property. If present, indicating
+    that ESAI would work in the synchronous mode, which means all the settings
+    for Receiving would be duplicated from Transmition related registers.
+
+Example:
+
+esai: esai@02024000 {
+       compatible = "fsl,imx35-esai";
+       reg = <0x02024000 0x4000>;
+       interrupts = <0 51 0x04>;
+       clocks = <&clks 208>, <&clks 118>, <&clks 208>;
+       clock-names = "core", "extal", "fsys";
+       dmas = <&sdma 23 21 0>, <&sdma 24 21 0>;
+       dma-names = "rx", "tx";
+       fsl,fifo-depth = <128>;
+       fsl,esai-synchronous;
+       status = "disabled";
+};
index 4303b6ab6208e0856f81bc2fbc0ab8c4e81f519c..b93e9a91e30e2a5fc35e28dba0c5282d2e2c7a0e 100644 (file)
@@ -4,7 +4,12 @@ The SSI is a serial device that communicates with audio codecs.  It can
 be programmed in AC97, I2S, left-justified, or right-justified modes.
 
 Required properties:
-- compatible:       Compatible list, contains "fsl,ssi".
+- compatible:       Compatible list, should contain one of the following
+                    compatibles:
+                      fsl,mpc8610-ssi
+                      fsl,imx51-ssi
+                      fsl,imx35-ssi
+                      fsl,imx21-ssi
 - cell-index:       The SSI, <0> = SSI1, <1> = SSI2, and so on.
 - reg:              Offset and length of the register set for the device.
 - interrupts:       <a b> where a is the interrupt number and b is a
diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt
new file mode 100644 (file)
index 0000000..98611a6
--- /dev/null
@@ -0,0 +1,40 @@
+Freescale Synchronous Audio Interface (SAI).
+
+The SAI is based on I2S module that used communicating with audio codecs,
+which provides a synchronous audio interface that supports fullduplex
+serial interfaces with frame synchronization such as I2S, AC97, TDM, and
+codec/DSP interfaces.
+
+
+Required properties:
+- compatible: Compatible list, contains "fsl,vf610-sai".
+- reg: Offset and length of the register set for the device.
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names : Must include the "sai" entry.
+- dmas : Generic dma devicetree binding as described in
+  Documentation/devicetree/bindings/dma/dma.txt.
+- dma-names : Two dmas have to be defined, "tx" and "rx".
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+  See ../pinctrl/pinctrl-bindings.txt for details of the property values.
+- big-endian-regs: If this property is absent, the little endian mode will
+  be in use as default, or the big endian mode will be in use for all the
+  device registers.
+- big-endian-data: If this property is absent, the little endian mode will
+  be in use as default, or the big endian mode will be in use for all the
+  fifo data.
+
+Example:
+sai2: sai@40031000 {
+             compatible = "fsl,vf610-sai";
+             reg = <0x40031000 0x1000>;
+             pinctrl-names = "default";
+             pinctrl-0 = <&pinctrl_sai2_1>;
+             clocks = <&clks VF610_CLK_SAI2>;
+             clock-names = "sai";
+             dma-names = "tx", "rx";
+             dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
+                  <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
+             big-endian-regs;
+             big-endian-data;
+};
diff --git a/Documentation/devicetree/bindings/sound/hdmi.txt b/Documentation/devicetree/bindings/sound/hdmi.txt
new file mode 100644 (file)
index 0000000..31af7bc
--- /dev/null
@@ -0,0 +1,17 @@
+Device-Tree bindings for dummy HDMI codec
+
+Required properties:
+       - compatible: should be "linux,hdmi-audio".
+
+CODEC output pins:
+  * TX
+
+CODEC input pins:
+  * RX
+
+Example node:
+
+       hdmi_audio: hdmi_audio@0 {
+               compatible = "linux,hdmi-audio";
+               status = "okay";
+       };
diff --git a/Documentation/devicetree/bindings/sound/max98090.txt b/Documentation/devicetree/bindings/sound/max98090.txt
new file mode 100644 (file)
index 0000000..e4c8b36
--- /dev/null
@@ -0,0 +1,43 @@
+MAX98090 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : "maxim,max98090".
+
+- reg : The I2C address of the device.
+
+- interrupts : The CODEC's interrupt output.
+
+Pins on the device (for linking into audio routes):
+
+  * MIC1
+  * MIC2
+  * DMICL
+  * DMICR
+  * IN1
+  * IN2
+  * IN3
+  * IN4
+  * IN5
+  * IN6
+  * IN12
+  * IN34
+  * IN56
+  * HPL
+  * HPR
+  * SPKL
+  * SPKR
+  * RCVL
+  * RCVR
+  * MICBIAS
+
+Example:
+
+audio-codec@10 {
+       compatible = "maxim,max98090";
+       reg = <0x10>;
+       interrupt-parent = <&gpio>;
+       interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt
new file mode 100644 (file)
index 0000000..9c7c55c
--- /dev/null
@@ -0,0 +1,51 @@
+NVIDIA Tegra audio complex, with MAX98090 CODEC
+
+Required properties:
+- compatible : "nvidia,tegra-audio-max98090"
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the MAX98090's pins (as documented in its binding), and the jacks
+  on the board:
+
+  * Headphones
+  * Speakers
+  * Mic Jack
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
+  connected to the CODEC.
+- nvidia,audio-codec : The phandle of the MAX98090 audio codec.
+
+Optional properties:
+- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
+
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-max98090-venice2",
+                    "nvidia,tegra-audio-max98090";
+       nvidia,model = "NVIDIA Tegra Venice2";
+
+       nvidia,audio-routing =
+               "Headphones", "HPR",
+               "Headphones", "HPL",
+               "Speakers", "SPKR",
+               "Speakers", "SPKL",
+               "Mic Jack", "MICBIAS",
+               "IN34", "Mic Jack";
+
+       nvidia,i2s-controller = <&tegra_i2s1>;
+       nvidia,audio-codec = <&acodec>;
+
+       clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
+                <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
+                <&tegra_car TEGRA124_CLK_EXTERN1>;
+       clock-names = "pll_a", "pll_a_out0", "mclk";
+};
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt
new file mode 100644 (file)
index 0000000..e9e20ec
--- /dev/null
@@ -0,0 +1,77 @@
+Simple-Card:
+
+Simple-Card specifies audio DAI connection of SoC <-> codec.
+
+Required properties:
+
+- compatible                           : "simple-audio-card"
+
+Optional properties:
+
+- simple-audio-card,format             : CPU/CODEC common audio format.
+                                         "i2s", "right_j", "left_j" , "dsp_a"
+                                         "dsp_b", "ac97", "pdm", "msb", "lsb"
+- simple-audio-card,routing            : A list of the connections between audio components.
+                                         Each entry is a pair of strings, the first being the
+                                         connection's sink, the second being the connection's
+                                         source.
+
+Required subnodes:
+
+- simple-audio-card,cpu                        : CPU   sub-node
+- simple-audio-card,codec              : CODEC sub-node
+
+Required CPU/CODEC subnodes properties:
+
+- sound-dai                            : phandle and port of CPU/CODEC
+
+Optional CPU/CODEC subnodes properties:
+
+- format                               : CPU/CODEC specific audio format if needed.
+                                         see simple-audio-card,format
+- frame-master                         : bool property. add this if subnode is frame master
+- bitclock-master                      : bool property. add this if subnode is bitclock master
+- bitclock-inversion                   : bool property. add this if subnode has clock inversion
+- frame-inversion                      : bool property. add this if subnode has frame inversion
+- clocks / system-clock-frequency      : specify subnode's clock if needed.
+                                         it can be specified via "clocks" if system has
+                                         clock node (= common clock), or "system-clock-frequency"
+                                         (if system doens't support common clock)
+
+Example:
+
+sound {
+       compatible = "simple-audio-card";
+       simple-audio-card,format = "left_j";
+       simple-audio-routing =
+               "MIC_IN", "Mic Jack",
+               "Headphone Jack", "HP_OUT",
+               "Ext Spk", "LINE_OUT";
+
+       simple-audio-card,cpu {
+               sound-dai = <&sh_fsi2 0>;
+       };
+
+       simple-audio-card,codec {
+               sound-dai = <&ak4648>;
+               bitclock-master;
+               frame-master;
+               clocks = <&osc>;
+       };
+};
+
+&i2c0 {
+       ak4648: ak4648@12 {
+               #sound-dai-cells = <0>;
+               compatible = "asahi-kasei,ak4648";
+               reg = <0x12>;
+       };
+};
+
+sh_fsi2: sh_fsi2@ec230000 {
+       #sound-dai-cells = <1>;
+       compatible = "renesas,sh_fsi2";
+       reg = <0xec230000 0x400>;
+       interrupt-parent = <&gic>;
+       interrupts = <0 146 0x4>;
+};
index 5e6040c2c2e9c34019dceb93e439504e4e5af9ad..9d8ea14db49011cd95bb86d102461ece9abeca2d 100644 (file)
@@ -6,6 +6,7 @@ Required properties:
 
 - compatible - "string" - One of:
     "ti,tlv320aic3x" - Generic TLV320AIC3x device
+    "ti,tlv320aic32x4" - TLV320AIC32x4
     "ti,tlv320aic33" - TLV320AIC33
     "ti,tlv320aic3007" - TLV320AIC3007
     "ti,tlv320aic3106" - TLV320AIC3106
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt
deleted file mode 100644 (file)
index 6b9e518..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-NVIDIA Tegra 2 SPI device
-
-Required properties:
-- compatible : should be "nvidia,tegra20-spi".
-- gpios : should specify GPIOs used for chipselect.
index ce95ed1c6d3e26578eaca876aa0f7caf26fa101d..edbb8d88c85e90e3e1760ef3d6f25e98d96e3e37 100644 (file)
@@ -32,12 +32,14 @@ est ESTeem Wireless Modems
 fsl    Freescale Semiconductor
 GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+gmt    Global Mixed-mode Technology, Inc.
 hisilicon      Hisilicon Limited.
 hp     Hewlett Packard
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
 img    Imagination Technologies Ltd.
 intercontrol   Inter Control Group
+lg     LG Corporation
 linux  Linux-specific binding
 lsi    LSI Corp. (LSI Logic)
 marvell        Marvell Technology Group Ltd.
diff --git a/Documentation/gpio/00-INDEX b/Documentation/gpio/00-INDEX
new file mode 100644 (file)
index 0000000..1de43ae
--- /dev/null
@@ -0,0 +1,14 @@
+00-INDEX
+       - This file
+gpio.txt
+       - Introduction to GPIOs and their kernel interfaces
+consumer.txt
+       - How to obtain and use GPIOs in a driver
+driver.txt
+       - How to write a GPIO driver
+board.txt
+       - How to assign GPIOs to a consumer device and a function
+sysfs.txt
+       - Information about the GPIO sysfs interface
+gpio-legacy.txt
+       - Historical documentation of the deprecated GPIO integer interface
diff --git a/Documentation/gpio/board.txt b/Documentation/gpio/board.txt
new file mode 100644 (file)
index 0000000..0d03506
--- /dev/null
@@ -0,0 +1,115 @@
+GPIO Mappings
+=============
+
+This document explains how GPIOs can be assigned to given devices and functions.
+Note that it only applies to the new descriptor-based interface. For a
+description of the deprecated integer-based GPIO interface please refer to
+gpio-legacy.txt (actually, there is no real mapping possible with the old
+interface; you just fetch an integer from somewhere and request the
+corresponding GPIO.
+
+Platforms that make use of GPIOs must select ARCH_REQUIRE_GPIOLIB (if GPIO usage
+is mandatory) or ARCH_WANT_OPTIONAL_GPIOLIB (if GPIO support can be omitted) in
+their Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
+describe its hardware layout. Currently, mappings can be defined through device
+tree, ACPI, and platform data.
+
+Device Tree
+-----------
+GPIOs can easily be mapped to devices and functions in the device tree. The
+exact way to do it depends on the GPIO controller providing the GPIOs, see the
+device tree bindings for your controller.
+
+GPIOs mappings are defined in the consumer device's node, in a property named
+<function>-gpios, where <function> is the function the driver will request
+through gpiod_get(). For example:
+
+       foo_device {
+               compatible = "acme,foo";
+               ...
+               led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
+                           <&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
+                           <&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
+
+               power-gpio = <&gpio 1 GPIO_ACTIVE_LOW>;
+       };
+
+This property will make GPIOs 15, 16 and 17 available to the driver under the
+"led" function, and GPIO 1 as the "power" GPIO:
+
+       struct gpio_desc *red, *green, *blue, *power;
+
+       red = gpiod_get_index(dev, "led", 0);
+       green = gpiod_get_index(dev, "led", 1);
+       blue = gpiod_get_index(dev, "led", 2);
+
+       power = gpiod_get(dev, "power");
+
+The led GPIOs will be active-high, while the power GPIO will be active-low (i.e.
+gpiod_is_active_low(power) will be true).
+
+ACPI
+----
+ACPI does not support function names for GPIOs. Therefore, only the "idx"
+argument of gpiod_get_index() is useful to discriminate between GPIOs assigned
+to a device. The "con_id" argument can still be set for debugging purposes (it
+will appear under error messages as well as debug and sysfs nodes).
+
+Platform Data
+-------------
+Finally, GPIOs can be bound to devices and functions using platform data. Board
+files that desire to do so need to include the following header:
+
+       #include <linux/gpio/driver.h>
+
+GPIOs are mapped by the means of tables of lookups, containing instances of the
+gpiod_lookup structure. Two macros are defined to help declaring such mappings:
+
+       GPIO_LOOKUP(chip_label, chip_hwnum, dev_id, con_id, flags)
+       GPIO_LOOKUP_IDX(chip_label, chip_hwnum, dev_id, con_id, idx, flags)
+
+where
+
+  - chip_label is the label of the gpiod_chip instance providing the GPIO
+  - chip_hwnum is the hardware number of the GPIO within the chip
+  - dev_id is the identifier of the device that will make use of this GPIO. If
+       NULL, the GPIO will be available to all devices.
+  - con_id is the name of the GPIO function from the device point of view. It
+       can be NULL.
+  - idx is the index of the GPIO within the function.
+  - flags is defined to specify the following properties:
+       * GPIOF_ACTIVE_LOW      - to configure the GPIO as active-low
+       * GPIOF_OPEN_DRAIN      - GPIO pin is open drain type.
+       * GPIOF_OPEN_SOURCE     - GPIO pin is open source type.
+
+In the future, these flags might be extended to support more properties.
+
+Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
+
+A lookup table can then be defined as follows:
+
+       struct gpiod_lookup gpios_table[] = {
+       GPIO_LOOKUP_IDX("gpio.0", 15, "foo.0", "led", 0, GPIO_ACTIVE_HIGH),
+       GPIO_LOOKUP_IDX("gpio.0", 16, "foo.0", "led", 1, GPIO_ACTIVE_HIGH),
+       GPIO_LOOKUP_IDX("gpio.0", 17, "foo.0", "led", 2, GPIO_ACTIVE_HIGH),
+       GPIO_LOOKUP("gpio.0", 1, "foo.0", "power", GPIO_ACTIVE_LOW),
+       };
+
+And the table can be added by the board code as follows:
+
+       gpiod_add_table(gpios_table, ARRAY_SIZE(gpios_table));
+
+The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:
+
+       struct gpio_desc *red, *green, *blue, *power;
+
+       red = gpiod_get_index(dev, "led", 0);
+       green = gpiod_get_index(dev, "led", 1);
+       blue = gpiod_get_index(dev, "led", 2);
+
+       power = gpiod_get(dev, "power");
+       gpiod_direction_output(power, 1);
+
+Since the "power" GPIO is mapped as active-low, its actual signal will be 0
+after this code. Contrary to the legacy integer GPIO interface, the active-low
+property is handled during mapping and is thus transparent to GPIO consumers.
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt
new file mode 100644 (file)
index 0000000..07c74a3
--- /dev/null
@@ -0,0 +1,197 @@
+GPIO Descriptor Consumer Interface
+==================================
+
+This document describes the consumer interface of the GPIO framework. Note that
+it describes the new descriptor-based interface. For a description of the
+deprecated integer-based GPIO interface please refer to gpio-legacy.txt.
+
+
+Guidelines for GPIOs consumers
+==============================
+
+Drivers that can't work without standard GPIO calls should have Kconfig entries
+that depend on GPIOLIB. The functions that allow a driver to obtain and use
+GPIOs are available by including the following file:
+
+       #include <linux/gpio/consumer.h>
+
+All the functions that work with the descriptor-based GPIO interface are
+prefixed with gpiod_. The gpio_ prefix is used for the legacy interface. No
+other function in the kernel should use these prefixes.
+
+
+Obtaining and Disposing GPIOs
+=============================
+
+With the descriptor-based interface, GPIOs are identified with an opaque,
+non-forgeable handler that must be obtained through a call to one of the
+gpiod_get() functions. Like many other kernel subsystems, gpiod_get() takes the
+device that will use the GPIO and the function the requested GPIO is supposed to
+fulfill:
+
+       struct gpio_desc *gpiod_get(struct device *dev, const char *con_id)
+
+If a function is implemented by using several GPIOs together (e.g. a simple LED
+device that displays digits), an additional index argument can be specified:
+
+       struct gpio_desc *gpiod_get_index(struct device *dev,
+                                         const char *con_id, unsigned int idx)
+
+Both functions return either a valid GPIO descriptor, or an error code checkable
+with IS_ERR(). They will never return a NULL pointer.
+
+Device-managed variants of these functions are also defined:
+
+       struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id)
+
+       struct gpio_desc *devm_gpiod_get_index(struct device *dev,
+                                              const char *con_id,
+                                              unsigned int idx)
+
+A GPIO descriptor can be disposed of using the gpiod_put() function:
+
+       void gpiod_put(struct gpio_desc *desc)
+
+It is strictly forbidden to use a descriptor after calling this function. The
+device-managed variant is, unsurprisingly:
+
+       void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
+
+
+Using GPIOs
+===========
+
+Setting Direction
+-----------------
+The first thing a driver must do with a GPIO is setting its direction. This is
+done by invoking one of the gpiod_direction_*() functions:
+
+       int gpiod_direction_input(struct gpio_desc *desc)
+       int gpiod_direction_output(struct gpio_desc *desc, int value)
+
+The return value is zero for success, else a negative errno. It should be
+checked, since the get/set calls don't return errors and since misconfiguration
+is possible. You should normally issue these calls from a task context. However,
+for spinlock-safe GPIOs it is OK to use them before tasking is enabled, as part
+of early board setup.
+
+For output GPIOs, the value provided becomes the initial output value. This
+helps avoid signal glitching during system startup.
+
+A driver can also query the current direction of a GPIO:
+
+       int gpiod_get_direction(const struct gpio_desc *desc)
+
+This function will return either GPIOF_DIR_IN or GPIOF_DIR_OUT.
+
+Be aware that there is no default direction for GPIOs. Therefore, **using a GPIO
+without setting its direction first is illegal and will result in undefined
+behavior!**
+
+
+Spinlock-Safe GPIO Access
+-------------------------
+Most GPIO controllers can be accessed with memory read/write instructions. Those
+don't need to sleep, and can safely be done from inside hard (non-threaded) IRQ
+handlers and similar contexts.
+
+Use the following calls to access GPIOs from an atomic context:
+
+       int gpiod_get_value(const struct gpio_desc *desc);
+       void gpiod_set_value(struct gpio_desc *desc, int value);
+
+The values are boolean, zero for low, nonzero for high. When reading the value
+of an output pin, the value returned should be what's seen on the pin. That
+won't always match the specified output value, because of issues including
+open-drain signaling and output latencies.
+
+The get/set calls do not return errors because "invalid GPIO" should have been
+reported earlier from gpiod_direction_*(). However, note that not all platforms
+can read the value of output pins; those that can't should always return zero.
+Also, using these calls for GPIOs that can't safely be accessed without sleeping
+(see below) is an error.
+
+
+GPIO Access That May Sleep
+--------------------------
+Some GPIO controllers must be accessed using message based buses like I2C or
+SPI. Commands to read or write those GPIO values require waiting to get to the
+head of a queue to transmit a command and get its response. This requires
+sleeping, which can't be done from inside IRQ handlers.
+
+Platforms that support this type of GPIO distinguish them from other GPIOs by
+returning nonzero from this call:
+
+       int gpiod_cansleep(const struct gpio_desc *desc)
+
+To access such GPIOs, a different set of accessors is defined:
+
+       int gpiod_get_value_cansleep(const struct gpio_desc *desc)
+       void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
+
+Accessing such GPIOs requires a context which may sleep, for example a threaded
+IRQ handler, and those accessors must be used instead of spinlock-safe
+accessors without the cansleep() name suffix.
+
+Other than the fact that these accessors might sleep, and will work on GPIOs
+that can't be accessed from hardIRQ handlers, these calls act the same as the
+spinlock-safe calls.
+
+
+Active-low State and Raw GPIO Values
+------------------------------------
+Device drivers like to manage the logical state of a GPIO, i.e. the value their
+device will actually receive, no matter what lies between it and the GPIO line.
+In some cases, it might make sense to control the actual GPIO line value. The
+following set of calls ignore the active-low property of a GPIO and work on the
+raw line value:
+
+       int gpiod_get_raw_value(const struct gpio_desc *desc)
+       void gpiod_set_raw_value(struct gpio_desc *desc, int value)
+       int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
+       void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
+
+The active-low state of a GPIO can also be queried using the following call:
+
+       int gpiod_is_active_low(const struct gpio_desc *desc)
+
+Note that these functions should only be used with great moderation ; a driver
+should not have to care about the physical line level.
+
+GPIOs mapped to IRQs
+--------------------
+GPIO lines can quite often be used as IRQs. You can get the IRQ number
+corresponding to a given GPIO using the following call:
+
+       int gpiod_to_irq(const struct gpio_desc *desc)
+
+It will return an IRQ number, or an negative errno code if the mapping can't be
+done (most likely because that particular GPIO cannot be used as IRQ). It is an
+unchecked error to use a GPIO that wasn't set up as an input using
+gpiod_direction_input(), or to use an IRQ number that didn't originally come
+from gpiod_to_irq(). gpiod_to_irq() is not allowed to sleep.
+
+Non-error values returned from gpiod_to_irq() can be passed to request_irq() or
+free_irq(). They will often be stored into IRQ resources for platform devices,
+by the board-specific initialization code. Note that IRQ trigger options are
+part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are system wakeup
+capabilities.
+
+
+Interacting With the Legacy GPIO Subsystem
+==========================================
+Many kernel subsystems still handle GPIOs using the legacy integer-based
+interface. Although it is strongly encouraged to upgrade them to the safer
+descriptor-based API, the following two functions allow you to convert a GPIO
+descriptor into the GPIO integer namespace and vice-versa:
+
+       int desc_to_gpio(const struct gpio_desc *desc)
+       struct gpio_desc *gpio_to_desc(unsigned gpio)
+
+The GPIO number returned by desc_to_gpio() can be safely used as long as the
+GPIO descriptor has not been freed. All the same, a GPIO number passed to
+gpio_to_desc() must have been properly acquired, and usage of the returned GPIO
+descriptor is only possible after the GPIO number has been released.
+
+Freeing a GPIO obtained by one API with the other API is forbidden and an
+unchecked error.
diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
new file mode 100644 (file)
index 0000000..9da0bfa
--- /dev/null
@@ -0,0 +1,75 @@
+GPIO Descriptor Driver Interface
+================================
+
+This document serves as a guide for GPIO chip drivers writers. Note that it
+describes the new descriptor-based interface. For a description of the
+deprecated integer-based GPIO interface please refer to gpio-legacy.txt.
+
+Each GPIO controller driver needs to include the following header, which defines
+the structures used to define a GPIO driver:
+
+       #include <linux/gpio/driver.h>
+
+
+Internal Representation of GPIOs
+================================
+
+Inside a GPIO driver, individual GPIOs are identified by their hardware number,
+which is a unique number between 0 and n, n being the number of GPIOs managed by
+the chip. This number is purely internal: the hardware number of a particular
+GPIO descriptor is never made visible outside of the driver.
+
+On top of this internal number, each GPIO also need to have a global number in
+the integer GPIO namespace so that it can be used with the legacy GPIO
+interface. Each chip must thus have a "base" number (which can be automatically
+assigned), and for each GPIO the global number will be (base + hardware number).
+Although the integer representation is considered deprecated, it still has many
+users and thus needs to be maintained.
+
+So for example one platform could use numbers 32-159 for GPIOs, with a
+controller defining 128 GPIOs at a "base" of 32 ; while another platform uses
+numbers 0..63 with one set of GPIO controllers, 64-79 with another type of GPIO
+controller, and on one particular board 80-95 with an FPGA. The numbers need not
+be contiguous; either of those platforms could also use numbers 2000-2063 to
+identify GPIOs in a bank of I2C GPIO expanders.
+
+
+Controller Drivers: gpio_chip
+=============================
+
+In the gpiolib framework each GPIO controller is packaged as a "struct
+gpio_chip" (see linux/gpio/driver.h for its complete definition) with members
+common to each controller of that type:
+
+ - methods to establish GPIO direction
+ - methods used to access GPIO values
+ - method to return the IRQ number associated to a given GPIO
+ - flag saying whether calls to its methods may sleep
+ - optional debugfs dump method (showing extra state like pullup config)
+ - optional base number (will be automatically assigned if omitted)
+ - label for diagnostics and GPIOs mapping using platform data
+
+The code implementing a gpio_chip should support multiple instances of the
+controller, possibly using the driver model. That code will configure each
+gpio_chip and issue gpiochip_add(). Removing a GPIO controller should be rare;
+use gpiochip_remove() when it is unavoidable.
+
+Most often a gpio_chip is part of an instance-specific structure with state not
+exposed by the GPIO interfaces, such as addressing, power management, and more.
+Chips such as codecs will have complex non-GPIO state.
+
+Any debugfs dump method should normally ignore signals which haven't been
+requested as GPIOs. They can use gpiochip_is_requested(), which returns either
+NULL or the label associated with that GPIO when it was requested.
+
+Locking IRQ usage
+-----------------
+Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
+to mark the GPIO as being used as an IRQ:
+
+       int gpiod_lock_as_irq(struct gpio_desc *desc)
+
+This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
+is released:
+
+       void gpiod_unlock_as_irq(struct gpio_desc *desc)
diff --git a/Documentation/gpio/gpio.txt b/Documentation/gpio/gpio.txt
new file mode 100644 (file)
index 0000000..cd9b356
--- /dev/null
@@ -0,0 +1,119 @@
+GPIO Interfaces
+===============
+
+The documents in this directory give detailed instructions on how to access
+GPIOs in drivers, and how to write a driver for a device that provides GPIOs
+itself.
+
+Due to the history of GPIO interfaces in the kernel, there are two different
+ways to obtain and use GPIOs:
+
+  - The descriptor-based interface is the preferred way to manipulate GPIOs,
+and is described by all the files in this directory excepted gpio-legacy.txt.
+  - The legacy integer-based interface which is considered deprecated (but still
+usable for compatibility reasons) is documented in gpio-legacy.txt.
+
+The remainder of this document applies to the new descriptor-based interface.
+gpio-legacy.txt contains the same information applied to the legacy
+integer-based interface.
+
+
+What is a GPIO?
+===============
+
+A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
+digital signal. They are provided from many kinds of chip, and are familiar
+to Linux developers working with embedded and custom hardware. Each GPIO
+represents a bit connected to a particular pin, or "ball" on Ball Grid Array
+(BGA) packages. Board schematics show which external hardware connects to
+which GPIOs. Drivers can be written generically, so that board setup code
+passes such pin configuration data to drivers.
+
+System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
+non-dedicated pin can be configured as a GPIO; and most chips have at least
+several dozen of them. Programmable logic devices (like FPGAs) can easily
+provide GPIOs; multifunction chips like power managers, and audio codecs
+often have a few such pins to help with pin scarcity on SOCs; and there are
+also "GPIO Expander" chips that connect using the I2C or SPI serial buses.
+Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
+firmware knowing how they're used).
+
+The exact capabilities of GPIOs vary between systems. Common options:
+
+  - Output values are writable (high=1, low=0). Some chips also have
+    options about how that value is driven, so that for example only one
+    value might be driven, supporting "wire-OR" and similar schemes for the
+    other value (notably, "open drain" signaling).
+
+  - Input values are likewise readable (1, 0). Some chips support readback
+    of pins configured as "output", which is very useful in such "wire-OR"
+    cases (to support bidirectional signaling). GPIO controllers may have
+    input de-glitch/debounce logic, sometimes with software controls.
+
+  - Inputs can often be used as IRQ signals, often edge triggered but
+    sometimes level triggered. Such IRQs may be configurable as system
+    wakeup events, to wake the system from a low power state.
+
+  - Usually a GPIO will be configurable as either input or output, as needed
+    by different product boards; single direction ones exist too.
+
+  - Most GPIOs can be accessed while holding spinlocks, but those accessed
+    through a serial bus normally can't. Some systems support both types.
+
+On a given board each GPIO is used for one specific purpose like monitoring
+MMC/SD card insertion/removal, detecting card write-protect status, driving
+a LED, configuring a transceiver, bit-banging a serial bus, poking a hardware
+watchdog, sensing a switch, and so on.
+
+
+Common GPIO Properties
+======================
+
+These properties are met through all the other documents of the GPIO interface
+and it is useful to understand them, especially if you need to define GPIO
+mappings.
+
+Active-High and Active-Low
+--------------------------
+It is natural to assume that a GPIO is "active" when its output signal is 1
+("high"), and inactive when it is 0 ("low"). However in practice the signal of a
+GPIO may be inverted before is reaches its destination, or a device could decide
+to have different conventions about what "active" means. Such decisions should
+be transparent to device drivers, therefore it is possible to define a GPIO as
+being either active-high ("1" means "active", the default) or active-low ("0"
+means "active") so that drivers only need to worry about the logical signal and
+not about what happens at the line level.
+
+Open Drain and Open Source
+--------------------------
+Sometimes shared signals need to use "open drain" (where only the low signal
+level is actually driven), or "open source" (where only the high signal level is
+driven) signaling. That term applies to CMOS transistors; "open collector" is
+used for TTL. A pullup or pulldown resistor causes the high or low signal level.
+This is sometimes called a "wire-AND"; or more practically, from the negative
+logic (low=true) perspective this is a "wire-OR".
+
+One common example of an open drain signal is a shared active-low IRQ line.
+Also, bidirectional data bus signals sometimes use open drain signals.
+
+Some GPIO controllers directly support open drain and open source outputs; many
+don't. When you need open drain signaling but your hardware doesn't directly
+support it, there's a common idiom you can use to emulate it with any GPIO pin
+that can be used as either an input or an output:
+
+ LOW:  gpiod_direction_output(gpio, 0) ... this drives the signal and overrides
+       the pullup.
+
+ HIGH: gpiod_direction_input(gpio) ... this turns off the output, so the pullup
+       (or some other device) controls the signal.
+
+The same logic can be applied to emulate open source signaling, by driving the
+high signal and configuring the GPIO as input for low. This open drain/open
+source emulation can be handled transparently by the GPIO framework.
+
+If you are "driving" the signal high but gpiod_get_value(gpio) reports a low
+value (after the appropriate rise time passes), you know some other component is
+driving the shared signal low. That's not necessarily an error. As one common
+example, that's how I2C clocks are stretched:  a slave that needs a slower clock
+delays the rising edge of SCK, and the I2C master adjusts its signaling rate
+accordingly.
diff --git a/Documentation/gpio/sysfs.txt b/Documentation/gpio/sysfs.txt
new file mode 100644 (file)
index 0000000..c2c3a97
--- /dev/null
@@ -0,0 +1,155 @@
+GPIO Sysfs Interface for Userspace
+==================================
+
+Platforms which use the "gpiolib" implementors framework may choose to
+configure a sysfs user interface to GPIOs. This is different from the
+debugfs interface, since it provides control over GPIO direction and
+value instead of just showing a gpio state summary. Plus, it could be
+present on production systems without debugging support.
+
+Given appropriate hardware documentation for the system, userspace could
+know for example that GPIO #23 controls the write protect line used to
+protect boot loader segments in flash memory. System upgrade procedures
+may need to temporarily remove that protection, first importing a GPIO,
+then changing its output state, then updating the code before re-enabling
+the write protection. In normal use, GPIO #23 would never be touched,
+and the kernel would have no need to know about it.
+
+Again depending on appropriate hardware documentation, on some systems
+userspace GPIO can be used to determine system configuration data that
+standard kernels won't know about. And for some tasks, simple userspace
+GPIO drivers could be all that the system really needs.
+
+Note that standard kernel drivers exist for common "LEDs and Buttons"
+GPIO tasks:  "leds-gpio" and "gpio_keys", respectively. Use those
+instead of talking directly to the GPIOs; they integrate with kernel
+frameworks better than your userspace code could.
+
+
+Paths in Sysfs
+--------------
+There are three kinds of entry in /sys/class/gpio:
+
+   -   Control interfaces used to get userspace control over GPIOs;
+
+   -   GPIOs themselves; and
+
+   -   GPIO controllers ("gpio_chip" instances).
+
+That's in addition to standard files including the "device" symlink.
+
+The control interfaces are write-only:
+
+    /sys/class/gpio/
+
+       "export" ... Userspace may ask the kernel to export control of
+               a GPIO to userspace by writing its number to this file.
+
+               Example:  "echo 19 > export" will create a "gpio19" node
+               for GPIO #19, if that's not requested by kernel code.
+
+       "unexport" ... Reverses the effect of exporting to userspace.
+
+               Example:  "echo 19 > unexport" will remove a "gpio19"
+               node exported using the "export" file.
+
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+       "direction" ... reads as either "in" or "out". This value may
+               normally be written. Writing as "out" defaults to
+               initializing the value as low. To ensure glitch free
+               operation, values "low" and "high" may be written to
+               configure the GPIO as an output with that initial value.
+
+               Note that this attribute *will not exist* if the kernel
+               doesn't support changing the direction of a GPIO, or
+               it was exported by kernel code that didn't explicitly
+               allow userspace to reconfigure this GPIO's direction.
+
+       "value" ... reads as either 0 (low) or 1 (high). If the GPIO
+               is configured as an output, this value may be written;
+               any nonzero value is treated as high.
+
+               If the pin can be configured as interrupt-generating interrupt
+               and if it has been configured to generate interrupts (see the
+               description of "edge"), you can poll(2) on that file and
+               poll(2) will return whenever the interrupt was triggered. If
+               you use poll(2), set the events POLLPRI and POLLERR. If you
+               use select(2), set the file descriptor in exceptfds. After
+               poll(2) returns, either lseek(2) to the beginning of the sysfs
+               file and read the new value or close the file and re-open it
+               to read the value.
+
+       "edge" ... reads as either "none", "rising", "falling", or
+               "both". Write these strings to select the signal edge(s)
+               that will make poll(2) on the "value" file return.
+
+               This file exists only if the pin can be configured as an
+               interrupt generating input pin.
+
+       "active_low" ... reads as either 0 (false) or 1 (true). Write
+               any nonzero value to invert the value attribute both
+               for reading and writing. Existing and subsequent
+               poll(2) support configuration via the edge attribute
+               for "rising" and "falling" edges will follow this
+               setting.
+
+GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
+controller implementing GPIOs starting at #42) and have the following
+read-only attributes:
+
+    /sys/class/gpio/gpiochipN/
+
+       "base" ... same as N, the first GPIO managed by this chip
+
+       "label" ... provided for diagnostics (not always unique)
+
+       "ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
+
+Board documentation should in most cases cover what GPIOs are used for
+what purposes. However, those numbers are not always stable; GPIOs on
+a daughtercard might be different depending on the base board being used,
+or other cards in the stack. In such cases, you may need to use the
+gpiochip nodes (possibly in conjunction with schematics) to determine
+the correct GPIO number to use for a given signal.
+
+
+Exporting from Kernel code
+--------------------------
+Kernel code can explicitly manage exports of GPIOs which have already been
+requested using gpio_request():
+
+       /* export the GPIO to userspace */
+       int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
+
+       /* reverse gpio_export() */
+       void gpiod_unexport(struct gpio_desc *desc);
+
+       /* create a sysfs link to an exported GPIO node */
+       int gpiod_export_link(struct device *dev, const char *name,
+                     struct gpio_desc *desc);
+
+       /* change the polarity of a GPIO node in sysfs */
+       int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
+
+After a kernel driver requests a GPIO, it may only be made available in
+the sysfs interface by gpiod_export(). The driver can control whether the
+signal direction may change. This helps drivers prevent userspace code
+from accidentally clobbering important system state.
+
+This explicit exporting can help with debugging (by making some kinds
+of experiments easier), or can provide an always-there interface that's
+suitable for documenting as part of a board support package.
+
+After the GPIO has been exported, gpiod_export_link() allows creating
+symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
+use this to provide the interface under their own device in sysfs with
+a descriptive name.
+
+Drivers can use gpiod_sysfs_set_active_low() to hide GPIO line polarity
+differences between boards from user space. Polarity change can be done both
+before and after gpiod_export(), and previously enabled poll(2) support for
+either rising or falling edge will be reconfigured to follow this setting.
index 50680a59a2ff9a913e449a1d71ced9fab3004fe4..b9e9bd85429801efa537bc1ea85f773fc92099f8 100644 (file)
@@ -1529,6 +1529,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        * atapi_dmadir: Enable ATAPI DMADIR bridge support
 
+                       * disable: Disable this device.
+
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
index 0c980ad40b17be5c34a271c87c7983e112620d6b..4d17487d5ad9e5b4f10008c6b817636fcae53494 100644 (file)
@@ -313,7 +313,7 @@ static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
        int i;
        void *dp = get_dp(mic, type);
 
-       for (i = mic_aligned_size(struct mic_bootparam); i < PAGE_SIZE;
+       for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
                i += mic_total_desc_size(d)) {
                d = dp + i;
 
@@ -445,8 +445,8 @@ init_vr(struct mic_info *mic, int fd, int type,
                __func__, mic->name, vr0->va, vr0->info, vr_size,
                vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
        mpsslog("magic 0x%x expected 0x%x\n",
-               vr0->info->magic, MIC_MAGIC + type);
-       assert(vr0->info->magic == MIC_MAGIC + type);
+               le32toh(vr0->info->magic), MIC_MAGIC + type);
+       assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
        if (vr1) {
                vr1->va = (struct mic_vring *)
                        &va[MIC_DEVICE_PAGE_END + vr_size];
@@ -458,8 +458,8 @@ init_vr(struct mic_info *mic, int fd, int type,
                        __func__, mic->name, vr1->va, vr1->info, vr_size,
                        vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
                mpsslog("magic 0x%x expected 0x%x\n",
-                       vr1->info->magic, MIC_MAGIC + type + 1);
-               assert(vr1->info->magic == MIC_MAGIC + type + 1);
+                       le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
+               assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
        }
 done:
        return va;
@@ -520,7 +520,7 @@ static void *
 virtio_net(void *arg)
 {
        static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
-       static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __aligned(64);
+       static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64)));
        struct iovec vnet_iov[2][2] = {
                { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
                  { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
@@ -1412,6 +1412,12 @@ mic_config(void *arg)
        }
 
        do {
+               ret = lseek(fd, 0, SEEK_SET);
+               if (ret < 0) {
+                       mpsslog("%s: Failed to seek to file start '%s': %s\n",
+                               mic->name, pathname, strerror(errno));
+                       goto close_error1;
+               }
                ret = read(fd, value, sizeof(value));
                if (ret < 0) {
                        mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
new file mode 100644 (file)
index 0000000..2b40e04
--- /dev/null
@@ -0,0 +1,240 @@
+                       ==============================
+                       KERNEL MODULE SIGNING FACILITY
+                       ==============================
+
+CONTENTS
+
+ - Overview.
+ - Configuring module signing.
+ - Generating signing keys.
+ - Public keys in the kernel.
+ - Manually signing modules.
+ - Signed modules and stripping.
+ - Loading signed modules.
+ - Non-valid signatures and unsigned modules.
+ - Administering/protecting the private key.
+
+
+========
+OVERVIEW
+========
+
+The kernel module signing facility cryptographically signs modules during
+installation and then checks the signature upon loading the module.  This
+allows increased kernel security by disallowing the loading of unsigned modules
+or modules signed with an invalid key.  Module signing increases security by
+making it harder to load a malicious module into the kernel.  The module
+signature checking is done by the kernel so that it is not necessary to have
+trusted userspace bits.
+
+This facility uses X.509 ITU-T standard certificates to encode the public keys
+involved.  The signatures are not themselves encoded in any industrial standard
+type.  The facility currently only supports the RSA public key encryption
+standard (though it is pluggable and permits others to be used).  The possible
+hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
+SHA-512 (the algorithm is selected by data in the signature).
+
+
+==========================
+CONFIGURING MODULE SIGNING
+==========================
+
+The module signing facility is enabled by going to the "Enable Loadable Module
+Support" section of the kernel configuration and turning on
+
+       CONFIG_MODULE_SIG       "Module signature verification"
+
+This has a number of options available:
+
+ (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
+
+     This specifies how the kernel should deal with a module that has a
+     signature for which the key is not known or a module that is unsigned.
+
+     If this is off (ie. "permissive"), then modules for which the key is not
+     available and modules that are unsigned are permitted, but the kernel will
+     be marked as being tainted.
+
+     If this is on (ie. "restrictive"), only modules that have a valid
+     signature that can be verified by a public key in the kernel's possession
+     will be loaded.  All other modules will generate an error.
+
+     Irrespective of the setting here, if the module has a signature block that
+     cannot be parsed, it will be rejected out of hand.
+
+
+ (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
+
+     If this is on then modules will be automatically signed during the
+     modules_install phase of a build.  If this is off, then the modules must
+     be signed manually using:
+
+       scripts/sign-file
+
+
+ (3) "Which hash algorithm should modules be signed with?"
+
+     This presents a choice of which hash algorithm the installation phase will
+     sign the modules with:
+
+       CONFIG_SIG_SHA1         "Sign modules with SHA-1"
+       CONFIG_SIG_SHA224       "Sign modules with SHA-224"
+       CONFIG_SIG_SHA256       "Sign modules with SHA-256"
+       CONFIG_SIG_SHA384       "Sign modules with SHA-384"
+       CONFIG_SIG_SHA512       "Sign modules with SHA-512"
+
+     The algorithm selected here will also be built into the kernel (rather
+     than being a module) so that modules signed with that algorithm can have
+     their signatures checked without causing a dependency loop.
+
+
+=======================
+GENERATING SIGNING KEYS
+=======================
+
+Cryptographic keypairs are required to generate and check signatures.  A
+private key is used to generate a signature and the corresponding public key is
+used to check it.  The private key is only needed during the build, after which
+it can be deleted or stored securely.  The public key gets built into the
+kernel so that it can be used to check the signatures as the modules are
+loaded.
+
+Under normal conditions, the kernel build will automatically generate a new
+keypair using openssl if one does not exist in the files:
+
+       signing_key.priv
+       signing_key.x509
+
+during the building of vmlinux (the public part of the key needs to be built
+into vmlinux) using parameters in the:
+
+       x509.genkey
+
+file (which is also generated if it does not already exist).
+
+It is strongly recommended that you provide your own x509.genkey file.
+
+Most notably, in the x509.genkey file, the req_distinguished_name section
+should be altered from the default:
+
+       [ req_distinguished_name ]
+       O = Magrathea
+       CN = Glacier signing key
+       emailAddress = slartibartfast@magrathea.h2g2
+
+The generated RSA key size can also be set with:
+
+       [ req ]
+       default_bits = 4096
+
+
+It is also possible to manually generate the key private/public files using the
+x509.genkey key generation configuration file in the root node of the Linux
+kernel sources tree and the openssl command.  The following is an example to
+generate the public/private key files:
+
+       openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
+          -config x509.genkey -outform DER -out signing_key.x509 \
+          -keyout signing_key.priv
+
+
+=========================
+PUBLIC KEYS IN THE KERNEL
+=========================
+
+The kernel contains a ring of public keys that can be viewed by root.  They're
+in a keyring called ".system_keyring" that can be seen by:
+
+       [root@deneb ~]# cat /proc/keys
+       ...
+       223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
+       302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
+       ...
+
+Beyond the public key generated specifically for module signing, any file
+placed in the kernel source root directory or the kernel build root directory
+whose name is suffixed with ".x509" will be assumed to be an X.509 public key
+and will be added to the keyring.
+
+Further, the architecture code may take public keys from a hardware store and
+add those in also (e.g. from the UEFI key database).
+
+Finally, it is possible to add additional public keys by doing:
+
+       keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
+
+e.g.:
+
+       keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
+
+Note, however, that the kernel will only permit keys to be added to
+.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
+that is already resident in the .system_keyring at the time the key was added.
+
+
+=========================
+MANUALLY SIGNING MODULES
+=========================
+
+To manually sign a module, use the scripts/sign-file tool available in
+the Linux kernel source tree.  The script requires 4 arguments:
+
+       1.  The hash algorithm (e.g., sha256)
+       2.  The private key filename
+       3.  The public key filename
+       4.  The kernel module to be signed
+
+The following is an example to sign a kernel module:
+
+       scripts/sign-file sha512 kernel-signkey.priv \
+               kernel-signkey.x509 module.ko
+
+The hash algorithm used does not have to match the one configured, but if it
+doesn't, you should make sure that hash algorithm is either built into the
+kernel or can be loaded without requiring itself.
+
+
+============================
+SIGNED MODULES AND STRIPPING
+============================
+
+A signed module has a digital signature simply appended at the end.  The string
+"~Module signature appended~." at the end of the module's file confirms that a
+signature is present but it does not confirm that the signature is valid!
+
+Signed modules are BRITTLE as the signature is outside of the defined ELF
+container.  Thus they MAY NOT be stripped once the signature is computed and
+attached.  Note the entire module is the signed payload, including any and all
+debug information present at the time of signing.
+
+
+======================
+LOADING SIGNED MODULES
+======================
+
+Modules are loaded with insmod, modprobe, init_module() or finit_module(),
+exactly as for unsigned modules as no processing is done in userspace.  The
+signature checking is all done within the kernel.
+
+
+=========================================
+NON-VALID SIGNATURES AND UNSIGNED MODULES
+=========================================
+
+If CONFIG_MODULE_SIG_FORCE is enabled or enforcemodulesig=1 is supplied on
+the kernel command line, the kernel will only load validly signed modules
+for which it has a public key.   Otherwise, it will also load modules that are
+unsigned.   Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load.
+
+Any module that has an unparseable signature will be rejected.
+
+
+=========================================
+ADMINISTERING/PROTECTING THE PRIVATE KEY
+=========================================
+
+Since the private key is used to sign modules, viruses and malware could use
+the private key to sign modules and compromise the operating system.  The
+private key must be either destroyed or moved to a secure location and not kept
+in the root node of the kernel source tree.
index 3c12d9a7ed00391d5c3f49ef80d7b1ae9abc40fe..8a984e994e61616a9dba0a4f425a5b4371b3ae99 100644 (file)
@@ -16,8 +16,12 @@ ip_default_ttl - INTEGER
        Default: 64 (as recommended by RFC1700)
 
 ip_no_pmtu_disc - BOOLEAN
-       Disable Path MTU Discovery.
-       default FALSE
+       Disable Path MTU Discovery. If enabled and a
+       fragmentation-required ICMP is received, the PMTU to this
+       destination will be set to min_pmtu (see below). You will need
+       to raise min_pmtu to the smallest interface MTU on your system
+       manually if you want to avoid locally generated fragments.
+       Default: FALSE
 
 min_pmtu - INTEGER
        default 552 - minimum discovered Path MTU
index c01223628a87ae5e522b714c8a3a86edda15dea5..8e48e3b142275ff1500df754301d39c7f1639d71 100644 (file)
@@ -123,6 +123,16 @@ Transmission process is similar to capture as shown below.
 [shutdown]  close() --------> destruction of the transmission socket and
                               deallocation of all associated resources.
 
+Socket creation and destruction is also straight forward, and is done
+the same way as in capturing described in the previous paragraph:
+
+ int fd = socket(PF_PACKET, mode, 0);
+
+The protocol can optionally be 0 in case we only want to transmit
+via this socket, which avoids an expensive call to packet_rcv().
+In this case, you also need to bind(2) the TX_RING with sll_protocol = 0
+set. Otherwise, htons(ETH_P_ALL) or any other protocol, for example.
+
 Binding the socket to your network interface is mandatory (with zero copy) to
 know the header size of frames used in the circular buffer.
 
index 138ac88c146126b4ca602de288fee60a3c2046a7..ff88f52eec9849e254796b1c56d77a19236ea6a4 100644 (file)
@@ -49,18 +49,23 @@ features :-
   * Machine specific controls: Allow machines to add controls to the sound card
     (e.g. volume control for speaker amplifier).
 
-To achieve all this, ASoC basically splits an embedded audio system into 3
-components :-
+To achieve all this, ASoC basically splits an embedded audio system into
+multiple re-usable component drivers :-
 
-  * Codec driver: The codec driver is platform independent and contains audio
-    controls, audio interface capabilities, codec DAPM definition and codec IO
-    functions.
+  * Codec class drivers: The codec class driver is platform independent and
+    contains audio controls, audio interface capabilities, codec DAPM
+    definition and codec IO functions. This class extends to BT, FM and MODEM
+    ICs if required. Codec class drivers should be generic code that can run
+    on any architecture and machine.
 
-  * Platform driver: The platform driver contains the audio DMA engine and audio
-    interface drivers (e.g. I2S, AC97, PCM) for that platform.
+  * Platform class drivers: The platform class driver includes the audio DMA
+    engine driver, digital audio interface (DAI) drivers (e.g. I2S, AC97, PCM)
+    and any audio DSP drivers for that platform.
 
-  * Machine driver: The machine driver handles any machine specific controls and
-    audio events (e.g. turning on an amp at start of playback).
+  * Machine class driver: The machine driver class acts as the glue that
+    decribes and binds the other component drivers together to form an ALSA
+    "sound card device". It handles any machine specific controls and
+    machine level audio events (e.g. turning on an amp at start of playback).
 
 
 Documentation
@@ -84,3 +89,7 @@ machine.txt: Machine driver internals.
 pop_clicks.txt: How to minimise audio artifacts.
 
 clocking.txt: ASoC clocking for best power performance.
+
+jack.txt: ASoC jack detection.
+
+DPCM.txt: Dynamic PCM - Describes DPCM with DSP examples.
index 8285ed4676b6388502be84ddde71d1e201827ce8..d5e4ff328cc7146827ac3d02cd8df189b881abc4 100644 (file)
@@ -893,20 +893,15 @@ F:        arch/arm/include/asm/hardware/dec21285.h
 F:     arch/arm/mach-footbridge/
 
 ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
+M:     Shawn Guo <shawn.guo@linaro.org>
 M:     Sascha Hauer <kernel@pengutronix.de>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
+T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
 F:     arch/arm/mach-imx/
+F:     arch/arm/boot/dts/imx*
 F:     arch/arm/configs/imx*_defconfig
 
-ARM/FREESCALE IMX6
-M:     Shawn Guo <shawn.guo@linaro.org>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
-F:     arch/arm/mach-imx/*imx6*
-
 ARM/FREESCALE MXS ARM ARCHITECTURE
 M:     Shawn Guo <shawn.guo@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1013,6 +1008,8 @@ M:        Santosh Shilimkar <santosh.shilimkar@ti.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-keystone/
+F:     drivers/clk/keystone/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
 
 ARM/LOGICPD PXA270 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -1934,7 +1931,8 @@ S:        Maintained
 F:     drivers/gpio/gpio-bt8xx.c
 
 BTRFS FILE SYSTEM
-M:     Chris Mason <chris.mason@fusionio.com>
+M:     Chris Mason <clm@fb.com>
+M:     Josef Bacik <jbacik@fb.com>
 L:     linux-btrfs@vger.kernel.org
 W:     http://btrfs.wiki.kernel.org/
 Q:     http://patchwork.kernel.org/project/linux-btrfs/list/
@@ -2137,11 +2135,17 @@ S:      Maintained
 F:     Documentation/zh_CN/
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
-M:     Alexander Shishkin <alexander.shishkin@linux.intel.com>
+M:     Peter Chen <Peter.Chen@freescale.com>
+T:     git://github.com/hzpeterchen/linux-usb.git
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/chipidea/
 
+CHROME HARDWARE PLATFORM SUPPORT
+M:     Olof Johansson <olof@lixom.net>
+S:     Maintained
+F:     drivers/platform/chrome/
+
 CISCO VIC ETHERNET NIC DRIVER
 M:     Christian Benvenuti <benve@cisco.com>
 M:     Sujith Sankar <ssujith@cisco.com>
@@ -3759,9 +3763,11 @@ F:       include/uapi/linux/gigaset_dev.h
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
-S:     Maintained
+M:     Alexandre Courbot <gnurou@gmail.com>
 L:     linux-gpio@vger.kernel.org
-F:     Documentation/gpio.txt
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
+S:     Maintained
+F:     Documentation/gpio/
 F:     drivers/gpio/
 F:     include/linux/gpio*
 F:     include/asm-generic/gpio.h
@@ -3829,6 +3835,12 @@ T:       git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/
 
+GUID PARTITION TABLE (GPT)
+M:     Davidlohr Bueso <davidlohr@hp.com>
+L:     linux-efi@vger.kernel.org
+S:     Maintained
+F:     block/partitions/efi.*
+
 STK1160 USB VIDEO CAPTURE DRIVER
 M:     Ezequiel Garcia <elezegarcia@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -4038,12 +4050,26 @@ W:      http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:     Maintained
 F:     fs/hpfs/
 
+HSI SUBSYSTEM
+M:     Sebastian Reichel <sre@debian.org>
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-bus-hsi
+F:     drivers/hsi/
+F:     include/linux/hsi/
+F:     include/uapi/linux/hsi/
+
 HSO 3G MODEM DRIVER
 M:     Jan Dumon <j.dumon@option.com>
 W:     http://www.pharscape.org
 S:     Maintained
 F:     drivers/net/usb/hso.c
 
+HSR NETWORK PROTOCOL
+M:     Arvid Brodin <arvid.brodin@alten.se>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     net/hsr/
+
 HTCPEN TOUCHSCREEN DRIVER
 M:     Pau Oliva Fora <pof@eslack.org>
 L:     linux-input@vger.kernel.org
@@ -4450,10 +4476,8 @@ M:       Bruce Allan <bruce.w.allan@intel.com>
 M:     Carolyn Wyborny <carolyn.wyborny@intel.com>
 M:     Don Skidmore <donald.c.skidmore@intel.com>
 M:     Greg Rose <gregory.v.rose@intel.com>
-M:     Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
-M:     Tushar Dave <tushar.n.dave@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
@@ -5256,7 +5280,7 @@ S:        Maintained
 F:     Documentation/lockdep*.txt
 F:     Documentation/lockstat.txt
 F:     include/linux/lockdep.h
-F:     kernel/lockdep*
+F:     kernel/locking/
 
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
 M:     "Richard Russon (FlatCap)" <ldm@flatcap.org>
@@ -5897,12 +5921,21 @@ M:      Steffen Klassert <steffen.klassert@secunet.com>
 M:     Herbert Xu <herbert@gondor.apana.org.au>
 M:     "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
 S:     Maintained
 F:     net/xfrm/
 F:     net/key/
 F:     net/ipv4/xfrm*
+F:     net/ipv4/esp4.c
+F:     net/ipv4/ah4.c
+F:     net/ipv4/ipcomp.c
+F:     net/ipv4/ip_vti.c
 F:     net/ipv6/xfrm*
+F:     net/ipv6/esp6.c
+F:     net/ipv6/ah6.c
+F:     net/ipv6/ipcomp6.c
+F:     net/ipv6/ip6_vti.c
 F:     include/uapi/linux/xfrm.h
 F:     include/net/xfrm.h
 
@@ -5968,10 +6001,10 @@ F:      drivers/nfc/
 F:     include/linux/platform_data/pn544.h
 
 NFS, SUNRPC, AND LOCKD CLIENTS
-M:     Trond Myklebust <Trond.Myklebust@netapp.com>
+M:     Trond Myklebust <trond.myklebust@primarydata.com>
 L:     linux-nfs@vger.kernel.org
 W:     http://client.linux-nfs.org
-T:     git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
+T:     git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
 S:     Maintained
 F:     fs/lockd/
 F:     fs/nfs/
@@ -6238,8 +6271,8 @@ OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
 M:     Rob Herring <rob.herring@calxeda.com>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
-M:     Stephen Warren <swarren@wwwdotorg.org>
 M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
+M:     Kumar Gala <galak@codeaurora.org>
 L:     devicetree@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/
@@ -6449,19 +6482,52 @@ F:      drivers/pci/
 F:     include/linux/pci*
 F:     arch/x86/pci/
 
+PCI DRIVER FOR IMX6
+M:     Richard Zhu <r65037@freescale.com>
+M:     Shawn Guo <shawn.guo@linaro.org>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pci/host/*imx6*
+
+PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
+M:     Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+M:     Jason Cooper <jason@lakedaemon.net>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pci/host/*mvebu*
+
 PCI DRIVER FOR NVIDIA TEGRA
 M:     Thierry Reding <thierry.reding@gmail.com>
 L:     linux-tegra@vger.kernel.org
+L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
 F:     drivers/pci/host/pci-tegra.c
 
+PCI DRIVER FOR RENESAS R-CAR
+M:     Simon Horman <horms@verge.net.au>
+L:     linux-pci@vger.kernel.org
+L:     linux-sh@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/*rcar*
+
 PCI DRIVER FOR SAMSUNG EXYNOS
 M:     Jingoo Han <jg1.han@samsung.com>
 L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/pci/host/pci-exynos.c
 
+PCI DRIVER FOR SYNOPSIS DESIGNWARE
+M:     Mohit Kumar <mohit.kumar@st.com>
+M:     Jingoo Han <jg1.han@samsung.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/*designware*
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     linux-pcmcia@lists.infradead.org
@@ -7380,7 +7446,6 @@ S:        Maintained
 F:     kernel/sched/
 F:     include/linux/sched.h
 F:     include/uapi/linux/sched.h
-F:     kernel/wait.c
 F:     include/linux/wait.h
 
 SCORE ARCHITECTURE
@@ -9525,7 +9590,7 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Dave Chinner <dchinner@fromorbit.com>
+M:     Dave Chinner <david@fromorbit.com>
 M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
index c0c2d58e3998613572208012d90ed9164ec8d3b2..ab80be7a38bca0261b2adc49e878f00fea113dcd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc6
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
@@ -732,19 +732,15 @@ export mod_strip_cmd
 # Select initial ramdisk compression format, default is gzip(1).
 # This shall be used by the dracut(8) tool while creating an initramfs image.
 #
-INITRD_COMPRESS=gzip
-ifeq ($(CONFIG_RD_BZIP2), y)
-        INITRD_COMPRESS=bzip2
-else ifeq ($(CONFIG_RD_LZMA), y)
-        INITRD_COMPRESS=lzma
-else ifeq ($(CONFIG_RD_XZ), y)
-        INITRD_COMPRESS=xz
-else ifeq ($(CONFIG_RD_LZO), y)
-        INITRD_COMPRESS=lzo
-else ifeq ($(CONFIG_RD_LZ4), y)
-        INITRD_COMPRESS=lz4
-endif
-export INITRD_COMPRESS
+INITRD_COMPRESS-y                  := gzip
+INITRD_COMPRESS-$(CONFIG_RD_BZIP2) := bzip2
+INITRD_COMPRESS-$(CONFIG_RD_LZMA)  := lzma
+INITRD_COMPRESS-$(CONFIG_RD_XZ)    := xz
+INITRD_COMPRESS-$(CONFIG_RD_LZO)   := lzo
+INITRD_COMPRESS-$(CONFIG_RD_LZ4)   := lz4
+# do not export INITRD_COMPRESS, since we didn't actually
+# choose a sane default compression above.
+# export INITRD_COMPRESS := $(INITRD_COMPRESS-y)
 
 ifdef CONFIG_MODULE_SIG_ALL
 MODSECKEY = ./signing_key.priv
index 2ee0c9bfd0325537a5d9299649abac4992b722f5..9063ae6553ccb7a0a220b8db667ac770627addbf 100644 (file)
@@ -8,6 +8,7 @@
 
 config ARC
        def_bool y
+       select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
        # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
        select DEVTMPFS if !INITRAMFS_SOURCE=""
index 6f30484f34b78c5fa5052e68bbcbd3b4280a193f..39e58d1cdf90b7d8f84d108d8024d8974c3b800c 100644 (file)
@@ -8,6 +8,13 @@
 
 /******** no-legacy-syscalls-ABI *******/
 
+/*
+ * Non-typical guard macro to enable inclusion twice in ARCH sys.c
+ * That is how the Generic syscall wrapper generator works
+ */
+#if !defined(_UAPI_ASM_ARC_UNISTD_H) || defined(__SYSCALL)
+#define _UAPI_ASM_ARC_UNISTD_H
+
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_VFORK
@@ -32,3 +39,7 @@ __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
 /* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
 #define __NR_sysfs             (__NR_arch_specific_syscall + 3)
 __SYSCALL(__NR_sysfs, sys_sysfs)
+
+#undef __SYSCALL
+
+#endif
index e46d81f709797a868b7cc68cc81ef71277a0f070..63177e4cb66d0d3a323b3e53081d4caaf2550ac0 100644 (file)
@@ -79,9 +79,9 @@ static int arc_pmu_cache_event(u64 config)
        cache_result    = (config >> 16) & 0xff;
        if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
                return -EINVAL;
-       if (cache_type >= PERF_COUNT_HW_CACHE_OP_MAX)
+       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
                return -EINVAL;
-       if (cache_type >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                return -EINVAL;
 
        ret = arc_pmu_cache_map[cache_type][cache_op][cache_result];
index c1f1a7eee953de4378b1f74bd4907c969f96dceb..ba0e23234ecfef1663d3bfb07effacc1924b02f3 100644 (file)
@@ -723,6 +723,7 @@ config ARCH_S3C64XX
        bool "Samsung S3C64XX"
        select ARCH_HAS_CPUFREQ
        select ARCH_REQUIRE_GPIOLIB
+       select ARM_AMBA
        select ARM_VIC
        select CLKDEV_LOOKUP
        select CLKSRC_SAMSUNG_PWM
index b4f95c2bbf74696577b544fd69bd41ed94dda4a9..72a9b3fc425111ec9924fb47defeffee169672e2 100644 (file)
 / {
        model = "IGEP COM AM335x on AQUILA Expansion";
        compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
+
+       hdmi {
+               compatible = "ti,tilcdc,slave";
+               i2c = <&i2c0>;
+               pinctrl-names = "default", "off";
+               pinctrl-0 = <&nxp_hdmi_pins>;
+               pinctrl-1 = <&nxp_hdmi_off_pins>;
+               status = "okay";
+       };
+
+       leds_base {
+               pinctrl-names = "default";
+               pinctrl-0 = <&leds_base_pins>;
+
+               compatible = "gpio-leds";
+
+               led@0 {
+                       label = "base:red:user";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;   /* gpio1_21 */
+                       default-state = "off";
+               };
+
+               led@1 {
+                       label = "base:green:user";
+                       gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;    /* gpio2_0 */
+                       default-state = "off";
+               };
+       };
+};
+
+&am33xx_pinmux {
+       nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
+               pinctrl-single,pins = <
+                       0x1b0 (PIN_OUTPUT | MUX_MODE3)  /* xdma_event_intr0.clkout1 */
+                       0xa0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data0 */
+                       0xa4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data1 */
+                       0xa8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data2 */
+                       0xac (PIN_OUTPUT | MUX_MODE0)   /* lcd_data3 */
+                       0xb0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data4 */
+                       0xb4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data5 */
+                       0xb8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data6 */
+                       0xbc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data7 */
+                       0xc0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data8 */
+                       0xc4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data9 */
+                       0xc8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data10 */
+                       0xcc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data11 */
+                       0xd0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data12 */
+                       0xd4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data13 */
+                       0xd8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data14 */
+                       0xdc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data15 */
+                       0xe0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_vsync */
+                       0xe4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_hsync */
+                       0xe8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_pclk */
+                       0xec (PIN_OUTPUT | MUX_MODE0)   /* lcd_ac_bias_en */
+               >;
+       };
+       nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
+               pinctrl-single,pins = <
+                       0x1b0 (PIN_OUTPUT | MUX_MODE3)  /* xdma_event_intr0.clkout1 */
+               >;
+       };
+
+       leds_base_pins: pinmux_leds_base_pins {
+               pinctrl-single,pins = <
+                       0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a5.gpio1_21 */
+                       0x88 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_csn3.gpio2_0 */
+               >;
+       };
+};
+
+&lcdc {
+       status = "okay";
+};
+
+&i2c0 {
+       eeprom: eeprom@50 {
+               compatible = "at,24c256";
+               reg = <0x50>;
+       };
 };
index 6196244793113cfb8c0aac21dcf2259558174ed6..7063311a58d96785dd297f89b982970a59a185bb 100644 (file)
        pinctrl-0 = <&uart0_pins>;
 };
 
+&usb {
+       status = "okay";
+
+       control@44e10000 {
+               status = "okay";
+       };
+
+       usb-phy@47401300 {
+               status = "okay";
+       };
+
+       usb-phy@47401b00 {
+               status = "okay";
+       };
+
+       usb@47401000 {
+               status = "okay";
+       };
+
+       usb@47401800 {
+               status = "okay";
+               dr_mode = "host";
+       };
+
+       dma-controller@07402000  {
+               status = "okay";
+       };
+};
+
 #include "tps65910.dtsi"
 
 &tps {
index e99dfaf70052f3dd993aa93588b6e47470befee2..03fcbf0a88a8ef24565257d32be79ab75dd4aa79 100644 (file)
@@ -7,11 +7,11 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "am3517.dtsi"
 
 / {
-       model = "TI AM3517 EVM (AM3517/05)";
-       compatible = "ti,am3517-evm", "ti,omap3";
+       model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
+       compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
 
        memory {
                device_type = "memory";
diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi
new file mode 100644 (file)
index 0000000..2fbe02f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for am3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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 "omap3.dtsi"
+
+/ {
+       aliases {
+               serial3 = &uart4;
+       };
+
+       ocp {
+               am35x_otg_hs: am35x_otg_hs@5c040000 {
+                       compatible = "ti,omap3-musb";
+                       ti,hwmods = "am35x_otg_hs";
+                       status = "disabled";
+                       reg = <0x5c040000 0x1000>;
+                       interrupts = <71>;
+                       interrupt-names = "mc";
+               };
+
+               davinci_emac: ethernet@0x5c000000 {
+                       compatible = "ti,am3517-emac";
+                       ti,hwmods = "davinci_emac";
+                       status = "disabled";
+                       reg = <0x5c000000 0x30000>;
+                       interrupts = <67 68 69 70>;
+                       ti,davinci-ctrl-reg-offset = <0x10000>;
+                       ti,davinci-ctrl-mod-reg-offset = <0>;
+                       ti,davinci-ctrl-ram-offset = <0x20000>;
+                       ti,davinci-ctrl-ram-size = <0x2000>;
+                       ti,davinci-rmii-en = /bits/ 8 <1>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+               };
+
+               davinci_mdio: ethernet@0x5c030000 {
+                       compatible = "ti,davinci_mdio";
+                       ti,hwmods = "davinci_mdio";
+                       status = "disabled";
+                       reg = <0x5c030000 0x1000>;
+                       bus_freq = <1000000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               uart4: serial@4809e000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart4";
+                       status = "disabled";
+                       reg = <0x4809e000 0x400>;
+                       interrupts = <84>;
+                       dmas = <&sdma 55 &sdma 54>;
+                       dma-names = "tx", "rx";
+                       clock-frequency = <48000000>;
+               };
+       };
+};
index 90ce29dbe119e4680b6f7b9b61d177319d8251c1..08a56bcfc7248704b34ad1789418308819b3bcbf 100644 (file)
                                        spi-max-frequency = <50000000>;
                                };
                        };
+               };
 
-                       pcie-controller {
+               pcie-controller {
+                       status = "okay";
+                       /*
+                        * The two PCIe units are accessible through
+                        * both standard PCIe slots and mini-PCIe
+                        * slots on the board.
+                        */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+                       pcie@2,0 {
+                               /* Port 1, Lane 0 */
                                status = "okay";
-                               /*
-                                * The two PCIe units are accessible through
-                                * both standard PCIe slots and mini-PCIe
-                                * slots on the board.
-                                */
-                               pcie@1,0 {
-                                       /* Port 0, Lane 0 */
-                                       status = "okay";
-                               };
-                               pcie@2,0 {
-                                       /* Port 1, Lane 0 */
-                                       status = "okay";
-                               };
                        };
                };
        };
index 00d6a798c705b9b04408a8d28af70cd7b7cc6868..7f10f627ae5b72b7f560732c6e8d5bb35b943e69 100644 (file)
 
                        coherency-fabric@20200 {
                                compatible = "marvell,coherency-fabric";
-                               reg = <0x20200 0xb0>, <0x21810 0x1c>;
+                               reg = <0x20200 0xb0>, <0x21010 0x1c>;
                        };
 
                        serial@12000 {
index 3f5e6121c730a21ae2079acff268da2be20518ef..98335fb34b7ad5a11d9f40b6564bddc161431455 100644 (file)
@@ -47,7 +47,7 @@
                /*
                 * MV78230 has 2 PCIe units Gen2.0: One unit can be
                 * configured as x4 or quad x1 lanes. One unit is
-                * x4/x1.
+                * x1 only.
                 */
                pcie-controller {
                        compatible = "marvell,armada-xp-pcie";
 
                        ranges =
                               <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
-                               0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
                                0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
                                0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
                                0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+                               0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
                                0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
                                0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
                                0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
@@ -74,8 +74,8 @@
                                0x81000000 0x3 0       MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
                                0x82000000 0x4 0       MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
                                0x81000000 0x4 0       MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
-                               0x82000000 0x9 0       MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
-                               0x81000000 0x9 0       MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
+                               0x82000000 0x5 0       MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+                               0x81000000 0x5 0       MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */>;
 
                        pcie@1,0 {
                                device_type = "pci";
                                status = "disabled";
                        };
 
-                       pcie@9,0 {
+                       pcie@5,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-                               reg = <0x4800 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x2800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
-                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+                                         0x81000000 0 0 0x81000000 0x5 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 99>;
-                               marvell,pcie-port = <2>;
+                               interrupt-map = <0 0 0 0 &mpic 62>;
+                               marvell,pcie-port = <1>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 26>;
+                               clocks = <&gateclk 9>;
                                status = "disabled";
                        };
                };
index 3e9fd1353f895d6778972e95518850268ef6eb4e..66609684d41b59ef701530fd2076553ffc4e9b6b 100644 (file)
@@ -48,7 +48,7 @@
                /*
                 * MV78260 has 3 PCIe units Gen2.0: Two units can be
                 * configured as x4 or quad x1 lanes. One unit is
-                * x4/x1.
+                * x4 only.
                 */
                pcie-controller {
                        compatible = "marvell,armada-xp-pcie";
@@ -68,7 +68,9 @@
                                0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
                                0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
                                0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
-                               0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000   /* Port 3.0 registers */
+                               0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000   /* Port 1.1 registers */
+                               0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000   /* Port 1.2 registers */
+                               0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000   /* Port 1.3 registers */
                                0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
                                0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
                                0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
                                0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
                                0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
                                0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
-                               0x82000000 0x9 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
-                               0x81000000 0x9 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
-                               0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
-                               0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
+
+                               0x82000000 0x5 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+                               0x81000000 0x5 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+                               0x82000000 0x6 0     MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
+                               0x81000000 0x6 0     MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO  */
+                               0x82000000 0x7 0     MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
+                               0x81000000 0x7 0     MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO  */
+                               0x82000000 0x8 0     MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
+                               0x81000000 0x8 0     MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO  */
+
+                               0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+                               0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
 
                        pcie@1,0 {
                                device_type = "pci";
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                                ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
-                                          0x81000000 0 0 0x81000000 0x2 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+                                         0x81000000 0 0 0x81000000 0x2 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
                                interrupt-map = <0 0 0 0 &mpic 59>;
                                marvell,pcie-port = <0>;
                                status = "disabled";
                        };
 
-                       pcie@9,0 {
+                       pcie@5,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-                               reg = <0x4800 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x2800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
-                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+                                         0x81000000 0 0 0x81000000 0x5 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 99>;
-                               marvell,pcie-port = <2>;
+                               interrupt-map = <0 0 0 0 &mpic 62>;
+                               marvell,pcie-port = <1>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 26>;
+                               clocks = <&gateclk 9>;
                                status = "disabled";
                        };
 
-                       pcie@10,0 {
+                       pcie@6,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
-                               reg = <0x5000 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
+                               reg = <0x3000 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
-                                         0x81000000 0 0 0x81000000 0xa 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
+                                         0x81000000 0 0 0x81000000 0x6 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 103>;
-                               marvell,pcie-port = <3>;
+                               interrupt-map = <0 0 0 0 &mpic 63>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <1>;
+                               clocks = <&gateclk 10>;
+                               status = "disabled";
+                       };
+
+                       pcie@7,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
+                               reg = <0x3800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
+                                         0x81000000 0 0 0x81000000 0x7 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 64>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <2>;
+                               clocks = <&gateclk 11>;
+                               status = "disabled";
+                       };
+
+                       pcie@8,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
+                               reg = <0x4000 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
+                                         0x81000000 0 0 0x81000000 0x8 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 65>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <3>;
+                               clocks = <&gateclk 12>;
+                               status = "disabled";
+                       };
+
+                       pcie@9,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+                               reg = <0x4800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 99>;
+                               marvell,pcie-port = <2>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 27>;
+                               clocks = <&gateclk 26>;
                                status = "disabled";
                        };
                };
index 2347e9563cef62bc760a94c6be2ba2d940cd8c89..6801106fa1f8a0fee541e33da838a15033ddb33c 100644 (file)
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+       aliases {
+               serial4 = &usart3;
+       };
+
        ahb {
                apb {
                        pinctrl@fffff400 {
index 1e12aeff403b018cf174ff1b710af391f970c997..aa537ed13f0a578ade79e74c62a56302f1d65437 100644 (file)
@@ -85,6 +85,8 @@
                        reg = <0x7e205000 0x1000>;
                        interrupts = <2 21>;
                        clocks = <&clk_i2c>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        status = "disabled";
                };
 
@@ -93,6 +95,8 @@
                        reg = <0x7e804000 0x1000>;
                        interrupts = <2 21>;
                        clocks = <&clk_i2c>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        status = "disabled";
                };
 
index dc259e8b8a73a8630dc9698295e662f0ab66e43d..9b186ac06c8ba2fbeff30f9bd58f6ca797e1b05d 100644 (file)
                i2c2_bus: i2c2-bus {
                        samsung,pin-pud = <0>;
                };
+
+               max77686_irq: max77686-irq {
+                       samsung,pins = "gpx3-2";
+                       samsung,pin-function = <0>;
+                       samsung,pin-pud = <0>;
+                       samsung,pin-drv = <0>;
+               };
        };
 
        i2c@12C60000 {
 
                max77686@09 {
                        compatible = "maxim,max77686";
+                       interrupt-parent = <&gpx3>;
+                       interrupts = <2 0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&max77686_irq>;
+                       wakeup-source;
                        reg = <0x09>;
 
                        voltage-regulators {
index 59154dc15fe4ee441c80fd17d9c9141a16ee5e60..fb28b2ecb1db37a28a9effbd7bea591ace78554a 100644 (file)
                                        clocks = <&clks 197>, <&clks 3>,
                                                 <&clks 197>, <&clks 107>,
                                                 <&clks 0>,   <&clks 118>,
-                                                <&clks 62>,  <&clks 139>,
+                                                <&clks 0>,  <&clks 139>,
                                                 <&clks 0>;
                                        clock-names = "core",  "rxtx0",
                                                      "rxtx1", "rxtx2",
index 9c18adf788f774101daa7a7ee4389cfb235bd561..f577b7df9a29e4f5f4e74ca86aef4b4ba61ceb87 100644 (file)
@@ -44,8 +44,8 @@
                gpmc,wr-access-ns = <186>;
                gpmc,cycle2cycle-samecsen;
                gpmc,cycle2cycle-diffcsen;
-               vmmc-supply = <&vddvario>;
-               vmmc_aux-supply = <&vdd33a>;
+               vddvario-supply = <&vddvario>;
+               vdd33a-supply = <&vdd33a>;
                reg-io-width = <4>;
                smsc,save-mac-address;
        };
index b0ee342598f070b508770074d6f474589503628e..68221fab978d40a2e92c5b089e0e4fd1494e39e4 100644 (file)
@@ -13,7 +13,7 @@
         * they probably share the same GPIO IRQ
         * REVISIT: Add timing support from slls644g.pdf
         */
-       8250@3,0 {
+       uart@3,0 {
                compatible = "ns16550a";
                reg = <3 0 0x100>;
                bank-width = <2>;
index a2bfcde858a6ec68f96fd123c515747f3c053004..d0c5b37e248c76734d8c58bc54660f65fc6f877a 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/omap.h>
 
 #include "skeleton.dtsi"
@@ -21,6 +22,8 @@
                serial0 = &uart1;
                serial1 = &uart2;
                serial2 = &uart3;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
        };
 
        cpus {
                ranges;
                ti,hwmods = "l3_main";
 
+               aes: aes@480a6000 {
+                       compatible = "ti,omap2-aes";
+                       ti,hwmods = "aes";
+                       reg = <0x480a6000 0x50>;
+                       dmas = <&sdma 9 &sdma 10>;
+                       dma-names = "tx", "rx";
+               };
+
+               hdq1w: 1w@480b2000 {
+                       compatible = "ti,omap2420-1w";
+                       ti,hwmods = "hdq1w";
+                       reg = <0x480b2000 0x1000>;
+                       interrupts = <58>;
+               };
+
+               mailbox: mailbox@48094000 {
+                       compatible = "ti,omap2-mailbox";
+                       ti,hwmods = "mailbox";
+                       reg = <0x48094000 0x200>;
+                       interrupts = <26>;
+               };
+
                intc: interrupt-controller@1 {
                        compatible = "ti,omap2-intc";
                        interrupt-controller;
@@ -63,6 +88,7 @@
 
                sdma: dma-controller@48056000 {
                        compatible = "ti,omap2430-sdma", "ti,omap2420-sdma";
+                       ti,hwmods = "dma";
                        reg = <0x48056000 0x1000>;
                        interrupts = <12>,
                                     <13>,
                        #dma-requests = <64>;
                };
 
+               i2c1: i2c@48070000 {
+                       compatible = "ti,omap2-i2c";
+                       ti,hwmods = "i2c1";
+                       reg = <0x48070000 0x80>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <56>;
+                       dmas = <&sdma 27 &sdma 28>;
+                       dma-names = "tx", "rx";
+               };
+
+               i2c2: i2c@48072000 {
+                       compatible = "ti,omap2-i2c";
+                       ti,hwmods = "i2c2";
+                       reg = <0x48072000 0x80>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <57>;
+                       dmas = <&sdma 29 &sdma 30>;
+                       dma-names = "tx", "rx";
+               };
+
+               mcspi1: mcspi@48098000 {
+                       compatible = "ti,omap2-mcspi";
+                       ti,hwmods = "mcspi1";
+                       reg = <0x48098000 0x100>;
+                       interrupts = <65>;
+                       dmas = <&sdma 35 &sdma 36 &sdma 37 &sdma 38
+                               &sdma 39 &sdma 40 &sdma 41 &sdma 42>;
+                       dma-names = "tx0", "rx0", "tx1", "rx1",
+                                   "tx2", "rx2", "tx3", "rx3";
+               };
+
+               mcspi2: mcspi@4809a000 {
+                       compatible = "ti,omap2-mcspi";
+                       ti,hwmods = "mcspi2";
+                       reg = <0x4809a000 0x100>;
+                       interrupts = <66>;
+                       dmas = <&sdma 43 &sdma 44 &sdma 45 &sdma 46>;
+                       dma-names = "tx0", "rx0", "tx1", "rx1";
+               };
+
+               rng: rng@480a0000 {
+                       compatible = "ti,omap2-rng";
+                       ti,hwmods = "rng";
+                       reg = <0x480a0000 0x50>;
+                       interrupts = <36>;
+               };
+
+               sham: sham@480a4000 {
+                       compatible = "ti,omap2-sham";
+                       ti,hwmods = "sham";
+                       reg = <0x480a4000 0x64>;
+                       interrupts = <51>;
+                       dmas = <&sdma 13>;
+                       dma-names = "rx";
+               };
+
                uart1: serial@4806a000 {
                        compatible = "ti,omap2-uart";
                        ti,hwmods = "uart1";
+                       reg = <0x4806a000 0x2000>;
+                       interrupts = <72>;
+                       dmas = <&sdma 49 &sdma 50>;
+                       dma-names = "tx", "rx";
                        clock-frequency = <48000000>;
                };
 
                uart2: serial@4806c000 {
                        compatible = "ti,omap2-uart";
                        ti,hwmods = "uart2";
+                       reg = <0x4806c000 0x400>;
+                       interrupts = <73>;
+                       dmas = <&sdma 51 &sdma 52>;
+                       dma-names = "tx", "rx";
                        clock-frequency = <48000000>;
                };
 
                uart3: serial@4806e000 {
                        compatible = "ti,omap2-uart";
                        ti,hwmods = "uart3";
+                       reg = <0x4806e000 0x400>;
+                       interrupts = <74>;
+                       dmas = <&sdma 53 &sdma 54>;
+                       dma-names = "tx", "rx";
                        clock-frequency = <48000000>;
                };
 
index c8f9c55169ead249c9f95add2f15ab99527dd01c..60c605de22ddcdfb9f7220669c12c443a4c218fa 100644 (file)
                        dma-names = "tx", "rx";
                };
 
+               msdi1: mmc@4809c000 {
+                       compatible = "ti,omap2420-mmc";
+                       ti,hwmods = "msdi1";
+                       reg = <0x4809c000 0x80>;
+                       interrupts = <83>;
+                       dmas = <&sdma 61 &sdma 62>;
+                       dma-names = "tx", "rx";
+               };
+
                timer1: timer@48028000 {
                        compatible = "ti,omap2420-timer";
                        reg = <0x48028000 0x400>;
                        ti,hwmods = "timer1";
                        ti,timer-alwon;
                };
+
+               wd_timer2: wdt@48022000 {
+                       compatible = "ti,omap2-wdt";
+                       ti,hwmods = "wd_timer2";
+                       reg = <0x48022000 0x80>;
+               };
        };
 };
+
+&i2c1 {
+       compatible = "ti,omap2420-i2c";
+};
+
+&i2c2 {
+       compatible = "ti,omap2420-i2c";
+};
index c535a5a2b27f9aa95b313c768893520b82d3a6c7..d624345666f56a1468c9e628ae1f3b971fb5d43a 100644 (file)
                        dma-names = "tx", "rx";
                };
 
+               mmc1: mmc@4809c000 {
+                       compatible = "ti,omap2-hsmmc";
+                       reg = <0x4809c000 0x200>;
+                       interrupts = <83>;
+                       ti,hwmods = "mmc1";
+                       ti,dual-volt;
+                       dmas = <&sdma 61>, <&sdma 62>;
+                       dma-names = "tx", "rx";
+               };
+
+               mmc2: mmc@480b4000 {
+                       compatible = "ti,omap2-hsmmc";
+                       reg = <0x480b4000 0x200>;
+                       interrupts = <86>;
+                       ti,hwmods = "mmc2";
+                       dmas = <&sdma 47>, <&sdma 48>;
+                       dma-names = "tx", "rx";
+               };
+
                timer1: timer@49018000 {
                        compatible = "ti,omap2420-timer";
                        reg = <0x49018000 0x400>;
                        ti,hwmods = "timer1";
                        ti,timer-alwon;
                };
+
+               mcspi3: mcspi@480b8000 {
+                       compatible = "ti,omap2-mcspi";
+                       ti,hwmods = "mcspi3";
+                       reg = <0x480b8000 0x100>;
+                       interrupts = <91>;
+                       dmas = <&sdma 15 &sdma 16 &sdma 23 &sdma 24>;
+                       dma-names = "tx0", "rx0", "tx1", "rx1";
+               };
+
+               usb_otg_hs: usb_otg_hs@480ac000 {
+                       compatible = "ti,omap2-musb";
+                       ti,hwmods = "usb_otg_hs";
+                       reg = <0x480ac000 0x1000>;
+                       interrupts = <93>;
+               };
+
+               wd_timer2: wdt@49016000 {
+                       compatible = "ti,omap2-wdt";
+                       ti,hwmods = "wd_timer2";
+                       reg = <0x49016000 0x80>;
+               };
        };
 };
+
+&i2c1 {
+       compatible = "ti,omap2430-i2c";
+};
+
+&i2c2 {
+       compatible = "ti,omap2430-i2c";
+};
index 31a632f7effbf239f298ff3619cdacdc5587356e..df33a50bc070b508fd8dacd8a3c72f645c18d3e0 100644 (file)
 &usbhsehci {
        phys = <0 &hsusb2_phy>;
 };
+
+&vaux2 {
+       regulator-name = "usb_1v8";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index fa532aaacc68943989241b92a6e31743e3e854fe..3ba4a625ea5b9714ce4371e8a9637c108349158c 100644 (file)
                vcc-supply = <&hsusb2_power>;
        };
 
+       sound {
+               compatible = "ti,omap-twl4030";
+               ti,model = "omap3beagle";
+
+               ti,mcbsp = <&mcbsp2>;
+               ti,codec = <&twl_audio>;
+       };
+
        gpio_keys {
                compatible = "gpio-keys";
 
                reg = <0x48>;
                interrupts = <7>; /* SYS_NIRQ cascaded to intc */
                interrupt-parent = <&intc>;
+
+               twl_audio: audio {
+                       compatible = "ti,twl4030-audio";
+                       codec {
+                       };
+               };
        };
 };
 
        mode = <3>;
        power = <50>;
 };
+
+&vaux2 {
+       regulator-name = "vdd_ehci";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index ba1e58b7b7e35ddbdf4825853cf72cef6a951939..165aaf7591ba8ef51856474d85db8754710a33ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP Technology devices
+ * Common device tree for IGEP boards based on AM/DM37x
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -10,7 +10,7 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "omap36xx.dtsi"
 
 / {
        memory {
                ti,mcbsp = <&mcbsp2>;
                ti,codec = <&twl_audio>;
        };
+
+       vdd33: regulator-vdd33 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd33";
+               regulator-always-on;
+       };
+
+       lbee1usjyc_vmmc: lbee1usjyc_vmmc {
+               pinctrl-names = "default";
+               pinctrl-0 = <&lbee1usjyc_pins>;
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;    /* gpio_138 WIFI_PDN */
+               startup-delay-us = <10000>;
+               enable-active-high;
+               vin-supply = <&vdd33>;
+       };
 };
 
 &omap3_pmx_core {
                >;
        };
 
+       /* WiFi/BT combo */
+       lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
+               pinctrl-single,pins = <
+                       0x136 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat5.gpio_137 */
+                       0x138 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat6.gpio_138 */
+                       0x13a (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat7.gpio_139 */
+               >;
+       };
+
        mcbsp2_pins: pinmux_mcbsp2_pins {
                pinctrl-single,pins = <
                        0x10c (PIN_INPUT | MUX_MODE0)           /* mcbsp2_fsx.mcbsp2_fsx */
                        0x11a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat1.sdmmc1_dat1 */
                        0x11c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat2.sdmmc1_dat2 */
                        0x11e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat3.sdmmc1_dat3 */
-                       0x120 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat4.sdmmc1_dat4 */
-                       0x122 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat5.sdmmc1_dat5 */
-                       0x124 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat6.sdmmc1_dat6 */
-                       0x126 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat7.sdmmc1_dat7 */
+               >;
+       };
+
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_clk.sdmmc2_clk */
+                       0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_cmd.sdmmc2_cmd */
+                       0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat0.sdmmc2_dat0 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat1.sdmmc2_dat1 */
+                       0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat2.sdmmc2_dat2 */
+                       0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat3.sdmmc2_dat3 */
                >;
        };
 
                >;
        };
 
+       i2c1_pins: pinmux_i2c1_pins {
+               pinctrl-single,pins = <
+                       0x18a (PIN_INPUT | MUX_MODE0)   /* i2c1_scl.i2c1_scl */
+                       0x18c (PIN_INPUT | MUX_MODE0)   /* i2c1_sda.i2c1_sda */
+               >;
+       };
+
+       i2c2_pins: pinmux_i2c2_pins {
+               pinctrl-single,pins = <
+                       0x18e (PIN_INPUT | MUX_MODE0)   /* i2c2_scl.i2c2_scl */
+                       0x190 (PIN_INPUT | MUX_MODE0)   /* i2c2_sda.i2c2_sda */
+               >;
+       };
+
+       i2c3_pins: pinmux_i2c3_pins {
+               pinctrl-single,pins = <
+                       0x192 (PIN_INPUT | MUX_MODE0)   /* i2c3_scl.i2c3_scl */
+                       0x194 (PIN_INPUT | MUX_MODE0)   /* i2c3_sda.i2c3_sda */
+               >;
+       };
+
        leds_pins: pinmux_leds_pins { };
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        clock-frequency = <2600000>;
 
        twl: twl@48 {
 #include "twl4030_omap3.dtsi"
 
 &i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
        clock-frequency = <400000>;
 };
 
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c3_pins>;
+};
+
 &mcbsp2 {
        pinctrl-names = "default";
        pinctrl-0 = <&mcbsp2_pins>;
       pinctrl-0 = <&mmc1_pins>;
       vmmc-supply = <&vmmc1>;
       vmmc_aux-supply = <&vsim>;
-      bus-width = <8>;
+      bus-width = <4>;
 };
 
 &mmc2 {
-       status = "disabled";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&lbee1usjyc_vmmc>;
+       bus-width = <4>;
+       non-removable;
 };
 
 &mmc3 {
index d5cc792672501012f2a368b4d27b17bbb7669d95..1c7e74d2d2bc7bd03f1a970cea9442f715c0f3eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEPv2 board
+ * Device Tree Source for IGEPv2 Rev. (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -13,7 +13,7 @@
 #include "omap-gpmc-smsc911x.dtsi"
 
 / {
-       model = "IGEPv2";
+       model = "IGEPv2 (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0020", "ti,omap3";
 
        leds {
@@ -67,6 +67,8 @@
        pinctrl-names = "default";
        pinctrl-0 = <
                &hsusbb1_pins
+               &tfp410_pins
+               &dss_pins
        >;
 
        hsusbb1_pins: pinmux_hsusbb1_pins {
                        0x5ba (PIN_INPUT_PULLDOWN | MUX_MODE3)  /* etk_d7.hsusb1_data3 */
                >;
        };
+
+       tfp410_pins: tfp410_dvi_pins {
+               pinctrl-single,pins = <
+                       0x196 (PIN_OUTPUT | MUX_MODE4)   /* hdq_sio.gpio_170 */
+               >;
+       };
+
+       dss_pins: pinmux_dss_dvi_pins {
+               pinctrl-single,pins = <
+                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
+                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
+                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
+                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
+                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
+                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+               >;
+       };
 };
 
 &leds_pins {
 &usbhsehci {
        phys = <&hsusb1_phy>;
 };
+
+&vpll2 {
+        /* Needed for DSS */
+        regulator-name = "vdds_dsi";
+};
index 525e6d9b09784c721b4660554a17abdda14273e9..02a23f8a3384255abca5d54ecf53417226a8347f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP COM Module
+ * Device Tree Source for IGEP COM MODULE (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -12,7 +12,7 @@
 #include "omap3-igep.dtsi"
 
 / {
-       model = "IGEP COM Module";
+       model = "IGEP COM MODULE (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0030", "ti,omap3";
 
        leds {
index c4f20bfe4cce15e641af5ef08c92ca939973b9c3..6fc85f96353024ad61d04d74d7ca51f8afb1c7ce 100644 (file)
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "omap34xx-hs.dtsi"
 
 / {
        model = "Nokia N900";
                >;
        };
 
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_clk */
+                       0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_cmd */
+                       0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat0 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat1 */
+                       0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat2 */
+                       0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat3 */
+                       0x134 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat4 */
+                       0x136 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat5 */
+                       0x138 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat6 */
+                       0x13a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat7 */
+               >;
+       };
+
        display_pins: pinmux_display_pins {
                pinctrl-single,pins = <
                        0x0d4 (PIN_OUTPUT | MUX_MODE4)          /* RX51_LCD_RESET_GPIO */
        cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
 };
 
+/* most boards use vaux3, only some old versions use vmmc2 instead */
 &mmc2 {
-       status = "disabled";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&vaux3>;
+       vmmc_aux-supply = <&vsim>;
+       bus-width = <8>;
+       non-removable;
 };
 
 &mmc3 {
index 94eb77d3b9ddc5a2c506f271834103cb06b4881e..5c26c184f2c18b50a18cdd51bd53b20f9b3f359b 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "omap36xx.dtsi"
+#include "omap36xx-hs.dtsi"
 
 / {
        cpus {
index f3a0c26ed0c2bcd6d6df65dcecc3f18329abec18..daabf99d402a8e4ff645824dcad9d56fc693b17d 100644 (file)
                ranges;
                ti,hwmods = "l3_main";
 
+               aes: aes@480c5000 {
+                       compatible = "ti,omap3-aes";
+                       ti,hwmods = "aes";
+                       reg = <0x480c5000 0x50>;
+                       interrupts = <0>;
+               };
+
                counter32k: counter@48320000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x48320000 0x20>;
                        ti,hwmods = "i2c3";
                };
 
+               mailbox: mailbox@48094000 {
+                       compatible = "ti,omap3-mailbox";
+                       ti,hwmods = "mailbox";
+                       reg = <0x48094000 0x200>;
+                       interrupts = <26>;
+               };
+
                mcspi1: spi@48098000 {
                        compatible = "ti,omap2-mcspi";
                        reg = <0x48098000 0x100>;
                        dma-names = "tx", "rx";
                };
 
+               mmu_isp: mmu@480bd400 {
+                       compatible = "ti,omap3-mmu-isp";
+                       ti,hwmods = "mmu_isp";
+                       reg = <0x480bd400 0x80>;
+                       interrupts = <8>;
+               };
+
                wdt2: wdt@48314000 {
                        compatible = "ti,omap3-wdt";
                        reg = <0x48314000 0x80>;
                        dma-names = "tx", "rx";
                };
 
+               sham: sham@480c3000 {
+                       compatible = "ti,omap3-sham";
+                       ti,hwmods = "sham";
+                       reg = <0x480c3000 0x64>;
+                       interrupts = <49>;
+               };
+
+               smartreflex_core: smartreflex@480cb000 {
+                       compatible = "ti,omap3-smartreflex-core";
+                       ti,hwmods = "smartreflex_core";
+                       reg = <0x480cb000 0x400>;
+                       interrupts = <19>;
+               };
+
+               smartreflex_mpu_iva: smartreflex@480c9000 {
+                       compatible = "ti,omap3-smartreflex-iva";
+                       ti,hwmods = "smartreflex_mpu_iva";
+                       reg = <0x480c9000 0x400>;
+                       interrupts = <18>;
+               };
+
                timer1: timer@48318000 {
                        compatible = "ti,omap3430-timer";
                        reg = <0x48318000 0x400>;
diff --git a/arch/arm/boot/dts/omap34xx-hs.dtsi b/arch/arm/boot/dts/omap34xx-hs.dtsi
new file mode 100644 (file)
index 0000000..1ff6264
--- /dev/null
@@ -0,0 +1,16 @@
+/* Disabled modules for secure omaps */
+
+#include "omap34xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
+
+&timer12 {
+       status = "disabled";
+};
diff --git a/arch/arm/boot/dts/omap36xx-hs.dtsi b/arch/arm/boot/dts/omap36xx-hs.dtsi
new file mode 100644 (file)
index 0000000..2c7febb
--- /dev/null
@@ -0,0 +1,16 @@
+/* Disabled modules for secure omaps */
+
+#include "omap36xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
+
+&timer12 {
+       status = "disabled";
+};
index 298e85020e1b20bec89b8ecc52b38886e4656467..88c6a05cab415f3cb04cdec0fb2bc3c504ec8d7f 100644 (file)
                        0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)     /* i2c4_sda */
                >;
        };
-};
-
-&omap4_pmx_wkup {
-       led_wkgpio_pins: pinmux_leds_wkpins {
-               pinctrl-single,pins = <
-                       0x1a (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk7 */
-                       0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
-               >;
-       };
 
        /*
         * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP
                pinctrl-single,pins = <
                        0x38 (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs2.gpio_52 */
                        0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
-                       0x108 (PIN_OUTPUT | MUX_MODE0)          /* sdmmc5_clk.sdmmc5_clk */
+                       0x108 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_clk.sdmmc5_clk */
                        0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
                        0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
                        0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
        };
 };
 
+&omap4_pmx_wkup {
+       led_wkgpio_pins: pinmux_leds_wkpins {
+               pinctrl-single,pins = <
+                       0x1a (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk7 */
+                       0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
+               >;
+       };
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1_pins>;
index 5fc3f43c5a81d4c9256b063f31bb32fc544dde38..dbc81fb6ef033428ce6b02d7287b7efa46ebfa1e 100644 (file)
        wl12xx_pins: pinmux_wl12xx_pins {
                pinctrl-single,pins = <
                        0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
-                       0x108 (PIN_OUTPUT | MUX_MODE3)          /* sdmmc5_clk.sdmmc5_clk */
-                       0x10a (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_cmd.sdmmc5_cmd */
-                       0x10c (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat0.sdmmc5_dat0 */
-                       0x10e (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat1.sdmmc5_dat1 */
-                       0x110 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat2.sdmmc5_dat2 */
-                       0x112 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat3.sdmmc5_dat3 */
+                       0x108 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_clk.sdmmc5_clk */
+                       0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
+                       0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
+                       0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
+                       0x110 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat2.sdmmc5_dat2 */
+                       0x112 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat3.sdmmc5_dat3 */
                >;
        };
 };
index ee845fad939b895a1bfb907c6597f9f916d926f8..9987dd0e9c599929042b1ce70d4b1d6c3ec1ebfb 100644 (file)
@@ -87,9 +87,9 @@
                interrupts = <1 9 0xf04>;
        };
 
-       gpio0: gpio@ffc40000 {
+       gpio0: gpio@e6050000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc40000 0 0x2c>;
+               reg = <0 0xe6050000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 4 0x4>;
                #gpio-cells = <2>;
@@ -99,9 +99,9 @@
                interrupt-controller;
        };
 
-       gpio1: gpio@ffc41000 {
+       gpio1: gpio@e6051000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc41000 0 0x2c>;
+               reg = <0 0xe6051000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 5 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio2: gpio@ffc42000 {
+       gpio2: gpio@e6052000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc42000 0 0x2c>;
+               reg = <0 0xe6052000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 6 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio3: gpio@ffc43000 {
+       gpio3: gpio@e6053000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc43000 0 0x2c>;
+               reg = <0 0xe6053000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 7 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio4: gpio@ffc44000 {
+       gpio4: gpio@e6054000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc44000 0 0x2c>;
+               reg = <0 0xe6054000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 8 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio5: gpio@ffc45000 {
+       gpio5: gpio@e6055000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc45000 0 0x2c>;
+               reg = <0 0xe6055000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 9 0x4>;
                #gpio-cells = <2>;
 
        sdhi0: sdhi@ee100000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee100000 0 0x100>;
+               reg = <0 0xee100000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 165 4>;
                cap-sd-highspeed;
 
        sdhi1: sdhi@ee120000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee120000 0 0x100>;
+               reg = <0 0xee120000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 166 4>;
                cap-sd-highspeed;
index 6d09b8d42fdd123da5e3b5e4b315983c42f9c6eb..f936476c2753ff380ab7cfe04064fba2598d87c4 100644 (file)
 
                                        mpu_periph_clk: mpu_periph_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mpuclk>;
                                                fixed-divider = <4>;
                                        };
 
                                        mpu_l2_ram_clk: mpu_l2_ram_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mpuclk>;
                                                fixed-divider = <2>;
                                        };
 
                                        l3_main_clk: l3_main_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mainclk>;
+                                               fixed-divider = <1>;
                                        };
 
                                        l3_mp_clk: l3_mp_clk {
index c1751a64889a615612101613d63145b15903bfc7..7f5878c2784ab28eff69c2a278dfa408fe70bc4d 100644 (file)
                pio: pinctrl@01c20800 {
                        compatible = "allwinner,sun6i-a31-pinctrl";
                        reg = <0x01c20800 0x400>;
-                       interrupts = <0 11 1>, <0 15 1>, <0 16 1>, <0 17 1>;
+                       interrupts = <0 11 4>,
+                                    <0 15 4>,
+                                    <0 16 4>,
+                                    <0 17 4>;
                        clocks = <&apb1_gates 5>;
                        gpio-controller;
                        interrupt-controller;
                timer@01c20c00 {
                        compatible = "allwinner,sun4i-timer";
                        reg = <0x01c20c00 0xa0>;
-                       interrupts = <0 18 1>,
-                                    <0 19 1>,
-                                    <0 20 1>,
-                                    <0 21 1>,
-                                    <0 22 1>;
+                       interrupts = <0 18 4>,
+                                    <0 19 4>,
+                                    <0 20 4>,
+                                    <0 21 4>,
+                                    <0 22 4>;
                        clocks = <&osc24M>;
                };
 
                uart0: serial@01c28000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28000 0x400>;
-                       interrupts = <0 0 1>;
+                       interrupts = <0 0 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 16>;
                uart1: serial@01c28400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
-                       interrupts = <0 1 1>;
+                       interrupts = <0 1 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 17>;
                uart2: serial@01c28800 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28800 0x400>;
-                       interrupts = <0 2 1>;
+                       interrupts = <0 2 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 18>;
                uart3: serial@01c28c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28c00 0x400>;
-                       interrupts = <0 3 1>;
+                       interrupts = <0 3 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 19>;
                uart4: serial@01c29000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29000 0x400>;
-                       interrupts = <0 4 1>;
+                       interrupts = <0 4 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 20>;
                uart5: serial@01c29400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29400 0x400>;
-                       interrupts = <0 5 1>;
+                       interrupts = <0 5 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 21>;
index e46cfedde74c220b698c829458dfa40cef916159..367611a0730bc0c978d24737fa611c1beeac7417 100644 (file)
                emac: ethernet@01c0b000 {
                        compatible = "allwinner,sun4i-emac";
                        reg = <0x01c0b000 0x1000>;
-                       interrupts = <0 55 1>;
+                       interrupts = <0 55 4>;
                        clocks = <&ahb_gates 17>;
                        status = "disabled";
                };
                pio: pinctrl@01c20800 {
                        compatible = "allwinner,sun7i-a20-pinctrl";
                        reg = <0x01c20800 0x400>;
-                       interrupts = <0 28 1>;
+                       interrupts = <0 28 4>;
                        clocks = <&apb0_gates 5>;
                        gpio-controller;
                        interrupt-controller;
                timer@01c20c00 {
                        compatible = "allwinner,sun4i-timer";
                        reg = <0x01c20c00 0x90>;
-                       interrupts = <0 22 1>,
-                                    <0 23 1>,
-                                    <0 24 1>,
-                                    <0 25 1>,
-                                    <0 67 1>,
-                                    <0 68 1>;
+                       interrupts = <0 22 4>,
+                                    <0 23 4>,
+                                    <0 24 4>,
+                                    <0 25 4>,
+                                    <0 67 4>,
+                                    <0 68 4>;
                        clocks = <&osc24M>;
                };
 
                uart0: serial@01c28000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28000 0x400>;
-                       interrupts = <0 1 1>;
+                       interrupts = <0 1 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 16>;
                uart1: serial@01c28400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
-                       interrupts = <0 2 1>;
+                       interrupts = <0 2 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 17>;
                uart2: serial@01c28800 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28800 0x400>;
-                       interrupts = <0 3 1>;
+                       interrupts = <0 3 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 18>;
                uart3: serial@01c28c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28c00 0x400>;
-                       interrupts = <0 4 1>;
+                       interrupts = <0 4 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 19>;
                uart4: serial@01c29000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29000 0x400>;
-                       interrupts = <0 17 1>;
+                       interrupts = <0 17 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 20>;
                uart5: serial@01c29400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29400 0x400>;
-                       interrupts = <0 18 1>;
+                       interrupts = <0 18 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 21>;
                uart6: serial@01c29800 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29800 0x400>;
-                       interrupts = <0 19 1>;
+                       interrupts = <0 19 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 22>;
                uart7: serial@01c29c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29c00 0x400>;
-                       interrupts = <0 20 1>;
+                       interrupts = <0 20 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 23>;
                i2c0: i2c@01c2ac00 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2ac00 0x400>;
-                       interrupts = <0 7 1>;
+                       interrupts = <0 7 4>;
                        clocks = <&apb1_gates 0>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c1: i2c@01c2b000 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2b000 0x400>;
-                       interrupts = <0 8 1>;
+                       interrupts = <0 8 4>;
                        clocks = <&apb1_gates 1>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c2: i2c@01c2b400 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2b400 0x400>;
-                       interrupts = <0 9 1>;
+                       interrupts = <0 9 4>;
                        clocks = <&apb1_gates 2>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c3: i2c@01c2b800 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2b800 0x400>;
-                       interrupts = <0 88 1>;
+                       interrupts = <0 88 4>;
                        clocks = <&apb1_gates 3>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c4: i2c@01c2bc00 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2bc00 0x400>;
-                       interrupts = <0 89 1>;
+                       interrupts = <0 89 4>;
                        clocks = <&apb1_gates 15>;
                        clock-frequency = <100000>;
                        status = "disabled";
index 4a5903e048272429bf58d753419bddda18d2f586..c1df4e9db140831e45e5b91b2c280b1a1d813fef 100644 (file)
@@ -69,6 +69,7 @@ CONFIG_KS8851=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=y
 CONFIG_MDIO_SUN4I=y
+CONFIG_TI_CPSW=y
 CONFIG_KEYBOARD_SPEAR=y
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIAL_8250=y
@@ -133,12 +134,14 @@ CONFIG_USB_GPIO_VBUS=y
 CONFIG_USB_ISP1301=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_EDAC=y
index 98a50c309b90ad72b710fdeddc4117208fa6c29c..bfa80a11e8c76304c800f2df62090f1f50d089c1 100644 (file)
@@ -173,6 +173,7 @@ CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
index d57a85badb5ef49959ad5bc8049768330367a920..3e2259b60236d76af041a1a6eb3ef99cab7975a6 100644 (file)
@@ -12,6 +12,9 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
@@ -58,4 +61,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_COMMON_CLK_DEBUG=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS=y
+CONFIG_PRINTK_TIME=y
index ac632cc38f249767bcedfc1232a4e4b8e6bc70d9..c6ebc184bf68201c69a0791ed83f0bbfc64b4348 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_IDLE=y
+CONFIG_ARM_U8500_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_PM_RUNTIME=y
@@ -109,6 +110,8 @@ CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_MISC_FILESYSTEMS is not set
index 9ecccc865046a2c257277cd03a8f607ed5e0217d..6976b03e521369bddedfe6968cfa221c6705c552 100644 (file)
 #define TASK_UNMAPPED_BASE     UL(0x00000000)
 #endif
 
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET            UL(CONFIG_DRAM_BASE)
-#endif
-
 #ifndef END_MEM
 #define END_MEM                (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
 #endif
 
 #ifndef PAGE_OFFSET
-#define PAGE_OFFSET            (PHYS_OFFSET)
+#define PAGE_OFFSET            PLAT_PHYS_OFFSET
 #endif
 
 /*
  * The module can be at any place in ram in nommu mode.
  */
 #define MODULES_END            (END_MEM)
-#define MODULES_VADDR          (PHYS_OFFSET)
+#define MODULES_VADDR          PAGE_OFFSET
 
 #define XIP_VIRT_ADDR(physaddr)  (physaddr)
 
 #endif
 #define ARCH_PGD_MASK          ((1 << ARCH_PGD_SHIFT) - 1)
 
+/*
+ * PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
+ * memory.  This is used for XIP and NoMMU kernels, or by kernels which
+ * have their own mach/memory.h.  Assembly code must always use
+ * PLAT_PHYS_OFFSET and not PHYS_OFFSET.
+ */
+#ifndef PLAT_PHYS_OFFSET
+#define PLAT_PHYS_OFFSET       UL(CONFIG_PHYS_OFFSET)
+#endif
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -239,6 +245,8 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
 
 #else
 
+#define PHYS_OFFSET    PLAT_PHYS_OFFSET
+
 static inline phys_addr_t __virt_to_phys(unsigned long x)
 {
        return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET;
@@ -251,17 +259,6 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
 
 #endif
 #endif
-#endif /* __ASSEMBLY__ */
-
-#ifndef PHYS_OFFSET
-#ifdef PLAT_PHYS_OFFSET
-#define PHYS_OFFSET    PLAT_PHYS_OFFSET
-#else
-#define PHYS_OFFSET    UL(CONFIG_PHYS_OFFSET)
-#endif
-#endif
-
-#ifndef __ASSEMBLY__
 
 /*
  * PFNs are used to describe any physical page; this means
index be956dbf6baea3a7481baa11c58233d0741702d1..1571d126e9ddb08b77c99955538209212755ebfd 100644 (file)
@@ -61,7 +61,7 @@ extern void __pgd_error(const char *file, int line, pgd_t);
  * mapping to be mapped at.  This is particularly important for
  * non-high vector CPUs.
  */
-#define FIRST_USER_ADDRESS     PAGE_SIZE
+#define FIRST_USER_ADDRESS     (PAGE_SIZE * 2)
 
 /*
  * Use TASK_SIZE as the ceiling argument for free_pgtables() and
index 14235ba64a90736ecebad575f5d88ea4568e8eaf..716249cc2ee18c178643e7e6c4a0cd0eb6a48c00 100644 (file)
@@ -68,7 +68,7 @@ ENTRY(stext)
 
 #ifdef CONFIG_ARM_MPU
        /* Calculate the size of a region covering just the kernel */
-       ldr     r5, =PHYS_OFFSET                @ Region start: PHYS_OFFSET
+       ldr     r5, =PLAT_PHYS_OFFSET           @ Region start: PHYS_OFFSET
        ldr     r6, =(_end)                     @ Cover whole kernel
        sub     r6, r6, r5                      @ Minimum size of region to map
        clz     r6, r6                          @ Region size must be 2^N...
@@ -213,7 +213,7 @@ ENTRY(__setup_mpu)
        set_region_nr r0, #MPU_RAM_REGION
        isb
        /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
-       ldr     r0, =PHYS_OFFSET                @ RAM starts at PHYS_OFFSET
+       ldr     r0, =PLAT_PHYS_OFFSET           @ RAM starts at PHYS_OFFSET
        ldr     r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
 
        setup_region r0, r5, r6, MPU_DATA_SIDE  @ PHYS_OFFSET, shared, enabled
index 11d59b32fb8dca45613ed00fb225a72359c19216..32f317e5828adafc2bdec200705a9d12c686711c 100644 (file)
@@ -110,7 +110,7 @@ ENTRY(stext)
        sub     r4, r3, r4                      @ (PHYS_OFFSET - PAGE_OFFSET)
        add     r8, r8, r4                      @ PHYS_OFFSET
 #else
-       ldr     r8, =PHYS_OFFSET                @ always constant in this case
+       ldr     r8, =PLAT_PHYS_OFFSET           @ always constant in this case
 #endif
 
        /*
index 57221e349a7ce0eec03445cd56de2845e5d23358..f0d180d8b29f4e22558a98fdf9366ebaf1c0c0cb 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
+#include <asm/fncpy.h>
 #include <asm/mach-types.h>
 #include <asm/smp_plat.h>
 #include <asm/system_misc.h>
 
-extern const unsigned char relocate_new_kernel[];
+extern void relocate_new_kernel(void);
 extern const unsigned int relocate_new_kernel_size;
 
 extern unsigned long kexec_start_address;
@@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image)
 {
        unsigned long page_list;
        unsigned long reboot_code_buffer_phys;
+       unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
+       unsigned long reboot_entry_phys;
        void *reboot_code_buffer;
 
        /*
@@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image)
 
 
        /* copy our kernel relocation code to the control code page */
-       memcpy(reboot_code_buffer,
-              relocate_new_kernel, relocate_new_kernel_size);
+       reboot_entry = fncpy(reboot_code_buffer,
+                            reboot_entry,
+                            relocate_new_kernel_size);
+       reboot_entry_phys = (unsigned long)reboot_entry +
+               (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);
 
-
-       flush_icache_range((unsigned long) reboot_code_buffer,
-                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
 
        if (kexec_reinit)
                kexec_reinit();
 
-       soft_restart(reboot_code_buffer_phys);
+       soft_restart(reboot_entry_phys);
 }
index 94f6b05f9e24e8cd1d79063f03a9b2dd16791c67..92f7b15dd22121d4aa674fd78cd95cac8924c07f 100644 (file)
@@ -404,6 +404,7 @@ EXPORT_SYMBOL(dump_fpu);
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
+       unsigned long stack_page;
        int count = 0;
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
@@ -412,9 +413,11 @@ unsigned long get_wchan(struct task_struct *p)
        frame.sp = thread_saved_sp(p);
        frame.lr = 0;                   /* recovered from the stack */
        frame.pc = thread_saved_pc(p);
+       stack_page = (unsigned long)task_stack_page(p);
        do {
-               int ret = unwind_frame(&frame);
-               if (ret < 0)
+               if (frame.sp < stack_page ||
+                   frame.sp >= stack_page + THREAD_SIZE ||
+                   unwind_frame(&frame) < 0)
                        return 0;
                if (!in_sched_functions(frame.pc))
                        return frame.pc;
index d0cdedf4864dc52092355e105f3ba04bba5c5704..95858966d84ec0f10d392a3356cb0367fcee0b85 100644 (file)
@@ -2,10 +2,12 @@
  * relocate_kernel.S - put the kernel image in place to boot
  */
 
+#include <linux/linkage.h>
 #include <asm/kexec.h>
 
-       .globl relocate_new_kernel
-relocate_new_kernel:
+       .align  3       /* not needed for this code, but keeps fncpy() happy */
+
+ENTRY(relocate_new_kernel)
 
        ldr     r0,kexec_indirection_page
        ldr     r1,kexec_start_address
@@ -79,6 +81,8 @@ kexec_mach_type:
 kexec_boot_atags:
        .long   0x0
 
+ENDPROC(relocate_new_kernel)
+
 relocate_new_kernel_end:
 
        .globl relocate_new_kernel_size
index 6a1b8a81b1ae448168572a9558aaf026f9e7e47e..987a7f5bce5f1759d73c01a80099cea57a94025d 100644 (file)
@@ -873,8 +873,6 @@ void __init setup_arch(char **cmdline_p)
        machine_desc = mdesc;
        machine_name = mdesc->name;
 
-       setup_dma_zone(mdesc);
-
        if (mdesc->reboot_mode != REBOOT_HARD)
                reboot_mode = mdesc->reboot_mode;
 
@@ -892,6 +890,7 @@ void __init setup_arch(char **cmdline_p)
        sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
 
        early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
+       setup_dma_zone(mdesc);
        sanity_check_meminfo();
        arm_memblock_init(&meminfo, mdesc);
 
index 3c5d0f2170fd7ee309260c2d2c0a6108a24e54f8..b84d0cb13682ccd42e41a22894cb8d2c1821496d 100644 (file)
  * snippets.
  */
 
+/*
+ * In CPU_THUMBONLY case kernel arm opcodes are not allowed.
+ * Note in this case codes skips those instructions but it uses .org
+ * directive to keep correct layout of sigreturn_codes array.
+ */
+#ifndef CONFIG_CPU_THUMBONLY
+#define ARM_OK(code...)        code
+#else
+#define ARM_OK(code...)
+#endif
+
+       .macro arm_slot n
+       .org    sigreturn_codes + 12 * (\n)
+ARM_OK(        .arm    )
+       .endm
+
+       .macro thumb_slot n
+       .org    sigreturn_codes + 12 * (\n) + 8
+       .thumb
+       .endm
+
 #if __LINUX_ARM_ARCH__ <= 4
        /*
         * Note we manually set minimally required arch that supports
        .global sigreturn_codes
        .type   sigreturn_codes, #object
 
-       .arm
+       .align
 
 sigreturn_codes:
 
        /* ARM sigreturn syscall code snippet */
-       mov     r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
-       swi     #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)
+       arm_slot 0
+ARM_OK(        mov     r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)       )
+ARM_OK(        swi     #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)      )
 
        /* Thumb sigreturn syscall code snippet */
-       .thumb
+       thumb_slot 0
        movs    r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
        swi     #0
 
        /* ARM sigreturn_rt syscall code snippet */
-       .arm
-       mov     r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
-       swi     #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)
+       arm_slot 1
+ARM_OK(        mov     r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)    )
+ARM_OK(        swi     #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)   )
 
        /* Thumb sigreturn_rt syscall code snippet */
-       .thumb
+       thumb_slot 1
        movs    r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
        swi     #0
 
@@ -74,7 +96,7 @@ sigreturn_codes:
         * it is thumb case or not, so we need additional
         * word after real last entry.
         */
-       .arm
+       arm_slot 2
        .space  4
 
        .size   sigreturn_codes, . - sigreturn_codes
index 00f79e59985bccaf54bd3b1c8f2e292f49014a47..af4e8c8a5422c4383396f7f4b3a836a67426b7de 100644 (file)
@@ -31,7 +31,7 @@ int notrace unwind_frame(struct stackframe *frame)
        high = ALIGN(low, THREAD_SIZE);
 
        /* check current frame pointer is within bounds */
-       if (fp < (low + 12) || fp + 4 >= high)
+       if (fp < low + 12 || fp > high - 4)
                return -EINVAL;
 
        /* restore the registers from the stack frame */
index dbf0923e8d76bda9392b902e0c8e500025d70402..7940241f0576b0db1cc0a749e449c7faf492518a 100644 (file)
@@ -509,9 +509,10 @@ static inline int
 __do_cache_op(unsigned long start, unsigned long end)
 {
        int ret;
-       unsigned long chunk = PAGE_SIZE;
 
        do {
+               unsigned long chunk = min(PAGE_SIZE, end - start);
+
                if (signal_pending(current)) {
                        struct thread_info *ti = current_thread_info();
 
index 36b668d8e121ee7450c8beffb5e9661923102038..bc1033b897b44510b16a8ab202f0c1b989cc15e5 100644 (file)
@@ -40,6 +40,7 @@ ENTRY(__loop_const_udelay)                    @ 0 <= r0 <= 0x7fffff06
 /*
  * loops = r0 * HZ * loops_per_jiffy / 1000000
  */
+               .align 3
 
 @ Delay routine
 ENTRY(__loop_delay)
index f607deb40f4da6a88a0778b203cdcfbbc8518ecc..bc7b363a3083bfdab31591786fe38991c199e2dc 100644 (file)
@@ -174,7 +174,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 static struct clock_event_device clkevt = {
        .name           = "at91_tick",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 150,
        .set_next_event = clkevt32k_next_event,
        .set_mode       = clkevt32k_mode,
@@ -265,11 +264,9 @@ void __init at91rm9200_timer_init(void)
        at91_st_write(AT91_ST_RTMR, 1);
 
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
-       clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
-       clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
-       clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
        clkevt.cpumask = cpumask_of(0);
-       clockevents_register_device(&clkevt);
+       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
+                                       2, AT91_ST_ALMV);
 
        /* register clocksource */
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
index 3ed190ce062bd5add5a426e07b1cf6c5d1e5b89a..c5101dcb4fb04d8d9af68bea524043feb3c289a9 100644 (file)
 #include <mach/at91_ramc.h>
 #include <mach/at91rm9200_sdramc.h>
 
+#ifdef CONFIG_PM
 extern void at91_pm_set_standby(void (*at91_standby)(void));
+#else
+static inline void at91_pm_set_standby(void (*at91_standby)(void)) { }
+#endif
 
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
index 3ea86428ee0964f11d0955a90d0348626e68da58..a28873fe30491334e9feaad188901bea37d34d24 100644 (file)
@@ -95,19 +95,19 @@ static struct clk twi0_clk = {
        .name           = "twi0_clk",
        .pid            = SAMA5D3_ID_TWI0,
        .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
+       .div            = AT91_PMC_PCR_DIV8,
 };
 static struct clk twi1_clk = {
        .name           = "twi1_clk",
        .pid            = SAMA5D3_ID_TWI1,
        .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
+       .div            = AT91_PMC_PCR_DIV8,
 };
 static struct clk twi2_clk = {
        .name           = "twi2_clk",
        .pid            = SAMA5D3_ID_TWI2,
        .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
+       .div            = AT91_PMC_PCR_DIV8,
 };
 static struct clk mmc0_clk = {
        .name           = "mci0_clk",
index c46eccbbd51226f5ae6ab5a16e1c89668c35fa1d..78829c513fdc354bce631d67f45922efff84368d 100644 (file)
@@ -487,7 +487,7 @@ int __init da8xx_register_emac(void)
 
 static struct resource da830_mcasp1_resources[] = {
        {
-               .name   = "mcasp1",
+               .name   = "mpu",
                .start  = DAVINCI_DA830_MCASP1_REG_BASE,
                .end    = DAVINCI_DA830_MCASP1_REG_BASE + (SZ_1K * 12) - 1,
                .flags  = IORESOURCE_MEM,
@@ -515,7 +515,7 @@ static struct platform_device da830_mcasp1_device = {
 
 static struct resource da850_mcasp_resources[] = {
        {
-               .name   = "mcasp",
+               .name   = "mpu",
                .start  = DAVINCI_DA8XX_MCASP0_REG_BASE,
                .end    = DAVINCI_DA8XX_MCASP0_REG_BASE + (SZ_1K * 12) - 1,
                .flags  = IORESOURCE_MEM,
index ef9ff1fb6f52a2533378ba37563c06e877b32ea3..6117fc644188d9aa81c2397dbb60538db190beea 100644 (file)
@@ -641,6 +641,7 @@ static struct platform_device dm355_edma_device = {
 
 static struct resource dm355_asp1_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_ASP1_BASE,
                .end    = DAVINCI_ASP1_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
@@ -906,7 +907,7 @@ static struct davinci_gpio_platform_data dm355_gpio_platform_data = {
 int __init dm355_gpio_register(void)
 {
        return davinci_gpio_register(dm355_gpio_resources,
-                                    sizeof(dm355_gpio_resources),
+                                    ARRAY_SIZE(dm355_gpio_resources),
                                     &dm355_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 1511a0680f9a1d399cf3094b538c3c52caa06547..d7c6f85d3fc9d5c4347ec214ae8e71a310f89b62 100644 (file)
@@ -720,7 +720,7 @@ static struct davinci_gpio_platform_data dm365_gpio_platform_data = {
 int __init dm365_gpio_register(void)
 {
        return davinci_gpio_register(dm365_gpio_resources,
-                                    sizeof(dm365_gpio_resources),
+                                    ARRAY_SIZE(dm365_gpio_resources),
                                     &dm365_gpio_platform_data);
 }
 
@@ -942,6 +942,7 @@ static struct platform_device dm365_edma_device = {
 
 static struct resource dm365_asp_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_DM365_ASP0_BASE,
                .end    = DAVINCI_DM365_ASP0_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
index 143a3217e8efb8fde1aa417700c45840d242aac0..3ce47997bb46150e82f40e718474feeae52b6d5e 100644 (file)
@@ -572,6 +572,7 @@ static struct platform_device dm644x_edma_device = {
 /* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
 static struct resource dm644x_asp_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_ASP0_BASE,
                .end    = DAVINCI_ASP0_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
@@ -792,7 +793,7 @@ static struct davinci_gpio_platform_data dm644_gpio_platform_data = {
 int __init dm644x_gpio_register(void)
 {
        return davinci_gpio_register(dm644_gpio_resources,
-                                    sizeof(dm644_gpio_resources),
+                                    ARRAY_SIZE(dm644_gpio_resources),
                                     &dm644_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 2a73f299c1d094615236359d6ac27959cdd16295..0e81fea65e7fb484cda893f0a4cd91d0b74fc0ad 100644 (file)
@@ -621,7 +621,7 @@ static struct platform_device dm646x_edma_device = {
 
 static struct resource dm646x_mcasp0_resources[] = {
        {
-               .name   = "mcasp0",
+               .name   = "mpu",
                .start  = DAVINCI_DM646X_MCASP0_REG_BASE,
                .end    = DAVINCI_DM646X_MCASP0_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
@@ -641,7 +641,7 @@ static struct resource dm646x_mcasp0_resources[] = {
 
 static struct resource dm646x_mcasp1_resources[] = {
        {
-               .name   = "mcasp1",
+               .name   = "mpu",
                .start  = DAVINCI_DM646X_MCASP1_REG_BASE,
                .end    = DAVINCI_DM646X_MCASP1_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
@@ -769,7 +769,7 @@ static struct davinci_gpio_platform_data dm646x_gpio_platform_data = {
 int __init dm646x_gpio_register(void)
 {
        return davinci_gpio_register(dm646x_gpio_resources,
-                                    sizeof(dm646x_gpio_resources),
+                                    ARRAY_SIZE(dm646x_gpio_resources),
                                     &dm646x_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 2739ca2c13346f1ed4bdce26916ae4e2270900ad..e0091685fd4861c8eb6f41b00c5f316865c1668b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <video/vga.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -196,6 +197,8 @@ void __init footbridge_map_io(void)
                iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
                pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
        }
+
+       vga_base = PCIMEM_BASE;
 }
 
 void footbridge_restart(enum reboot_mode mode, const char *cmd)
index 3490a24f969e4a0b450ef146cee72f37e1cb6c9f..7c2fdae9a38b63454523277a005dcf6c5c1c65ab 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
-#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
@@ -291,7 +290,6 @@ void __init dc21285_preinit(void)
        int cfn_mode;
 
        pcibios_min_mem = 0x81000000;
-       vga_base = PCIMEM_BASE;
 
        mem_size = (unsigned int)high_memory - PAGE_OFFSET;
        for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
index b08243500e2e9bc8f7196d6e6c5484b3ba7dadb4..1a7235fb52acb3cb8ae784dbeeda4fb3c940594a 100644 (file)
@@ -30,21 +30,24 @@ static const struct {
        const char *name;
        const char *trigger;
 } ebsa285_leds[] = {
-       { "ebsa285:amber", "heartbeat", },
-       { "ebsa285:green", "cpu0", },
+       { "ebsa285:amber", "cpu0", },
+       { "ebsa285:green", "heartbeat", },
        { "ebsa285:red",},
 };
 
+static unsigned char hw_led_state;
+
 static void ebsa285_led_set(struct led_classdev *cdev,
                enum led_brightness b)
 {
        struct ebsa285_led *led = container_of(cdev,
                        struct ebsa285_led, cdev);
 
-       if (b != LED_OFF)
-               *XBUS_LEDS |= led->mask;
+       if (b == LED_OFF)
+               hw_led_state |= led->mask;
        else
-               *XBUS_LEDS &= ~led->mask;
+               hw_led_state &= ~led->mask;
+       *XBUS_LEDS = hw_led_state;
 }
 
 static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
@@ -52,18 +55,19 @@ static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
        struct ebsa285_led *led = container_of(cdev,
                        struct ebsa285_led, cdev);
 
-       return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF;
+       return hw_led_state & led->mask ? LED_OFF : LED_FULL;
 }
 
 static int __init ebsa285_leds_init(void)
 {
        int i;
 
-       if (machine_is_ebsa285())
+       if (!machine_is_ebsa285())
                return -ENODEV;
 
-       /* 3 LEDS All ON */
-       *XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+       /* 3 LEDS all off */
+       hw_led_state = XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+       *XBUS_LEDS = hw_led_state;
 
        for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
                struct ebsa285_led *led;
index b3d7e5634b83cb02ce568040099027007820a45b..bd3bf66ce3449a31c9c7c9f56be6b4225ee9cbf9 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
+#include <linux/input.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
+#include <linux/mailbox.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
+#include <linux/reboot.h>
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
 
@@ -130,6 +133,24 @@ static struct platform_device highbank_cpuidle_device = {
        .name = "cpuidle-calxeda",
 };
 
+static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data)
+{
+       u32 key = *(u32 *)data;
+
+       if (event != 0x1000)
+               return 0;
+
+       if (key == KEY_POWER)
+               orderly_poweroff(false);
+       else if (key == 0xffff)
+               ctrl_alt_del();
+
+       return 0;
+}
+static struct notifier_block hb_keys_nb = {
+       .notifier_call = hb_keys_notifier,
+};
+
 static void __init highbank_init(void)
 {
        struct device_node *np;
@@ -145,6 +166,8 @@ static void __init highbank_init(void)
        bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
        bus_register_notifier(&amba_bustype, &highbank_amba_nb);
 
+       pl320_ipc_register_notifier(&hb_keys_nb);
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        if (psci_ops.cpu_suspend)
index 1f25f3e99c05481418dcb7aa1472df14cee7202f..adcef406ff0abdc5a1695cac7f9cb04dc6ac542e 100644 (file)
@@ -19,11 +19,11 @@ secure-common                               = omap-smc.o omap-secure.o
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
-obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
+obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common)
 obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
-obj-$(CONFIG_SOC_OMAP5)         += prm44xx.o $(hwmod-common) $(secure-common)
+obj-$(CONFIG_SOC_OMAP5)         += $(hwmod-common) $(secure-common)
 obj-$(CONFIG_SOC_AM43XX) += $(hwmod-common) $(secure-common)
-obj-$(CONFIG_SOC_DRA7XX) += prm44xx.o $(hwmod-common) $(secure-common)
+obj-$(CONFIG_SOC_DRA7XX) += $(hwmod-common) $(secure-common)
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
 obj-y += mcbsp.o
index 19f1652e94cfbf5e1f09d2d4cc27e44087cc68d7..8d972ff18c561111317aa96d61c0b9fda2d8cade 100644 (file)
@@ -131,6 +131,24 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
        .dt_compat      = omap3_gp_boards_compat,
        .restart        = omap3xxx_restart,
 MACHINE_END
+
+static const char *am3517_boards_compat[] __initdata = {
+       "ti,am3517",
+       NULL,
+};
+
+DT_MACHINE_START(AM3517_DT, "Generic AM3517 (Flattened Device Tree)")
+       .reserve        = omap_reserve,
+       .map_io         = omap3_map_io,
+       .init_early     = am35xx_init_early,
+       .init_irq       = omap_intc_of_init,
+       .handle_irq     = omap3_intc_handle_irq,
+       .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
+       .init_time      = omap3_gptimer_timer_init,
+       .dt_compat      = am3517_boards_compat,
+       .restart        = omap3xxx_restart,
+MACHINE_END
 #endif
 
 #ifdef CONFIG_SOC_AM33XX
index 4ec8d82b0492f3e66e75bec0aa7cff8cd25a5faa..44a59c3abfb0535e8c9168284a5bf67ed0f13bb6 100644 (file)
@@ -242,12 +242,18 @@ static void __init ldp_display_init(void)
 
 static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 {
+       int res;
+
        /* LCD enable GPIO */
        ldp_lcd_pdata.enable_gpio = gpio + 7;
 
        /* Backlight enable GPIO */
        ldp_lcd_pdata.backlight_gpio = gpio + 15;
 
+       res = platform_device_register(&ldp_lcd_device);
+       if (res)
+               pr_err("Unable to register LCD: %d\n", res);
+
        return 0;
 }
 
@@ -346,7 +352,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 
 static struct platform_device *ldp_devices[] __initdata = {
        &ldp_gpio_keys_device,
-       &ldp_lcd_device,
 };
 
 #ifdef CONFIG_OMAP_MUX
index f7644febee81d7d41ae2cfc01e1fc362b972de02..e30ef6797c6311798cbb92b4521c56306b7fdc67 100644 (file)
@@ -299,7 +299,6 @@ struct omap_sdrc_params;
 extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
                                      struct omap_sdrc_params *sdrc_cs1);
 struct omap2_hsmmc_info;
-extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
 extern void omap_reserve(void);
 
 struct omap_hwmod;
index a4e536b11ec9a997d8e640ff44745e6759c031fa..4cf165502b35cfdd06c09696a20b09758d974169 100644 (file)
@@ -32,7 +32,6 @@
 
 #include "soc.h"
 #include "iomap.h"
-#include "mux.h"
 #include "control.h"
 #include "display.h"
 #include "prm.h"
@@ -102,35 +101,6 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
-static void __init omap4_tpd12s015_mux_pads(void)
-{
-       omap_mux_init_signal("hdmi_cec",
-                       OMAP_PIN_INPUT_PULLUP);
-       omap_mux_init_signal("hdmi_ddc_scl",
-                       OMAP_PIN_INPUT_PULLUP);
-       omap_mux_init_signal("hdmi_ddc_sda",
-                       OMAP_PIN_INPUT_PULLUP);
-}
-
-static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
-{
-       u32 reg;
-       u16 control_i2c_1;
-
-       /*
-        * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
-        * HDMI_DDC_SCL_PULLUPRESX (bit 24) are set to disable
-        * internal pull up resistor.
-        */
-       if (flags & OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP) {
-               control_i2c_1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1;
-               reg = omap4_ctrl_pad_readl(control_i2c_1);
-               reg |= (OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK |
-                       OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK);
-                       omap4_ctrl_pad_writel(reg, control_i2c_1);
-       }
-}
-
 static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 {
        u32 enable_mask, enable_shift;
@@ -164,16 +134,6 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
        return 0;
 }
 
-int __init omap_hdmi_init(enum omap_hdmi_flags flags)
-{
-       if (cpu_is_omap44xx()) {
-               omap4_hdmi_mux_pads(flags);
-               omap4_tpd12s015_mux_pads();
-       }
-
-       return 0;
-}
-
 static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
        if (cpu_is_omap44xx())
index 365bfd3d9c68b8486f23049a71889484c60eb793..dadccc91488c64e94c06e9bf93b54bc5c294e26e 100644 (file)
@@ -223,7 +223,7 @@ void __init omap_4430sdp_display_init_of(void)
 static struct connector_dvi_platform_data omap3_igep2_dvi_connector_pdata = {
        .name                   = "dvi",
        .source                 = "tfp410.0",
-       .i2c_bus_num            = 3,
+       .i2c_bus_num            = 2,
 };
 
 static struct platform_device omap3_igep2_dvi_connector_device = {
index 81de56251955a7bf82b7f4ce3b03ffcd3333fd5e..d24926e6340fa714cf0aeacca14a6578e5b481a4 100644 (file)
@@ -1501,6 +1501,22 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
                return ret;
        }
 
+       /*
+        * For some GPMC devices we still need to rely on the bootloader
+        * timings because the devices can be connected via FPGA. So far
+        * the list is smc91x on the omap2 SDP boards, and 8250 on zooms.
+        * REVISIT: Add timing support from slls644g.pdf and from the
+        * lan91c96 manual.
+        */
+       if (of_device_is_compatible(child, "ns16550a") ||
+           of_device_is_compatible(child, "smsc,lan91c94") ||
+           of_device_is_compatible(child, "smsc,lan91c111")) {
+               dev_warn(&pdev->dev,
+                        "%s using bootloader timings on CS%d\n",
+                        child->name, cs);
+               goto no_timings;
+       }
+
        /*
         * FIXME: gpmc_cs_request() will map the CS to an arbitary
         * location in the gpmc address space. When booting with
@@ -1529,6 +1545,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
        gpmc_read_timings_dt(child, &gpmc_t);
        gpmc_cs_set_timings(cs, &gpmc_t);
 
+no_timings:
        if (of_platform_device_create(child, NULL, &pdev->dev))
                return 0;
 
@@ -1541,42 +1558,6 @@ err:
        return ret;
 }
 
-/*
- * REVISIT: Add timing support from slls644g.pdf
- */
-static int gpmc_probe_8250(struct platform_device *pdev,
-                               struct device_node *child)
-{
-       struct resource res;
-       unsigned long base;
-       int ret, cs;
-
-       if (of_property_read_u32(child, "reg", &cs) < 0) {
-               dev_err(&pdev->dev, "%s has no 'reg' property\n",
-                       child->full_name);
-               return -ENODEV;
-       }
-
-       if (of_address_to_resource(child, 0, &res) < 0) {
-               dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
-                       child->full_name);
-               return -ENODEV;
-       }
-
-       ret = gpmc_cs_request(cs, resource_size(&res), &base);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
-               return ret;
-       }
-
-       if (of_platform_device_create(child, NULL, &pdev->dev))
-               return 0;
-
-       dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
-
-       return -ENODEV;
-}
-
 static int gpmc_probe_dt(struct platform_device *pdev)
 {
        int ret;
@@ -1618,10 +1599,9 @@ static int gpmc_probe_dt(struct platform_device *pdev)
                else if (of_node_cmp(child->name, "onenand") == 0)
                        ret = gpmc_probe_onenand_child(pdev, child);
                else if (of_node_cmp(child->name, "ethernet") == 0 ||
-                        of_node_cmp(child->name, "nor") == 0)
+                        of_node_cmp(child->name, "nor") == 0 ||
+                        of_node_cmp(child->name, "uart") == 0)
                        ret = gpmc_probe_generic_child(pdev, child);
-               else if (of_node_cmp(child->name, "8250") == 0)
-                       ret = gpmc_probe_8250(pdev, child);
 
                if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
                         __func__, child->full_name))
index 8cc7d331437d844a3b0ba5b3d2afb844b2de5d06..3e97c6c8ecf139781c7f0d03a68583d5ff81ea2b 100644 (file)
@@ -76,6 +76,13 @@ static inline void omap_barrier_reserve_memblock(void)
 { }
 #endif
 
+#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
 void set_cntfreq(void);
+#else
+static inline void set_cntfreq(void)
+{
+}
+#endif
+
 #endif /* __ASSEMBLER__ */
 #endif /* OMAP_ARCH_OMAP_SECURE_H */
index 57911430324e30cdfdfb1408d0272c8b6bf0dde4..b39efd46abf991827169a6c17a6aa91f3dfeb39f 100644 (file)
@@ -35,7 +35,6 @@
 #include "iomap.h"
 #include "common.h"
 #include "mmc.h"
-#include "hsmmc.h"
 #include "prminst44xx.h"
 #include "prcm_mpu44xx.h"
 #include "omap4-sar-layout.h"
@@ -284,59 +283,3 @@ skip_errata_init:
        omap_wakeupgen_init();
        irqchip_init();
 }
-
-#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
-{
-       int irq = 0;
-       struct platform_device *pdev = container_of(dev,
-                               struct platform_device, dev);
-       struct omap_mmc_platform_data *pdata = dev->platform_data;
-
-       /* Setting MMC1 Card detect Irq */
-       if (pdev->id == 0) {
-               irq = twl6030_mmc_card_detect_config();
-               if (irq < 0) {
-                       dev_err(dev, "%s: Error card detect config(%d)\n",
-                               __func__, irq);
-                       return irq;
-               }
-               pdata->slots[0].card_detect_irq = irq;
-               pdata->slots[0].card_detect = twl6030_mmc_card_detect;
-       }
-       return 0;
-}
-
-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
-       struct omap_mmc_platform_data *pdata;
-
-       /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
-       if (!dev) {
-               pr_err("Failed %s\n", __func__);
-               return;
-       }
-       pdata = dev->platform_data;
-       pdata->init =   omap4_twl6030_hsmmc_late_init;
-}
-
-int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
-{
-       struct omap2_hsmmc_info *c;
-
-       omap_hsmmc_init(controllers);
-       for (c = controllers; c->mmc; c++) {
-               /* pdev can be null if CONFIG_MMC_OMAP_HS is not set */
-               if (!c->pdev)
-                       continue;
-               omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-       }
-
-       return 0;
-}
-#else
-int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
-{
-       return 0;
-}
-#endif
index 53f0735817bb7cf984f3fada24c7e8960941860c..e0a398cf28d80a409e25055c19ad44baef25d7fc 100644 (file)
@@ -183,6 +183,10 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 odbfd_exit1:
        kfree(hwmods);
 odbfd_exit:
+       /* if data/we are at fault.. load up a fail handler */
+       if (ret)
+               pdev->dev.pm_domain = &omap_device_fail_pm_domain;
+
        return ret;
 }
 
@@ -604,6 +608,19 @@ static int _od_runtime_resume(struct device *dev)
 
        return pm_generic_runtime_resume(dev);
 }
+
+static int _od_fail_runtime_suspend(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
+static int _od_fail_runtime_resume(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
 #endif
 
 #ifdef CONFIG_SUSPEND
@@ -657,6 +674,13 @@ static int _od_resume_noirq(struct device *dev)
 #define _od_resume_noirq NULL
 #endif
 
+struct dev_pm_domain omap_device_fail_pm_domain = {
+       .ops = {
+               SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
+                                  _od_fail_runtime_resume, NULL)
+       }
+};
+
 struct dev_pm_domain omap_device_pm_domain = {
        .ops = {
                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
index 17ca1aec271033d7551c2ffd4cf22fd0c4724fb2..78c02b355179894126f5e2e75f835fc1d753060a 100644 (file)
@@ -29,6 +29,7 @@
 #include "omap_hwmod.h"
 
 extern struct dev_pm_domain omap_device_pm_domain;
+extern struct dev_pm_domain omap_device_fail_pm_domain;
 
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN      0
index e3f0ecaf87dd76c3b075c389173ac89faff04a6a..8a1b5e0bad40df2adbab8b202e0dd87602fe7921 100644 (file)
@@ -399,7 +399,7 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
 }
 
 /**
- * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
+ * _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v
  * @oh: struct omap_hwmod *
  * @v: pointer to register contents to modify
  *
@@ -426,6 +426,36 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v
+ * @oh: struct omap_hwmod *
+ * @v: pointer to register contents to modify
+ *
+ * Clear the SOFTRESET bit in @v for hwmod @oh.  Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int _clear_softreset(struct omap_hwmod *oh, u32 *v)
+{
+       u32 softrst_mask;
+
+       if (!oh->class->sysc ||
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
+               return -EINVAL;
+
+       if (!oh->class->sysc->sysc_fields) {
+               WARN(1,
+                    "omap_hwmod: %s: sysc_fields absent for sysconfig class\n",
+                    oh->name);
+               return -EINVAL;
+       }
+
+       softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
+
+       *v &= ~softrst_mask;
+
+       return 0;
+}
+
 /**
  * _wait_softreset_complete - wait for an OCP softreset to complete
  * @oh: struct omap_hwmod * to wait on
@@ -785,6 +815,7 @@ static int _init_interface_clks(struct omap_hwmod *oh)
                        pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
                                   oh->name, os->clk);
                        ret = -EINVAL;
+                       continue;
                }
                os->_clk = c;
                /*
@@ -821,6 +852,7 @@ static int _init_opt_clks(struct omap_hwmod *oh)
                        pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
                                   oh->name, oc->clk);
                        ret = -EINVAL;
+                       continue;
                }
                oc->_clk = c;
                /*
@@ -1911,6 +1943,12 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        ret = _set_softreset(oh, &v);
        if (ret)
                goto dis_opt_clks;
+
+       _write_sysconfig(v, oh);
+       ret = _clear_softreset(oh, &v);
+       if (ret)
+               goto dis_opt_clks;
+
        _write_sysconfig(v, oh);
 
        if (oh->class->sysc->srst_udelay)
@@ -2326,38 +2364,80 @@ static int _shutdown(struct omap_hwmod *oh)
        return 0;
 }
 
+static int of_dev_find_hwmod(struct device_node *np,
+                            struct omap_hwmod *oh)
+{
+       int count, i, res;
+       const char *p;
+
+       count = of_property_count_strings(np, "ti,hwmods");
+       if (count < 1)
+               return -ENODEV;
+
+       for (i = 0; i < count; i++) {
+               res = of_property_read_string_index(np, "ti,hwmods",
+                                                   i, &p);
+               if (res)
+                       continue;
+               if (!strcmp(p, oh->name)) {
+                       pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n",
+                                np->name, i, oh->name);
+                       return i;
+               }
+       }
+
+       return -ENODEV;
+}
+
 /**
  * of_dev_hwmod_lookup - look up needed hwmod from dt blob
  * @np: struct device_node *
  * @oh: struct omap_hwmod *
+ * @index: index of the entry found
+ * @found: struct device_node * found or NULL
  *
  * Parse the dt blob and find out needed hwmod. Recursive function is
  * implemented to take care hierarchical dt blob parsing.
- * Return: The device node on success or NULL on failure.
+ * Return: Returns 0 on success, -ENODEV when not found.
  */
-static struct device_node *of_dev_hwmod_lookup(struct device_node *np,
-                                               struct omap_hwmod *oh)
+static int of_dev_hwmod_lookup(struct device_node *np,
+                              struct omap_hwmod *oh,
+                              int *index,
+                              struct device_node **found)
 {
-       struct device_node *np0 = NULL, *np1 = NULL;
-       const char *p;
+       struct device_node *np0 = NULL;
+       int res;
+
+       res = of_dev_find_hwmod(np, oh);
+       if (res >= 0) {
+               *found = np;
+               *index = res;
+               return 0;
+       }
 
        for_each_child_of_node(np, np0) {
-               if (of_find_property(np0, "ti,hwmods", NULL)) {
-                       p = of_get_property(np0, "ti,hwmods", NULL);
-                       if (!strcmp(p, oh->name))
-                               return np0;
-                       np1 = of_dev_hwmod_lookup(np0, oh);
-                       if (np1)
-                               return np1;
+               struct device_node *fc;
+               int i;
+
+               res = of_dev_hwmod_lookup(np0, oh, &i, &fc);
+               if (res == 0) {
+                       *found = fc;
+                       *index = i;
+                       return 0;
                }
        }
-       return NULL;
+
+       *found = NULL;
+       *index = 0;
+
+       return -ENODEV;
 }
 
 /**
  * _init_mpu_rt_base - populate the virtual address for a hwmod
  * @oh: struct omap_hwmod * to locate the virtual address
  * @data: (unused, caller should pass NULL)
+ * @index: index of the reg entry iospace in device tree
  * @np: struct device_node * of the IP block's device node in the DT data
  *
  * Cache the virtual address used by the MPU to access this IP block's
@@ -2368,7 +2448,7 @@ static struct device_node *of_dev_hwmod_lookup(struct device_node *np,
  * -ENXIO on absent or invalid register target address space.
  */
 static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
-                                   struct device_node *np)
+                                   int index, struct device_node *np)
 {
        struct omap_hwmod_addr_space *mem;
        void __iomem *va_start = NULL;
@@ -2390,13 +2470,17 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
                if (!np)
                        return -ENXIO;
 
-               va_start = of_iomap(np, oh->mpu_rt_idx);
+               va_start = of_iomap(np, index + oh->mpu_rt_idx);
        } else {
                va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
        }
 
        if (!va_start) {
-               pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+               if (mem)
+                       pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+               else
+                       pr_err("omap_hwmod: %s: Missing dt reg%i for %s\n",
+                              oh->name, index, np->full_name);
                return -ENXIO;
        }
 
@@ -2422,17 +2506,29 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
  */
 static int __init _init(struct omap_hwmod *oh, void *data)
 {
-       int r;
+       int r, index;
        struct device_node *np = NULL;
 
        if (oh->_state != _HWMOD_STATE_REGISTERED)
                return 0;
 
-       if (of_have_populated_dt())
-               np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
+       if (of_have_populated_dt()) {
+               struct device_node *bus;
+
+               bus = of_find_node_by_name(NULL, "ocp");
+               if (!bus)
+                       return -ENODEV;
+
+               r = of_dev_hwmod_lookup(bus, oh, &index, &np);
+               if (r)
+                       pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
+               else if (np && index)
+                       pr_warn("omap_hwmod: %s using broken dt data from %s\n",
+                               oh->name, np->name);
+       }
 
        if (oh->class->sysc) {
-               r = _init_mpu_rt_base(oh, NULL, np);
+               r = _init_mpu_rt_base(oh, NULL, index, np);
                if (r < 0) {
                        WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
                             oh->name);
@@ -3169,6 +3265,11 @@ int omap_hwmod_softreset(struct omap_hwmod *oh)
                goto error;
        _write_sysconfig(v, oh);
 
+       ret = _clear_softreset(oh, &v);
+       if (ret)
+               goto error;
+       _write_sysconfig(v, oh);
+
 error:
        return ret;
 }
index 56cebb05509e15c0054f342e158a21214b7a6603..d23c77fadb31036058ab7b750cf02495d2ef33ab 100644 (file)
@@ -796,7 +796,7 @@ struct omap_hwmod omap2xxx_counter_32k_hwmod = {
 
 /* gpmc */
 static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -841,7 +841,7 @@ static struct omap_hwmod_class omap2_rng_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap2_rng_mpu_irqs[] = {
-       { .irq = 52 },
+       { .irq = 52 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index 9e56fabd7fa3b834fbe09a463facd521592107a7..4c3b1e6df50806700cbcfc3c4f582650b36cc3a3 100644 (file)
@@ -1943,7 +1943,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_usb_host_hs_sysc = {
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
        .sysc_fields    = &omap_hwmod_sysc_type1,
@@ -2021,15 +2022,7 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 };
 
 /*
@@ -2172,7 +2165,7 @@ static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -3006,7 +2999,7 @@ static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_isp_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_isp_irqs[] = {
-       { .irq = 24 },
+       { .irq = 24 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -3048,7 +3041,7 @@ static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_iva_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_iva_irqs[] = {
-       { .irq = 28 },
+       { .irq = 28 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index 1e5b12cb8246290cc8e2865036e0f4a291513f9c..3318cae96e7d1e94a8699192d1c00512c8f34f38 100644 (file)
@@ -2937,7 +2937,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET),
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
                           MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
@@ -3001,15 +3001,7 @@ static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 };
 
 /*
index 9e08d6994a0b09c44760e03323c9543f720ad026..e297d6231c3aa3c35910d25f3115466be2d453ab 100644 (file)
@@ -1544,7 +1544,8 @@ static struct omap_hwmod_class_sysconfig omap54xx_usb_host_hs_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
                           MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
@@ -1598,15 +1599,7 @@ static struct omap_hwmod omap54xx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
        .main_clk       = "l3init_60m_fclk",
        .prcm = {
                .omap4 = {
index db32d5380b118cda247e6f8e863bc14906eed6bc..18f333c440db3b72ff49577ef71d24b64dbcc916 100644 (file)
@@ -1637,7 +1637,7 @@ static struct omap_hwmod dra7xx_uart1_hwmod = {
        .class          = &dra7xx_uart_hwmod_class,
        .clkdm_name     = "l4per_clkdm",
        .main_clk       = "uart1_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP2UART1_FLAGS,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
index 10c71450cf632c2816c40ab22207ad65ef09dd0b..39f020c982e8b3a41d547d9d45b60c46cb08877b 100644 (file)
@@ -139,6 +139,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 
 static struct pdata_init pdata_quirks[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP3
+       { "nokia,omap3-n900", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n9", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n950", hsmmc2_internal_input_clk, },
        { "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
index 93b80e5da8d4d5888982b30ffed5d5dc5f2cc470..1f3770a8a7286fd7650f76d46917408d0ff52b96 100644 (file)
@@ -120,7 +120,7 @@ static void omap3_save_secure_ram_context(void)
                 * will hang the system.
                 */
                pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
-               ret = _omap_save_secure_sram((u32 *)
+               ret = _omap_save_secure_sram((u32 *)(unsigned long)
                                __pa(omap3_secure_ram_storage));
                pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
                /* Following is for error tracking, it should not happen */
index e233dfcbc18670ff6f0e507df07b6f9c09289534..93a2a6e4260f46c6b1580d7dbf50188dbc7154a3 100644 (file)
@@ -128,7 +128,8 @@ skip_voltdm:
        for (i = 0; i < pwrdm->banks; i++)
                pwrdm->ret_mem_off_counter[i] = 0;
 
-       arch_pwrdm->pwrdm_wait_transition(pwrdm);
+       if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
+               arch_pwrdm->pwrdm_wait_transition(pwrdm);
        pwrdm->state = pwrdm_read_pwrst(pwrdm);
        pwrdm->state_counter[pwrdm->state] = 1;
 
index 7a976065e1389cf8396c28e5da37ca6574e8cad4..8d95aa543ef562f65fe18e6ed0fd07ed23dbc505 100644 (file)
@@ -43,7 +43,7 @@ extern void omap4_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
-       defined(CONFIG_SOC_DRA7XX)
+       defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
 void omap44xx_prm_reconfigure_io_chain(void);
 #else
 static inline void omap44xx_prm_reconfigure_io_chain(void)
index 2a086e8373eb7bf1104892784aba7a5236a3bd5b..958cd6af93842566308a33d11f1799dd78f332d9 100644 (file)
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <mach/irqs.h>
+
 #define LUBBOCK_ETH_PHYS       PXA_CS3_PHYS
 
 #define LUBBOCK_FPGA_PHYS      PXA_CS2_PHYS
index 0d5dd646f61fa7d5aa743d4c68f162a2453d00e0..263b15249b5b803436709e1e5e268b9552bedef0 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <mach/regs-ost.h>
 #include <mach/reset.h>
+#include <mach/smemc.h>
 
 unsigned int reset_status;
 EXPORT_SYMBOL(reset_status);
@@ -81,6 +82,12 @@ static void do_hw_reset(void)
        writel_relaxed(OSSR_M3, OSSR);
        /* ... in 100 ms */
        writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3);
+       /*
+        * SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71)
+        * we put SDRAM into self-refresh to prevent that
+        */
+       while (1)
+               writel_relaxed(MDREFR_SLFRSH, MDREFR);
 }
 
 void pxa_restart(enum reboot_mode mode, const char *cmd)
@@ -104,4 +111,3 @@ void pxa_restart(enum reboot_mode mode, const char *cmd)
                break;
        }
 }
-
index 0206b915a6f6e07e3de75854617284f9c56aa870..ef5557b807ed95bbfce94ecc1c3ec17549767aec 100644 (file)
@@ -425,57 +425,57 @@ static struct platform_device tosa_power_device = {
  * Tosa Keyboard
  */
 static const uint32_t tosakbd_keymap[] = {
-       KEY(0, 2, KEY_W),
-       KEY(0, 6, KEY_K),
-       KEY(0, 7, KEY_BACKSPACE),
-       KEY(0, 8, KEY_P),
-       KEY(1, 1, KEY_Q),
-       KEY(1, 2, KEY_E),
-       KEY(1, 3, KEY_T),
-       KEY(1, 4, KEY_Y),
-       KEY(1, 6, KEY_O),
-       KEY(1, 7, KEY_I),
-       KEY(1, 8, KEY_COMMA),
-       KEY(2, 1, KEY_A),
-       KEY(2, 2, KEY_D),
-       KEY(2, 3, KEY_G),
-       KEY(2, 4, KEY_U),
-       KEY(2, 6, KEY_L),
-       KEY(2, 7, KEY_ENTER),
-       KEY(2, 8, KEY_DOT),
-       KEY(3, 1, KEY_Z),
-       KEY(3, 2, KEY_C),
-       KEY(3, 3, KEY_V),
-       KEY(3, 4, KEY_J),
-       KEY(3, 5, TOSA_KEY_ADDRESSBOOK),
-       KEY(3, 6, TOSA_KEY_CANCEL),
-       KEY(3, 7, TOSA_KEY_CENTER),
-       KEY(3, 8, TOSA_KEY_OK),
-       KEY(3, 9, KEY_LEFTSHIFT),
-       KEY(4, 1, KEY_S),
-       KEY(4, 2, KEY_R),
-       KEY(4, 3, KEY_B),
-       KEY(4, 4, KEY_N),
-       KEY(4, 5, TOSA_KEY_CALENDAR),
-       KEY(4, 6, TOSA_KEY_HOMEPAGE),
-       KEY(4, 7, KEY_LEFTCTRL),
-       KEY(4, 8, TOSA_KEY_LIGHT),
-       KEY(4, 10, KEY_RIGHTSHIFT),
-       KEY(5, 1, KEY_TAB),
-       KEY(5, 2, KEY_SLASH),
-       KEY(5, 3, KEY_H),
-       KEY(5, 4, KEY_M),
-       KEY(5, 5, TOSA_KEY_MENU),
-       KEY(5, 7, KEY_UP),
-       KEY(5, 11, TOSA_KEY_FN),
-       KEY(6, 1, KEY_X),
-       KEY(6, 2, KEY_F),
-       KEY(6, 3, KEY_SPACE),
-       KEY(6, 4, KEY_APOSTROPHE),
-       KEY(6, 5, TOSA_KEY_MAIL),
-       KEY(6, 6, KEY_LEFT),
-       KEY(6, 7, KEY_DOWN),
-       KEY(6, 8, KEY_RIGHT),
+       KEY(0, 1, KEY_W),
+       KEY(0, 5, KEY_K),
+       KEY(0, 6, KEY_BACKSPACE),
+       KEY(0, 7, KEY_P),
+       KEY(1, 0, KEY_Q),
+       KEY(1, 1, KEY_E),
+       KEY(1, 2, KEY_T),
+       KEY(1, 3, KEY_Y),
+       KEY(1, 5, KEY_O),
+       KEY(1, 6, KEY_I),
+       KEY(1, 7, KEY_COMMA),
+       KEY(2, 0, KEY_A),
+       KEY(2, 1, KEY_D),
+       KEY(2, 2, KEY_G),
+       KEY(2, 3, KEY_U),
+       KEY(2, 5, KEY_L),
+       KEY(2, 6, KEY_ENTER),
+       KEY(2, 7, KEY_DOT),
+       KEY(3, 0, KEY_Z),
+       KEY(3, 1, KEY_C),
+       KEY(3, 2, KEY_V),
+       KEY(3, 3, KEY_J),
+       KEY(3, 4, TOSA_KEY_ADDRESSBOOK),
+       KEY(3, 5, TOSA_KEY_CANCEL),
+       KEY(3, 6, TOSA_KEY_CENTER),
+       KEY(3, 7, TOSA_KEY_OK),
+       KEY(3, 8, KEY_LEFTSHIFT),
+       KEY(4, 0, KEY_S),
+       KEY(4, 1, KEY_R),
+       KEY(4, 2, KEY_B),
+       KEY(4, 3, KEY_N),
+       KEY(4, 4, TOSA_KEY_CALENDAR),
+       KEY(4, 5, TOSA_KEY_HOMEPAGE),
+       KEY(4, 6, KEY_LEFTCTRL),
+       KEY(4, 7, TOSA_KEY_LIGHT),
+       KEY(4, 9, KEY_RIGHTSHIFT),
+       KEY(5, 0, KEY_TAB),
+       KEY(5, 1, KEY_SLASH),
+       KEY(5, 2, KEY_H),
+       KEY(5, 3, KEY_M),
+       KEY(5, 4, TOSA_KEY_MENU),
+       KEY(5, 6, KEY_UP),
+       KEY(5, 10, TOSA_KEY_FN),
+       KEY(6, 0, KEY_X),
+       KEY(6, 1, KEY_F),
+       KEY(6, 2, KEY_SPACE),
+       KEY(6, 3, KEY_APOSTROPHE),
+       KEY(6, 4, TOSA_KEY_MAIL),
+       KEY(6, 5, KEY_LEFT),
+       KEY(6, 6, KEY_DOWN),
+       KEY(6, 7, KEY_RIGHT),
 };
 
 static struct matrix_keymap_data tosakbd_keymap_data = {
index 2cb8dc55b50ecbc4aa612ab805b52f03efec3eb9..7094bccbae913ae953594a51e900ce13f8e4137d 100644 (file)
@@ -17,9 +17,10 @@ config CPU_S3C6410
        help
          Enable S3C6410 CPU support
 
-config S3C64XX_DMA
-       bool "S3C64XX DMA"
-       select S3C_DMA
+config S3C64XX_PL080
+       bool "S3C64XX DMA using generic PL08x driver"
+       select AMBA_PL08X
+       select SAMSUNG_DMADEV
 
 config S3C64XX_SETUP_SDHCI
        bool
index 6faedcffce040d0cfc041c9d3b559ff1be94a207..58069a702a435046ae627bff9ab4e8c689b1aa3c 100644 (file)
@@ -26,7 +26,7 @@ obj-$(CONFIG_CPU_IDLE)                += cpuidle.o
 
 # DMA support
 
-obj-$(CONFIG_S3C64XX_DMA)      += dma.o
+obj-$(CONFIG_S3C64XX_PL080)    += pl080.o
 
 # Device support
 
index bd3bd562011e1515198e924627fd7165f57cb3dd..7043e7a3a67ed868f9e4465d7afae197619dcdc9 100644 (file)
@@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void);
 static inline int s3c64xx_pm_late_initcall(void) { return 0; }
 #endif
 
+#ifdef CONFIG_S3C64XX_PL080
+extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
+extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
+#endif
+
 #endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
deleted file mode 100644 (file)
index 7e22c21..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/dma.c
- *
- * Copyright 2009 Openmoko, Inc.
- * Copyright 2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C64XX DMA core
- *
- * 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.
-*/
-
-/*
- * NOTE: Code in this file is not used when booting with Device Tree support.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/dmapool.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/amba/pl080.h>
-#include <linux/of.h>
-
-#include <mach/dma.h>
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#include "regs-sys.h"
-
-/* dma channel state information */
-
-struct s3c64xx_dmac {
-       struct device           dev;
-       struct clk              *clk;
-       void __iomem            *regs;
-       struct s3c2410_dma_chan *channels;
-       enum dma_ch              chanbase;
-};
-
-/* pool to provide LLI buffers */
-static struct dma_pool *dma_pool;
-
-/* Debug configuration and code */
-
-static unsigned char debug_show_buffs = 0;
-
-static void dbg_showchan(struct s3c2410_dma_chan *chan)
-{
-       pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
-                chan->number,
-                readl(chan->regs + PL080_CH_SRC_ADDR),
-                readl(chan->regs + PL080_CH_DST_ADDR),
-                readl(chan->regs + PL080_CH_LLI),
-                readl(chan->regs + PL080_CH_CONTROL),
-                readl(chan->regs + PL080S_CH_CONTROL2),
-                readl(chan->regs + PL080S_CH_CONFIG));
-}
-
-static void show_lli(struct pl080s_lli *lli)
-{
-       pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
-                lli, lli->src_addr, lli->dst_addr, lli->next_lli,
-                lli->control0, lli->control1);
-}
-
-static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
-{
-       struct s3c64xx_dma_buff *ptr;
-       struct s3c64xx_dma_buff *end;
-
-       pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
-                chan->number, chan->next, chan->curr, chan->end);
-
-       ptr = chan->next;
-       end = chan->end;
-
-       if (debug_show_buffs) {
-               for (; ptr != NULL; ptr = ptr->next) {
-                       pr_debug("DMA%d: %08x ",
-                                chan->number, ptr->lli_dma);
-                       show_lli(ptr->lli);
-               }
-       }
-}
-
-/* End of Debug */
-
-static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
-{
-       struct s3c2410_dma_chan *chan;
-       unsigned int start, offs;
-
-       start = 0;
-
-       if (channel >= DMACH_PCM1_TX)
-               start = 8;
-
-       for (offs = 0; offs < 8; offs++) {
-               chan = &s3c2410_chans[start + offs];
-               if (!chan->in_use)
-                       goto found;
-       }
-
-       return NULL;
-
-found:
-       s3c_dma_chan_map[channel] = chan;
-       return chan;
-}
-
-int s3c2410_dma_config(enum dma_ch channel, int xferunit)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       switch (xferunit) {
-       case 1:
-               chan->hw_width = 0;
-               break;
-       case 2:
-               chan->hw_width = 1;
-               break;
-       case 4:
-               chan->hw_width = 2;
-               break;
-       default:
-               printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
-                                struct pl080s_lli *lli,
-                                dma_addr_t data, int size)
-{
-       dma_addr_t src, dst;
-       u32 control0, control1;
-
-       switch (chan->source) {
-       case DMA_FROM_DEVICE:
-               src = chan->dev_addr;
-               dst = data;
-               control0 = PL080_CONTROL_SRC_AHB2;
-               control0 |= PL080_CONTROL_DST_INCR;
-               break;
-
-       case DMA_TO_DEVICE:
-               src = data;
-               dst = chan->dev_addr;
-               control0 = PL080_CONTROL_DST_AHB2;
-               control0 |= PL080_CONTROL_SRC_INCR;
-               break;
-       default:
-               BUG();
-       }
-
-       /* note, we do not currently setup any of the burst controls */
-
-       control1 = size >> chan->hw_width;      /* size in no of xfers */
-       control0 |= PL080_CONTROL_PROT_SYS;     /* always in priv. mode */
-       control0 |= PL080_CONTROL_TC_IRQ_EN;    /* always fire IRQ */
-       control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
-       control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
-
-       lli->src_addr = src;
-       lli->dst_addr = dst;
-       lli->next_lli = 0;
-       lli->control0 = control0;
-       lli->control1 = control1;
-}
-
-static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
-                               struct pl080s_lli *lli)
-{
-       void __iomem *regs = chan->regs;
-
-       pr_debug("%s: LLI %p => regs\n", __func__, lli);
-       show_lli(lli);
-
-       writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
-       writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
-       writel(lli->next_lli, regs + PL080_CH_LLI);
-       writel(lli->control0, regs + PL080_CH_CONTROL);
-       writel(lli->control1, regs + PL080S_CH_CONTROL2);
-}
-
-static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
-{
-       struct s3c64xx_dmac *dmac = chan->dmac;
-       u32 config;
-       u32 bit = chan->bit;
-
-       dbg_showchan(chan);
-
-       pr_debug("%s: clearing interrupts\n", __func__);
-
-       /* clear interrupts */
-       writel(bit, dmac->regs + PL080_TC_CLEAR);
-       writel(bit, dmac->regs + PL080_ERR_CLEAR);
-
-       pr_debug("%s: starting channel\n", __func__);
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config |= PL080_CONFIG_ENABLE;
-       config &= ~PL080_CONFIG_HALT;
-
-       pr_debug("%s: writing config %08x\n", __func__, config);
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       return 0;
-}
-
-static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
-{
-       u32 config;
-       int timeout;
-
-       pr_debug("%s: stopping channel\n", __func__);
-
-       dbg_showchan(chan);
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config |= PL080_CONFIG_HALT;
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       timeout = 1000;
-       do {
-               config = readl(chan->regs + PL080S_CH_CONFIG);
-               pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
-               if (config & PL080_CONFIG_ACTIVE)
-                       udelay(10);
-               else
-                       break;
-               } while (--timeout > 0);
-
-       if (config & PL080_CONFIG_ACTIVE) {
-               printk(KERN_ERR "%s: channel still active\n", __func__);
-               return -EFAULT;
-       }
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config &= ~PL080_CONFIG_ENABLE;
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       return 0;
-}
-
-static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
-                                        struct s3c64xx_dma_buff *buf,
-                                        enum s3c2410_dma_buffresult result)
-{
-       if (chan->callback_fn != NULL)
-               (chan->callback_fn)(chan, buf->pw, 0, result);
-}
-
-static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
-{
-       dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
-       kfree(buff);
-}
-
-static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
-{
-       struct s3c64xx_dma_buff *buff, *next;
-       u32 config;
-
-       dbg_showchan(chan);
-
-       pr_debug("%s: flushing channel\n", __func__);
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config &= ~PL080_CONFIG_ENABLE;
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       /* dump all the buffers associated with this channel */
-
-       for (buff = chan->curr; buff != NULL; buff = next) {
-               next = buff->next;
-               pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
-
-               s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
-               s3c64xx_dma_freebuff(buff);
-       }
-
-       chan->curr = chan->next = chan->end = NULL;
-
-       return 0;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       switch (op) {
-       case S3C2410_DMAOP_START:
-               return s3c64xx_dma_start(chan);
-
-       case S3C2410_DMAOP_STOP:
-               return s3c64xx_dma_stop(chan);
-
-       case S3C2410_DMAOP_FLUSH:
-               return s3c64xx_dma_flush(chan);
-
-       /* believe PAUSE/RESUME are no-ops */
-       case S3C2410_DMAOP_PAUSE:
-       case S3C2410_DMAOP_RESUME:
-       case S3C2410_DMAOP_STARTED:
-       case S3C2410_DMAOP_TIMEOUT:
-               return 0;
-       }
-
-       return -ENOENT;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* s3c2410_dma_enque
- *
- */
-
-int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
-                       dma_addr_t data, int size)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-       struct s3c64xx_dma_buff *next;
-       struct s3c64xx_dma_buff *buff;
-       struct pl080s_lli *lli;
-       unsigned long flags;
-       int ret;
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC);
-       if (!buff) {
-               printk(KERN_ERR "%s: no memory for buffer\n", __func__);
-               return -ENOMEM;
-       }
-
-       lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma);
-       if (!lli) {
-               printk(KERN_ERR "%s: no memory for lli\n", __func__);
-               ret = -ENOMEM;
-               goto err_buff;
-       }
-
-       pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
-                __func__, buff, data, lli, (u32)buff->lli_dma, size);
-
-       buff->lli = lli;
-       buff->pw = id;
-
-       s3c64xx_dma_fill_lli(chan, lli, data, size);
-
-       local_irq_save(flags);
-
-       if ((next = chan->next) != NULL) {
-               struct s3c64xx_dma_buff *end = chan->end;
-               struct pl080s_lli *endlli = end->lli;
-
-               pr_debug("enquing onto channel\n");
-
-               end->next = buff;
-               endlli->next_lli = buff->lli_dma;
-
-               if (chan->flags & S3C2410_DMAF_CIRCULAR) {
-                       struct s3c64xx_dma_buff *curr = chan->curr;
-                       lli->next_lli = curr->lli_dma;
-               }
-
-               if (next == chan->curr) {
-                       writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
-                       chan->next = buff;
-               }
-
-               show_lli(endlli);
-               chan->end = buff;
-       } else {
-               pr_debug("enquing onto empty channel\n");
-
-               chan->curr = buff;
-               chan->next = buff;
-               chan->end = buff;
-
-               s3c64xx_lli_to_regs(chan, lli);
-       }
-
-       local_irq_restore(flags);
-
-       show_lli(lli);
-
-       dbg_showchan(chan);
-       dbg_showbuffs(chan);
-       return 0;
-
-err_buff:
-       kfree(buff);
-       return ret;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-
-int s3c2410_dma_devconfig(enum dma_ch channel,
-                         enum dma_data_direction source,
-                         unsigned long devaddr)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-       u32 peripheral;
-       u32 config = 0;
-
-       pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
-                __func__, channel, source, devaddr, chan);
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       peripheral = (chan->peripheral & 0xf);
-       chan->source = source;
-       chan->dev_addr = devaddr;
-
-       pr_debug("%s: peripheral %d\n", __func__, peripheral);
-
-       switch (source) {
-       case DMA_FROM_DEVICE:
-               config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-               config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
-               break;
-       case DMA_TO_DEVICE:
-               config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-               config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
-               break;
-       default:
-               printk(KERN_ERR "%s: bad source\n", __func__);
-               return -EINVAL;
-       }
-
-       /* allow TC and ERR interrupts */
-       config |= PL080_CONFIG_TC_IRQ_MASK;
-       config |= PL080_CONFIG_ERR_IRQ_MASK;
-
-       pr_debug("%s: config %08x\n", __func__, config);
-
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-
-int s3c2410_dma_getposition(enum dma_ch channel,
-                           dma_addr_t *src, dma_addr_t *dst)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       if (src != NULL)
-               *src = readl(chan->regs + PL080_CH_SRC_ADDR);
-
-       if (dst != NULL)
-               *dst = readl(chan->regs + PL080_CH_DST_ADDR);
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(enum dma_ch channel,
-                       struct s3c2410_dma_client *client,
-                       void *dev)
-{
-       struct s3c2410_dma_chan *chan;
-       unsigned long flags;
-
-       pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
-                channel, client->name, dev);
-
-       local_irq_save(flags);
-
-       chan = s3c64xx_dma_map_channel(channel);
-       if (chan == NULL) {
-               local_irq_restore(flags);
-               return -EBUSY;
-       }
-
-       dbg_showchan(chan);
-
-       chan->client = client;
-       chan->in_use = 1;
-       chan->peripheral = channel;
-       chan->flags = 0;
-
-       local_irq_restore(flags);
-
-       /* need to setup */
-
-       pr_debug("%s: channel initialised, %p\n", __func__, chan);
-
-       return chan->number | DMACH_LOW_LEVEL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
-
-int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-       unsigned long flags;
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       local_irq_save(flags);
-
-       if (chan->client != client) {
-               printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
-                      channel, chan->client, client);
-       }
-
-       /* sort out stopping and freeing the channel */
-
-
-       chan->client = NULL;
-       chan->in_use = 0;
-
-       if (!(channel & DMACH_LOW_LEVEL))
-               s3c_dma_chan_map[channel] = NULL;
-
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
-{
-       struct s3c64xx_dmac *dmac = pw;
-       struct s3c2410_dma_chan *chan;
-       enum s3c2410_dma_buffresult res;
-       u32 tcstat, errstat;
-       u32 bit;
-       int offs;
-
-       tcstat = readl(dmac->regs + PL080_TC_STATUS);
-       errstat = readl(dmac->regs + PL080_ERR_STATUS);
-
-       for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
-               struct s3c64xx_dma_buff *buff;
-
-               if (!(errstat & bit) && !(tcstat & bit))
-                       continue;
-
-               chan = dmac->channels + offs;
-               res = S3C2410_RES_ERR;
-
-               if (tcstat & bit) {
-                       writel(bit, dmac->regs + PL080_TC_CLEAR);
-                       res = S3C2410_RES_OK;
-               }
-
-               if (errstat & bit)
-                       writel(bit, dmac->regs + PL080_ERR_CLEAR);
-
-               /* 'next' points to the buffer that is next to the
-                * currently active buffer.
-                * For CIRCULAR queues, 'next' will be same as 'curr'
-                * when 'end' is the active buffer.
-                */
-               buff = chan->curr;
-               while (buff && buff != chan->next
-                               && buff->next != chan->next)
-                       buff = buff->next;
-
-               if (!buff)
-                       BUG();
-
-               if (buff == chan->next)
-                       buff = chan->end;
-
-               s3c64xx_dma_bufffdone(chan, buff, res);
-
-               /* Free the node and update curr, if non-circular queue */
-               if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
-                       chan->curr = buff->next;
-                       s3c64xx_dma_freebuff(buff);
-               }
-
-               /* Update 'next' */
-               buff = chan->next;
-               if (chan->next == chan->end) {
-                       chan->next = chan->curr;
-                       if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
-                               chan->end = NULL;
-               } else {
-                       chan->next = buff->next;
-               }
-       }
-
-       return IRQ_HANDLED;
-}
-
-static struct bus_type dma_subsys = {
-       .name           = "s3c64xx-dma",
-       .dev_name       = "s3c64xx-dma",
-};
-
-static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
-                            int irq, unsigned int base)
-{
-       struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
-       struct s3c64xx_dmac *dmac;
-       char clkname[16];
-       void __iomem *regs;
-       void __iomem *regptr;
-       int err, ch;
-
-       dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
-       if (!dmac) {
-               printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
-               return -ENOMEM;
-       }
-
-       dmac->dev.id = chno / 8;
-       dmac->dev.bus = &dma_subsys;
-
-       err = device_register(&dmac->dev);
-       if (err) {
-               printk(KERN_ERR "%s: failed to register device\n", __func__);
-               goto err_alloc;
-       }
-
-       regs = ioremap(base, 0x200);
-       if (!regs) {
-               printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
-               err = -ENXIO;
-               goto err_dev;
-       }
-
-       snprintf(clkname, sizeof(clkname), "dma%d", dmac->dev.id);
-
-       dmac->clk = clk_get(NULL, clkname);
-       if (IS_ERR(dmac->clk)) {
-               printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
-               err = PTR_ERR(dmac->clk);
-               goto err_map;
-       }
-
-       clk_prepare_enable(dmac->clk);
-
-       dmac->regs = regs;
-       dmac->chanbase = chbase;
-       dmac->channels = chptr;
-
-       err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
-       if (err < 0) {
-               printk(KERN_ERR "%s: failed to get irq\n", __func__);
-               goto err_clk;
-       }
-
-       regptr = regs + PL080_Cx_BASE(0);
-
-       for (ch = 0; ch < 8; ch++, chptr++) {
-               pr_debug("%s: registering DMA %d (%p)\n",
-                        __func__, chno + ch, regptr);
-
-               chptr->bit = 1 << ch;
-               chptr->number = chno + ch;
-               chptr->dmac = dmac;
-               chptr->regs = regptr;
-               regptr += PL080_Cx_STRIDE;
-       }
-
-       /* for the moment, permanently enable the controller */
-       writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
-
-       printk(KERN_INFO "PL080: IRQ %d, at %p, channels %d..%d\n",
-              irq, regs, chno, chno+8);
-
-       return 0;
-
-err_clk:
-       clk_disable_unprepare(dmac->clk);
-       clk_put(dmac->clk);
-err_map:
-       iounmap(regs);
-err_dev:
-       device_unregister(&dmac->dev);
-err_alloc:
-       kfree(dmac);
-       return err;
-}
-
-static int __init s3c64xx_dma_init(void)
-{
-       int ret;
-
-       /* This driver is not supported when booting with device tree. */
-       if (of_have_populated_dt())
-               return -ENODEV;
-
-       printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
-
-       dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
-       if (!dma_pool) {
-               printk(KERN_ERR "%s: failed to create pool\n", __func__);
-               return -ENOMEM;
-       }
-
-       ret = subsys_system_register(&dma_subsys, NULL);
-       if (ret) {
-               printk(KERN_ERR "%s: failed to create subsys\n", __func__);
-               return -ENOMEM;
-       }
-
-       /* Set all DMA configuration to be DMA, not SDMA */
-       writel(0xffffff, S3C64XX_SDMA_SEL);
-
-       /* Register standard DMA controllers */
-       s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
-       s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
-
-       return 0;
-}
-
-arch_initcall(s3c64xx_dma_init);
index fe1a98cf0e4c7cb3a63311efec61f507e9ebf8e2..059b1fc8503727d7c84139ce7c2311cbc1a7ab8a 100644 (file)
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#define S3C_DMA_CHANNELS       (16)
+#define S3C64XX_DMA_CHAN(name)         ((unsigned long)(name))
+
+/* DMA0/SDMA0 */
+#define DMACH_UART0            S3C64XX_DMA_CHAN("uart0_tx")
+#define DMACH_UART0_SRC2       S3C64XX_DMA_CHAN("uart0_rx")
+#define DMACH_UART1            S3C64XX_DMA_CHAN("uart1_tx")
+#define DMACH_UART1_SRC2       S3C64XX_DMA_CHAN("uart1_rx")
+#define DMACH_UART2            S3C64XX_DMA_CHAN("uart2_tx")
+#define DMACH_UART2_SRC2       S3C64XX_DMA_CHAN("uart2_rx")
+#define DMACH_UART3            S3C64XX_DMA_CHAN("uart3_tx")
+#define DMACH_UART3_SRC2       S3C64XX_DMA_CHAN("uart3_rx")
+#define DMACH_PCM0_TX          S3C64XX_DMA_CHAN("pcm0_tx")
+#define DMACH_PCM0_RX          S3C64XX_DMA_CHAN("pcm0_rx")
+#define DMACH_I2S0_OUT         S3C64XX_DMA_CHAN("i2s0_tx")
+#define DMACH_I2S0_IN          S3C64XX_DMA_CHAN("i2s0_rx")
+#define DMACH_SPI0_TX          S3C64XX_DMA_CHAN("spi0_tx")
+#define DMACH_SPI0_RX          S3C64XX_DMA_CHAN("spi0_rx")
+#define DMACH_HSI_I2SV40_TX    S3C64XX_DMA_CHAN("i2s2_tx")
+#define DMACH_HSI_I2SV40_RX    S3C64XX_DMA_CHAN("i2s2_rx")
+
+/* DMA1/SDMA1 */
+#define DMACH_PCM1_TX          S3C64XX_DMA_CHAN("pcm1_tx")
+#define DMACH_PCM1_RX          S3C64XX_DMA_CHAN("pcm1_rx")
+#define DMACH_I2S1_OUT         S3C64XX_DMA_CHAN("i2s1_tx")
+#define DMACH_I2S1_IN          S3C64XX_DMA_CHAN("i2s1_rx")
+#define DMACH_SPI1_TX          S3C64XX_DMA_CHAN("spi1_tx")
+#define DMACH_SPI1_RX          S3C64XX_DMA_CHAN("spi1_rx")
+#define DMACH_AC97_PCMOUT      S3C64XX_DMA_CHAN("ac97_out")
+#define DMACH_AC97_PCMIN       S3C64XX_DMA_CHAN("ac97_in")
+#define DMACH_AC97_MICIN       S3C64XX_DMA_CHAN("ac97_mic")
+#define DMACH_PWM              S3C64XX_DMA_CHAN("pwm")
+#define DMACH_IRDA             S3C64XX_DMA_CHAN("irda")
+#define DMACH_EXTERNAL         S3C64XX_DMA_CHAN("external")
+#define DMACH_SECURITY_RX      S3C64XX_DMA_CHAN("sec_rx")
+#define DMACH_SECURITY_TX      S3C64XX_DMA_CHAN("sec_tx")
 
-/* see mach-s3c2410/dma.h for notes on dma channel numbers */
-
-/* Note, for the S3C64XX architecture we keep the DMACH_
- * defines in the order they are allocated to [S]DMA0/[S]DMA1
- * so that is easy to do DHACH_ -> DMA controller conversion
- */
 enum dma_ch {
-       /* DMA0/SDMA0 */
-       DMACH_UART0 = 0,
-       DMACH_UART0_SRC2,
-       DMACH_UART1,
-       DMACH_UART1_SRC2,
-       DMACH_UART2,
-       DMACH_UART2_SRC2,
-       DMACH_UART3,
-       DMACH_UART3_SRC2,
-       DMACH_PCM0_TX,
-       DMACH_PCM0_RX,
-       DMACH_I2S0_OUT,
-       DMACH_I2S0_IN,
-       DMACH_SPI0_TX,
-       DMACH_SPI0_RX,
-       DMACH_HSI_I2SV40_TX,
-       DMACH_HSI_I2SV40_RX,
+       DMACH_MAX = 32
+};
 
-       /* DMA1/SDMA1 */
-       DMACH_PCM1_TX = 16,
-       DMACH_PCM1_RX,
-       DMACH_I2S1_OUT,
-       DMACH_I2S1_IN,
-       DMACH_SPI1_TX,
-       DMACH_SPI1_RX,
-       DMACH_AC97_PCMOUT,
-       DMACH_AC97_PCMIN,
-       DMACH_AC97_MICIN,
-       DMACH_PWM,
-       DMACH_IRDA,
-       DMACH_EXTERNAL,
-       DMACH_RES1,
-       DMACH_RES2,
-       DMACH_SECURITY_RX,      /* SDMA1 only */
-       DMACH_SECURITY_TX,      /* SDMA1 only */
-       DMACH_MAX               /* the end */
+struct s3c2410_dma_client {
+       char    *name;
 };
 
 static inline bool samsung_dma_has_circular(void)
@@ -65,67 +62,10 @@ static inline bool samsung_dma_has_circular(void)
 
 static inline bool samsung_dma_is_dmadev(void)
 {
-       return false;
+       return true;
 }
-#define S3C2410_DMAF_CIRCULAR          (1 << 0)
-
-#include <plat/dma.h>
-
-#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
-
-struct s3c64xx_dma_buff;
-
-/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
- * @next: Pointer to next buffer in queue or ring.
- * @pw: Client provided identifier
- * @lli: Pointer to hardware descriptor this buffer is associated with.
- * @lli_dma: Hardare address of the descriptor.
- */
-struct s3c64xx_dma_buff {
-       struct s3c64xx_dma_buff *next;
-
-       void                    *pw;
-       struct pl080s_lli       *lli;
-       dma_addr_t               lli_dma;
-};
-
-struct s3c64xx_dmac;
-
-struct s3c2410_dma_chan {
-       unsigned char            number;      /* number of this dma channel */
-       unsigned char            in_use;      /* channel allocated */
-       unsigned char            bit;         /* bit for enable/disable/etc */
-       unsigned char            hw_width;
-       unsigned char            peripheral;
-
-       unsigned int             flags;
-       enum dma_data_direction  source;
-
-
-       dma_addr_t              dev_addr;
-
-       struct s3c2410_dma_client *client;
-       struct s3c64xx_dmac     *dmac;          /* pointer to controller */
-
-       void __iomem            *regs;
-
-       /* cdriver callbacks */
-       s3c2410_dma_cbfn_t       callback_fn;   /* buffer done callback */
-       s3c2410_dma_opfn_t       op_fn;         /* channel op callback */
-
-       /* buffer list and information */
-       struct s3c64xx_dma_buff *curr;          /* current dma buffer */
-       struct s3c64xx_dma_buff *next;          /* next buffer to load */
-       struct s3c64xx_dma_buff *end;           /* end of queue */
-
-       /* note, when channel is running in circular mode, curr is the
-        * first buffer enqueued, end is the last and curr is where the
-        * last buffer-done event is set-at. The buffers are not freed
-        * and the last buffer hardware descriptor points back to the
-        * first.
-        */
-};
 
-#include <plat/dma-core.h>
+#include <linux/amba/pl08x.h>
+#include <plat/dma-ops.h>
 
 #endif /* __ASM_ARCH_IRQ_H */
index 7eb9a10fc1af68d81b1dd308ebfd352d28c9e416..2fddf38192df3ad0f67bc646914e7d4121a6b41c 100644 (file)
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/clk-provider.h>
-#include <linux/irqchip.h>
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
@@ -48,15 +46,9 @@ static void __init s3c64xx_dt_map_io(void)
                panic("SoC is not S3C64xx!");
 }
 
-static void __init s3c64xx_dt_init_irq(void)
-{
-       of_clk_init(NULL);
-       samsung_wdt_reset_of_init();
-       irqchip_init();
-};
-
 static void __init s3c64xx_dt_init_machine(void)
 {
+       samsung_wdt_reset_of_init();
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -79,7 +71,6 @@ DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
        /* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
        .dt_compat      = s3c64xx_dt_compat,
        .map_io         = s3c64xx_dt_map_io,
-       .init_irq       = s3c64xx_dt_init_irq,
        .init_machine   = s3c64xx_dt_init_machine,
        .restart        = s3c64xx_dt_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/pl080.c b/arch/arm/mach-s3c64xx/pl080.c
new file mode 100644 (file)
index 0000000..901a984
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl080.h>
+#include <linux/amba/pl08x.h>
+#include <linux/of.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include "regs-sys.h"
+
+static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
+{
+       return cd->min_signal;
+}
+
+static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
+{
+}
+
+/*
+ * DMA0
+ */
+
+static struct pl08x_channel_data s3c64xx_dma0_info[] = {
+       {
+               .bus_id = "uart0_tx",
+               .min_signal = 0,
+               .max_signal = 0,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart0_rx",
+               .min_signal = 1,
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart1_tx",
+               .min_signal = 2,
+               .max_signal = 2,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart1_rx",
+               .min_signal = 3,
+               .max_signal = 3,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart2_tx",
+               .min_signal = 4,
+               .max_signal = 4,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart2_rx",
+               .min_signal = 5,
+               .max_signal = 5,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart3_tx",
+               .min_signal = 6,
+               .max_signal = 6,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart3_rx",
+               .min_signal = 7,
+               .max_signal = 7,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm0_tx",
+               .min_signal = 8,
+               .max_signal = 8,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm0_rx",
+               .min_signal = 9,
+               .max_signal = 9,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s0_tx",
+               .min_signal = 10,
+               .max_signal = 10,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s0_rx",
+               .min_signal = 11,
+               .max_signal = 11,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi0_tx",
+               .min_signal = 12,
+               .max_signal = 12,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi0_rx",
+               .min_signal = 13,
+               .max_signal = 13,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s2_tx",
+               .min_signal = 14,
+               .max_signal = 14,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s2_rx",
+               .min_signal = 15,
+               .max_signal = 15,
+               .periph_buses = PL08X_AHB2,
+       }
+};
+
+struct pl08x_platform_data s3c64xx_dma0_plat_data = {
+       .memcpy_channel = {
+               .bus_id = "memcpy",
+               .cctl_memcpy =
+                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+                       PL080_CONTROL_PROT_SYS),
+       },
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+       .get_xfer_signal = pl08x_get_xfer_signal,
+       .put_xfer_signal = pl08x_put_xfer_signal,
+       .slave_channels = s3c64xx_dma0_info,
+       .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
+                       0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
+
+/*
+ * DMA1
+ */
+
+static struct pl08x_channel_data s3c64xx_dma1_info[] = {
+       {
+               .bus_id = "pcm1_tx",
+               .min_signal = 0,
+               .max_signal = 0,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm1_rx",
+               .min_signal = 1,
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s1_tx",
+               .min_signal = 2,
+               .max_signal = 2,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s1_rx",
+               .min_signal = 3,
+               .max_signal = 3,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi1_tx",
+               .min_signal = 4,
+               .max_signal = 4,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi1_rx",
+               .min_signal = 5,
+               .max_signal = 5,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_out",
+               .min_signal = 6,
+               .max_signal = 6,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_in",
+               .min_signal = 7,
+               .max_signal = 7,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_mic",
+               .min_signal = 8,
+               .max_signal = 8,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pwm",
+               .min_signal = 9,
+               .max_signal = 9,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "irda",
+               .min_signal = 10,
+               .max_signal = 10,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "external",
+               .min_signal = 11,
+               .max_signal = 11,
+               .periph_buses = PL08X_AHB2,
+       },
+};
+
+struct pl08x_platform_data s3c64xx_dma1_plat_data = {
+       .memcpy_channel = {
+               .bus_id = "memcpy",
+               .cctl_memcpy =
+                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+                       PL080_CONTROL_PROT_SYS),
+       },
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+       .get_xfer_signal = pl08x_get_xfer_signal,
+       .put_xfer_signal = pl08x_put_xfer_signal,
+       .slave_channels = s3c64xx_dma1_info,
+       .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
+                       0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
+
+static int __init s3c64xx_pl080_init(void)
+{
+       /* Set all DMA configuration to be DMA, not SDMA */
+       writel(0xffffff, S3C64XX_SDMA_SEL);
+
+       if (of_have_populated_dt())
+               return 0;
+
+       amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
+       amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
+
+       return 0;
+}
+arch_initcall(s3c64xx_pl080_init);
index 958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8..c186891230233fe617161531b5f637246b4e0da7 100644 (file)
@@ -614,6 +614,11 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
        REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
 };
 
+/* Fixed 3.3V regulator used by LCD backlight */
+static struct regulator_consumer_supply fixed5v0_power_consumers[] = {
+       REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
 /* Fixed 3.3V regulator to be used by SDHI0 */
 static struct regulator_consumer_supply vcc_sdhi0_consumers[] = {
        REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
@@ -1196,6 +1201,8 @@ static void __init eva_init(void)
 
        regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
                                     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+       regulator_register_always_on(3, "fixed-5.0V", fixed5v0_power_consumers,
+                                    ARRAY_SIZE(fixed5v0_power_consumers), 5000000);
 
        pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
        pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
index 38611526fe9a55953372afcd2662aa668b34e080..3c4995aebd220870406934ba905d90d5949d18ca 100644 (file)
@@ -679,7 +679,7 @@ static void __init bockw_init(void)
                        .id             = i,
                        .data           = &rsnd_card_info[i],
                        .size_data      = sizeof(struct asoc_simple_card_info),
-                       .dma_mask       = ~0,
+                       .dma_mask       = DMA_BIT_MASK(32),
                };
 
                platform_device_register_full(&cardinfo);
index a8d3ce646fb900514fa983964bf8d70d0e88c278..e0406fd373906e4d43d53769a7d7cfa548b6f388 100644 (file)
@@ -245,7 +245,9 @@ static void __init lager_init(void)
 {
        lager_add_standard_devices();
 
-       phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
+       if (IS_ENABLED(CONFIG_PHYLIB))
+               phy_register_fixup_for_id("r8a7790-ether-ff:01",
+                                         lager_ksz8041_fixup);
 }
 
 static const char * const lager_boards_compat_dt[] __initconst = {
index 037100a1563aca5f52dd2e68f42c711dc71484c2..aee77f06f887da5d8f73e2112333a015640e93ab 100644 (file)
@@ -10,6 +10,7 @@ config ARCH_SOCFPGA
        select GENERIC_CLOCKEVENTS
        select GPIO_PL061 if GPIOLIB
        select HAVE_ARM_SCU
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MFD_SYSCON
        select SPARSE_IRQ
index d4639c5066222ea785f3dab068f46874fd52513c..3a9c1f1c219dd47bd79ecb1c3bb9f1538abe4463 100644 (file)
@@ -198,10 +198,12 @@ void __init tegra_init_fuse(void)
        switch (tegra_chip_id) {
        case TEGRA20:
                tegra20_fuse_init_randomness();
+               break;
        case TEGRA30:
        case TEGRA114:
        default:
                tegra30_fuse_init_randomness();
+               break;
        }
 
        pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
@@ -209,13 +211,3 @@ void __init tegra_init_fuse(void)
                tegra_sku_id, tegra_cpu_process_id,
                tegra_core_process_id);
 }
-
-unsigned long long tegra_chip_uid(void)
-{
-       unsigned long long lo, hi;
-
-       lo = tegra_fuse_readl(FUSE_UID_LOW);
-       hi = tegra_fuse_readl(FUSE_UID_HIGH);
-       return (hi << 32ull) | lo;
-}
-EXPORT_SYMBOL(tegra_chip_uid);
index 154e15f59702c1010af74cce8fed51077c78e111..43d6cb8c381da9d4364afd45ae686dd155e1975d 100644 (file)
@@ -31,7 +31,7 @@ static struct stedma40_chan_cfg msp0_dma_tx = {
 };
 
 struct msp_i2s_platform_data msp0_platform_data = {
-       .id = MSP_I2S_0,
+       .id = 0,
        .msp_i2s_dma_rx = &msp0_dma_rx,
        .msp_i2s_dma_tx = &msp0_dma_tx,
 };
@@ -49,7 +49,7 @@ static struct stedma40_chan_cfg msp1_dma_tx = {
 };
 
 struct msp_i2s_platform_data msp1_platform_data = {
-       .id = MSP_I2S_1,
+       .id = 1,
        .msp_i2s_dma_rx = NULL,
        .msp_i2s_dma_tx = &msp1_dma_tx,
 };
@@ -69,13 +69,13 @@ static struct stedma40_chan_cfg msp2_dma_tx = {
 };
 
 struct msp_i2s_platform_data msp2_platform_data = {
-       .id = MSP_I2S_2,
+       .id = 2,
        .msp_i2s_dma_rx = &msp2_dma_rx,
        .msp_i2s_dma_tx = &msp2_dma_tx,
 };
 
 struct msp_i2s_platform_data msp3_platform_data = {
-       .id             = MSP_I2S_3,
+       .id             = 3,
        .msp_i2s_dma_rx = &msp1_dma_rx,
        .msp_i2s_dma_tx = NULL,
 };
index 2e85c1e72535138a1b90c543ec3e95e2b36a6fa6..12c7e5c03ea488336eac954daab98f4b6a22c649 100644 (file)
@@ -140,6 +140,10 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        /* Requires call-back bindings. */
        OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
        /* Requires DMA bindings. */
+       OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  &mop500_sdi1_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  &mop500_sdi2_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
                       "ux500-msp-i2s.0", &msp0_platform_data),
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
index 033d34dcbd3fb8a8e1325900ddecdeb64090e874..c26ef5b92ca78587ce35b0f597a9cea66f9d592a 100644 (file)
 #define A15_BX_ADDR0           0x68
 #define A7_BX_ADDR0            0x78
 
+/* SPC CPU/cluster reset statue */
+#define STANDBYWFI_STAT                0x3c
+#define STANDBYWFI_STAT_A15_CPU_MASK(cpu)      (1 << (cpu))
+#define STANDBYWFI_STAT_A7_CPU_MASK(cpu)       (1 << (3 + (cpu)))
+
 /* SPC system config interface registers */
 #define SYSCFG_WDATA           0x70
 #define SYSCFG_RDATA           0x74
@@ -213,6 +218,41 @@ void ve_spc_powerdown(u32 cluster, bool enable)
        writel_relaxed(enable, info->baseaddr + pwdrn_reg);
 }
 
+static u32 standbywfi_cpu_mask(u32 cpu, u32 cluster)
+{
+       return cluster_is_a15(cluster) ?
+                 STANDBYWFI_STAT_A15_CPU_MASK(cpu)
+               : STANDBYWFI_STAT_A7_CPU_MASK(cpu);
+}
+
+/**
+ * ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
+ *
+ * @cpu: mpidr[7:0] bitfield describing CPU affinity level within cluster
+ * @cluster: mpidr[15:8] bitfield describing cluster affinity level
+ *
+ * @return: non-zero if and only if the specified CPU is in WFI
+ *
+ * Take care when interpreting the result of this function: a CPU might
+ * be in WFI temporarily due to idle, and is not necessarily safely
+ * parked.
+ */
+int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster)
+{
+       int ret;
+       u32 mask = standbywfi_cpu_mask(cpu, cluster);
+
+       if (cluster >= MAX_CLUSTERS)
+               return 1;
+
+       ret = readl_relaxed(info->baseaddr + STANDBYWFI_STAT);
+
+       pr_debug("%s: PCFGREG[0x%X] = 0x%08X, mask = 0x%X\n",
+                __func__, STANDBYWFI_STAT, ret, mask);
+
+       return ret & mask;
+}
+
 static int ve_spc_get_performance(int cluster, u32 *freq)
 {
        struct ve_spc_opp *opps = info->opps[cluster];
index dbd44c3720f98e711e5cabf28e6734847d8c7ea8..793d065243b9e469300be86a3325f777d7a37b4c 100644 (file)
@@ -20,5 +20,6 @@ void ve_spc_global_wakeup_irq(bool set);
 void ve_spc_cpu_wakeup_irq(u32 cluster, u32 cpu, bool set);
 void ve_spc_set_resume_addr(u32 cluster, u32 cpu, u32 addr);
 void ve_spc_powerdown(u32 cluster, bool enable);
+int ve_spc_cpu_in_wfi(u32 cpu, u32 cluster);
 
 #endif
index 05a364c5077a7a40f4c3a348bced3a70e22ea280..29e7785a54bcbbb3e4e7fa3f2f46180e430ad91c 100644 (file)
@@ -12,6 +12,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include "spc.h"
 
 /* SCC conf registers */
+#define RESET_CTRL             0x018
+#define RESET_A15_NCORERESET(cpu)      (1 << (2 + (cpu)))
+#define RESET_A7_NCORERESET(cpu)       (1 << (16 + (cpu)))
+
 #define A15_CONF               0x400
 #define A7_CONF                        0x500
 #define SYS_INFO               0x700
 #define SPC_BASE               0xb00
 
+static void __iomem *scc;
+
 /*
  * We can't use regular spinlocks. In the switcher case, it is possible
  * for an outbound CPU to call power_down() after its inbound counterpart
@@ -190,6 +197,55 @@ static void tc2_pm_power_down(void)
        tc2_pm_down(0);
 }
 
+static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster)
+{
+       u32 mask = cluster ?
+                 RESET_A7_NCORERESET(cpu)
+               : RESET_A15_NCORERESET(cpu);
+
+       return !(readl_relaxed(scc + RESET_CTRL) & mask);
+}
+
+#define POLL_MSEC 10
+#define TIMEOUT_MSEC 1000
+
+static int tc2_pm_power_down_finish(unsigned int cpu, unsigned int cluster)
+{
+       unsigned tries;
+
+       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+       BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
+
+       for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; ++tries) {
+               /*
+                * Only examine the hardware state if the target CPU has
+                * caught up at least as far as tc2_pm_down():
+                */
+               if (ACCESS_ONCE(tc2_pm_use_count[cpu][cluster]) == 0) {
+                       pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n",
+                                __func__, cpu, cluster,
+                                readl_relaxed(scc + RESET_CTRL));
+
+                       /*
+                        * We need the CPU to reach WFI, but the power
+                        * controller may put the cluster in reset and
+                        * power it off as soon as that happens, before
+                        * we have a chance to see STANDBYWFI.
+                        *
+                        * So we need to check for both conditions:
+                        */
+                       if (tc2_core_in_reset(cpu, cluster) ||
+                           ve_spc_cpu_in_wfi(cpu, cluster))
+                               return 0; /* success: the CPU is halted */
+               }
+
+               /* Otherwise, wait and retry: */
+               msleep(POLL_MSEC);
+       }
+
+       return -ETIMEDOUT; /* timeout */
+}
+
 static void tc2_pm_suspend(u64 residency)
 {
        unsigned int mpidr, cpu, cluster;
@@ -232,10 +288,11 @@ static void tc2_pm_powered_up(void)
 }
 
 static const struct mcpm_platform_ops tc2_pm_power_ops = {
-       .power_up       = tc2_pm_power_up,
-       .power_down     = tc2_pm_power_down,
-       .suspend        = tc2_pm_suspend,
-       .powered_up     = tc2_pm_powered_up,
+       .power_up               = tc2_pm_power_up,
+       .power_down             = tc2_pm_power_down,
+       .power_down_finish      = tc2_pm_power_down_finish,
+       .suspend                = tc2_pm_suspend,
+       .powered_up             = tc2_pm_powered_up,
 };
 
 static bool __init tc2_pm_usage_count_init(void)
@@ -269,7 +326,6 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
 static int __init tc2_pm_init(void)
 {
        int ret, irq;
-       void __iomem *scc;
        u32 a15_cluster_id, a7_cluster_id, sys_info;
        struct device_node *np;
 
index 79f8b39801a8e570bd86ea80e566ee939bbb600b..f61a5707823a40e0af9474d4f18809f9196b1264 100644 (file)
@@ -9,6 +9,7 @@
  *
  *  DMA uncached mapping support.
  */
+#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/gfp.h>
@@ -157,6 +158,44 @@ struct dma_map_ops arm_coherent_dma_ops = {
 };
 EXPORT_SYMBOL(arm_coherent_dma_ops);
 
+static int __dma_supported(struct device *dev, u64 mask, bool warn)
+{
+       unsigned long max_dma_pfn;
+
+       /*
+        * If the mask allows for more memory than we can address,
+        * and we actually have that much memory, then we must
+        * indicate that DMA to this device is not supported.
+        */
+       if (sizeof(mask) != sizeof(dma_addr_t) &&
+           mask > (dma_addr_t)~0 &&
+           dma_to_pfn(dev, ~0) < max_pfn) {
+               if (warn) {
+                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
+                                mask);
+                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
+               }
+               return 0;
+       }
+
+       max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
+
+       /*
+        * Translate the device's DMA mask to a PFN limit.  This
+        * PFN number includes the page which we can DMA to.
+        */
+       if (dma_to_pfn(dev, mask) < max_dma_pfn) {
+               if (warn)
+                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
+                                mask,
+                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
+                                max_dma_pfn + 1);
+               return 0;
+       }
+
+       return 1;
+}
+
 static u64 get_coherent_dma_mask(struct device *dev)
 {
        u64 mask = (u64)DMA_BIT_MASK(32);
@@ -173,32 +212,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
                        return 0;
                }
 
-               /*
-                * If the mask allows for more memory than we can address,
-                * and we actually have that much memory, then fail the
-                * allocation.
-                */
-               if (sizeof(mask) != sizeof(dma_addr_t) &&
-                   mask > (dma_addr_t)~0 &&
-                   dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) {
-                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
-                                mask);
-                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
-                       return 0;
-               }
-
-               /*
-                * Now check that the mask, when translated to a PFN,
-                * fits within the allowable addresses which we can
-                * allocate.
-                */
-               if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) {
-                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
-                                mask,
-                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
-                                arm_dma_pfn_limit + 1);
+               if (!__dma_supported(dev, mask, true))
                        return 0;
-               }
        }
 
        return mask;
@@ -1027,28 +1042,7 @@ void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-       unsigned long limit;
-
-       /*
-        * If the mask allows for more memory than we can address,
-        * and we actually have that much memory, then we must
-        * indicate that DMA to this device is not supported.
-        */
-       if (sizeof(mask) != sizeof(dma_addr_t) &&
-           mask > (dma_addr_t)~0 &&
-           dma_to_pfn(dev, ~0) > arm_dma_pfn_limit)
-               return 0;
-
-       /*
-        * Translate the device's DMA mask to a PFN limit.  This
-        * PFN number includes the page which we can DMA to.
-        */
-       limit = dma_to_pfn(dev, mask);
-
-       if (limit < arm_dma_pfn_limit)
-               return 0;
-
-       return 1;
+       return __dma_supported(dev, mask, false);
 }
 EXPORT_SYMBOL(dma_supported);
 
index 3e8f106ee5fe01855fe12f66b0c581822c0521da..1f7b19a470606726595ebc692f3b05aae94729c6 100644 (file)
@@ -229,7 +229,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc)
 #ifdef CONFIG_ZONE_DMA
        if (mdesc->dma_zone_size) {
                arm_dma_zone_size = mdesc->dma_zone_size;
-               arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
+               arm_dma_limit = __pv_phys_offset + arm_dma_zone_size - 1;
        } else
                arm_dma_limit = 0xffffffff;
        arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT;
index d27158c38eb0b190b869e028b93d8265fb90969e..5e85ed371364c17657be7d7155139a5e3f536437 100644 (file)
@@ -146,7 +146,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 
        info.flags = VM_UNMAPPED_AREA_TOPDOWN;
        info.length = len;
-       info.low_limit = PAGE_SIZE;
+       info.low_limit = FIRST_USER_ADDRESS;
        info.high_limit = mm->mmap_base;
        info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
        info.align_offset = pgoff << PAGE_SHIFT;
index 0acb089d0f70db818ce487fa67b0fb90b1b0b69d..1046b373d1aedb2823e3bb62f106681f9b63fc2a 100644 (file)
@@ -87,7 +87,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
                init_pud = pud_offset(init_pgd, 0);
                init_pmd = pmd_offset(init_pud, 0);
                init_pte = pte_offset_map(init_pmd, 0);
-               set_pte_ext(new_pte, *init_pte, 0);
+               set_pte_ext(new_pte + 0, init_pte[0], 0);
+               set_pte_ext(new_pte + 1, init_pte[1], 0);
                pte_unmap(init_pte);
                pte_unmap(new_pte);
        }
index fb92abb91628a2e06f6aebc54f03a724a79c23ee..2861b155485aefa0adeb1029d6657b4081179af6 100644 (file)
@@ -336,8 +336,11 @@ static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
        if (timer->posted)
                return;
 
-       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
+       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) {
+               timer->posted = OMAP_TIMER_NONPOSTED;
+               __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0);
                return;
+       }
 
        __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
                              OMAP_TIMER_CTRL_POSTED, 0);
index 99a3590f034949cc45bc99df724857e096888e51..ac07e871f6a781594ffae471516527e7ea090941 100644 (file)
@@ -1468,6 +1468,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
        pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
 #if defined(CONFIG_PL330_DMA)
        pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C64XX_PL080)
+       pd.filter = pl08x_filter_id;
 #elif defined(CONFIG_S3C24XX_DMAC)
        pd.filter = s3c24xx_dma_filter;
 #endif
@@ -1509,8 +1511,10 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
        pd.num_cs = num_cs;
        pd.src_clk_nr = src_clk_nr;
        pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
-#ifdef CONFIG_PL330_DMA
+#if defined(CONFIG_PL330_DMA)
        pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C64XX_PL080)
+       pd.filter = pl08x_filter_id;
 #endif
 
        s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
@@ -1550,8 +1554,10 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
        pd.num_cs = num_cs;
        pd.src_clk_nr = src_clk_nr;
        pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
-#ifdef CONFIG_PL330_DMA
+#if defined(CONFIG_PL330_DMA)
        pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C64XX_PL080)
+       pd.filter = pl08x_filter_id;
 #endif
 
        s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
index ec0d731b0e7b88ed8bc7b2937528545c15f60f6e..886326ee6f6c373c36d16fddef48b9ce58d5f7c9 100644 (file)
 
 #include <mach/dma.h>
 
+#if defined(CONFIG_PL330_DMA)
+#define dma_filter pl330_filter
+#elif defined(CONFIG_S3C64XX_PL080)
+#define dma_filter pl08x_filter_id
+#endif
+
 static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
                                struct samsung_dma_req *param,
                                struct device *dev, char *ch_name)
@@ -30,7 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
        if (dev->of_node)
                return (unsigned)dma_request_slave_channel(dev, ch_name);
        else
-               return (unsigned)dma_request_channel(mask, pl330_filter,
+               return (unsigned)dma_request_channel(mask, dma_filter,
                                                        (void *)dma_ch);
 }
 
index 83e4f959ee47c6b9b18a77d9f50995b7b4fc5ab0..85501238b4258316272f9448ad8829b18a1111b2 100644 (file)
@@ -96,7 +96,7 @@ static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
        struct remap_data *info = data;
        struct page *page = info->pages[info->index++];
        unsigned long pfn = page_to_pfn(page);
-       pte_t pte = pfn_pte(pfn, info->prot);
+       pte_t pte = pte_mkspecial(pfn_pte(pfn, info->prot));
 
        if (map_foreign_page(pfn, info->fgmfn, info->domid))
                return -EFAULT;
@@ -224,10 +224,10 @@ static int __init xen_guest_init(void)
        }
        if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
                return 0;
-       xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
+       xen_hvm_resume_frames = res.start;
        xen_events_irq = irq_of_parse_and_map(node, 0);
        pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
-                       version, xen_events_irq, xen_hvm_resume_frames);
+                       version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT));
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
index 23732cdff5511ff3c20bf1cbd403034797faf296..b31ee1b275b011d7010dbcac1eea3ab206290908 100644 (file)
@@ -25,8 +25,9 @@ struct xen_p2m_entry {
        struct rb_node rbnode_phys;
 };
 
-rwlock_t p2m_lock;
+static rwlock_t p2m_lock;
 struct rb_root phys_to_mach = RB_ROOT;
+EXPORT_SYMBOL_GPL(phys_to_mach);
 static struct rb_root mach_to_phys = RB_ROOT;
 
 static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
@@ -200,7 +201,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 }
 EXPORT_SYMBOL_GPL(__set_phys_to_machine);
 
-int p2m_init(void)
+static int p2m_init(void)
 {
        rwlock_init(&p2m_lock);
        return 0;
index 88c8b6c1341a445bdc425955383a8563033edd90..6d4dd22ee4b7bc70622f3fe95538bcba0ff6b99e 100644 (file)
@@ -159,8 +159,7 @@ config NR_CPUS
        range 2 32
        depends on SMP
        # These have to remain sorted largest to smallest
-       default "8" if ARCH_XGENE
-       default "4"
+       default "8"
 
 config HOTPLUG_CPU
        bool "Support for hot-pluggable CPUs"
index 84fcc5018284b6cee3dca436dd4ec7634e3b00cc..519c4b2c06873dc82f7ed2ebff9ccb698691e24f 100644 (file)
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+/memreserve/ 0x80000000 0x00010000;
+
 / {
        model = "Foundation-v8A";
        compatible = "arm,foundation-aarch64", "arm,vexpress";
index 4cc813eddacbebee4c84f864f103bb6492d7c193..57276972722768b86f5c21d0cdd50481e1a48683 100644 (file)
@@ -229,7 +229,7 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 
-#define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
+#define PROT_DEFAULT           (pgprot_default | PTE_DIRTY)
 #define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 #define PROT_NORMAL            (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
index aa11943b850213c77a32f87c1ce22c8aac87bf83..b2fcfbc51ecc4b0eaef6e4b20efd0f7afd2a9efd 100644 (file)
@@ -56,6 +56,9 @@ static inline void arch_local_irq_disable(void)
 #define local_fiq_enable()     asm("msr        daifclr, #1" : : : "memory")
 #define local_fiq_disable()    asm("msr        daifset, #1" : : : "memory")
 
+#define local_async_enable()   asm("msr        daifclr, #4" : : : "memory")
+#define local_async_disable()  asm("msr        daifset, #4" : : : "memory")
+
 /*
  * Save the current interrupt enable state.
  */
index 755f86143320167038e24e9be093e61b8b307e65..b1d2e26c3c883e7259f0ab679efe33ffe2935429 100644 (file)
@@ -43,7 +43,7 @@
  * Section
  */
 #define PMD_SECT_VALID         (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 58)
 #define PMD_SECT_USER          (_AT(pmdval_t, 1) << 6)         /* AP[1] */
 #define PMD_SECT_RDONLY                (_AT(pmdval_t, 1) << 7)         /* AP[2] */
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
index 17bd3af0a1177d094f27a9a4294dd6eae5103098..7f2b60affbb49509f290a5a56e5842fd1f29f4eb 100644 (file)
  * Software defined PTE bits definition.
  */
 #define PTE_VALID              (_AT(pteval_t, 1) << 0)
-#define PTE_PROT_NONE          (_AT(pteval_t, 1) << 2) /* only when !PTE_VALID */
-#define PTE_FILE               (_AT(pteval_t, 1) << 3) /* only when !pte_present() */
+#define PTE_FILE               (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
 #define PTE_DIRTY              (_AT(pteval_t, 1) << 55)
 #define PTE_SPECIAL            (_AT(pteval_t, 1) << 56)
+                               /* bit 57 for PMD_SECT_SPLITTING */
+#define PTE_PROT_NONE          (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
 
 /*
  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
@@ -254,7 +255,7 @@ static inline int has_transparent_hugepage(void)
 #define pgprot_noncached(prot) \
        __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE))
 #define pgprot_writecombine(prot) \
-       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE))
+       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
 #define pgprot_dmacoherent(prot) \
        __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
 #define __HAVE_PHYS_MEM_ACCESS_PROT
@@ -357,18 +358,20 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
 
 /*
  * Encode and decode a swap entry:
- *     bits 0, 2:      present (must both be zero)
- *     bit  3:         PTE_FILE
- *     bits 4-8:       swap type
- *     bits 9-63:      swap offset
+ *     bits 0-1:       present (must be zero)
+ *     bit  2:         PTE_FILE
+ *     bits 3-8:       swap type
+ *     bits 9-57:      swap offset
  */
-#define __SWP_TYPE_SHIFT       4
+#define __SWP_TYPE_SHIFT       3
 #define __SWP_TYPE_BITS                6
+#define __SWP_OFFSET_BITS      49
 #define __SWP_TYPE_MASK                ((1 << __SWP_TYPE_BITS) - 1)
 #define __SWP_OFFSET_SHIFT     (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
+#define __SWP_OFFSET_MASK      ((1UL << __SWP_OFFSET_BITS) - 1)
 
 #define __swp_type(x)          (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
-#define __swp_offset(x)                ((x).val >> __SWP_OFFSET_SHIFT)
+#define __swp_offset(x)                (((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK)
 #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
 
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
@@ -382,15 +385,15 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
 
 /*
  * Encode and decode a file entry:
- *     bits 0, 2:      present (must both be zero)
- *     bit  3:         PTE_FILE
- *     bits 4-63:      file offset / PAGE_SIZE
+ *     bits 0-1:       present (must be zero)
+ *     bit  2:         PTE_FILE
+ *     bits 3-57:      file offset / PAGE_SIZE
  */
 #define pte_file(pte)          (pte_val(pte) & PTE_FILE)
-#define pte_to_pgoff(x)                (pte_val(x) >> 4)
-#define pgoff_to_pte(x)                __pte(((x) << 4) | PTE_FILE)
+#define pte_to_pgoff(x)                (pte_val(x) >> 3)
+#define pgoff_to_pte(x)                __pte(((x) << 3) | PTE_FILE)
 
-#define PTE_FILE_MAX_BITS      60
+#define PTE_FILE_MAX_BITS      55
 
 extern int kern_addr_valid(unsigned long addr);
 
index 2820f1a6eebe0252d280e5d56e0a6bc60ac14182..dde3fc9c49f015c80b43f9ca21f1d996b9d2a910 100644 (file)
@@ -23,25 +23,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
             struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
 }
 
 static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir,
                struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
 }
 
 static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
 }
 
 static inline void xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
 }
 #endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 6a0a9b132d7af11714348f3950990a9854d56ba6..4ae68579031db9fb1e8e5a04689499fde2fcbc4c 100644 (file)
@@ -248,7 +248,8 @@ static int brk_handler(unsigned long addr, unsigned int esr,
 int aarch32_break_handler(struct pt_regs *regs)
 {
        siginfo_t info;
-       unsigned int instr;
+       u32 arm_instr;
+       u16 thumb_instr;
        bool bp = false;
        void __user *pc = (void __user *)instruction_pointer(regs);
 
@@ -257,18 +258,21 @@ int aarch32_break_handler(struct pt_regs *regs)
 
        if (compat_thumb_mode(regs)) {
                /* get 16-bit Thumb instruction */
-               get_user(instr, (u16 __user *)pc);
-               if (instr == AARCH32_BREAK_THUMB2_LO) {
+               get_user(thumb_instr, (u16 __user *)pc);
+               thumb_instr = le16_to_cpu(thumb_instr);
+               if (thumb_instr == AARCH32_BREAK_THUMB2_LO) {
                        /* get second half of 32-bit Thumb-2 instruction */
-                       get_user(instr, (u16 __user *)(pc + 2));
-                       bp = instr == AARCH32_BREAK_THUMB2_HI;
+                       get_user(thumb_instr, (u16 __user *)(pc + 2));
+                       thumb_instr = le16_to_cpu(thumb_instr);
+                       bp = thumb_instr == AARCH32_BREAK_THUMB2_HI;
                } else {
-                       bp = instr == AARCH32_BREAK_THUMB;
+                       bp = thumb_instr == AARCH32_BREAK_THUMB;
                }
        } else {
                /* 32-bit ARM instruction */
-               get_user(instr, (u32 __user *)pc);
-               bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM;
+               get_user(arm_instr, (u32 __user *)pc);
+               arm_instr = le32_to_cpu(arm_instr);
+               bp = (arm_instr & ~0xf0000000) == AARCH32_BREAK_ARM;
        }
 
        if (!bp)
index e1166145ca29b59801c84420e1f98225650f4580..4d2c6f3f0c4186da25fb1d6932d2671040941df2 100644 (file)
@@ -309,15 +309,12 @@ el1_irq:
 #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_off
 #endif
-#ifdef CONFIG_PREEMPT
-       get_thread_info tsk
-       ldr     w24, [tsk, #TI_PREEMPT]         // get preempt count
-       add     w0, w24, #1                     // increment it
-       str     w0, [tsk, #TI_PREEMPT]
-#endif
+
        irq_handler
+
 #ifdef CONFIG_PREEMPT
-       str     w24, [tsk, #TI_PREEMPT]         // restore preempt count
+       get_thread_info tsk
+       ldr     w24, [tsk, #TI_PREEMPT]         // restore preempt count
        cbnz    w24, 1f                         // preempt count != 0
        ldr     x0, [tsk, #TI_FLAGS]            // get flags
        tbz     x0, #TIF_NEED_RESCHED, 1f       // needs rescheduling?
@@ -507,22 +504,10 @@ el0_irq_naked:
 #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_off
 #endif
-       get_thread_info tsk
-#ifdef CONFIG_PREEMPT
-       ldr     w24, [tsk, #TI_PREEMPT]         // get preempt count
-       add     w23, w24, #1                    // increment it
-       str     w23, [tsk, #TI_PREEMPT]
-#endif
+
        irq_handler
-#ifdef CONFIG_PREEMPT
-       ldr     w0, [tsk, #TI_PREEMPT]
-       str     w24, [tsk, #TI_PREEMPT]
-       cmp     w0, w23
-       b.eq    1f
-       mov     x1, #0
-       str     x1, [x1]                        // BUG
-1:
-#endif
+       get_thread_info tsk
+
 #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_on
 #endif
index 7009387348b7c416f9dc8732a18c7563eac4af4e..c68cca5c3523221421e93460805a3c4d9cbac5a4 100644 (file)
@@ -282,8 +282,9 @@ ENDPROC(secondary_holding_pen)
         * be used where CPUs are brought online dynamically by the kernel.
         */
 ENTRY(secondary_entry)
-       bl      __calc_phys_offset              // x2=phys offset
        bl      el2_setup                       // Drop to EL1
+       bl      __calc_phys_offset              // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+       bl      set_cpu_boot_mode_flag
        b       secondary_startup
 ENDPROC(secondary_entry)
 
index fecdbf7de82e9a94d6f467f5999428cfcf623145..6a8928bba03c9e8135c4481b497268f7018ca393 100644 (file)
@@ -214,31 +214,29 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
 {
        int err, len, type, disabled = !ctrl.enabled;
 
-       if (disabled) {
-               len = 0;
-               type = HW_BREAKPOINT_EMPTY;
-       } else {
-               err = arch_bp_generic_fields(ctrl, &len, &type);
-               if (err)
-                       return err;
-
-               switch (note_type) {
-               case NT_ARM_HW_BREAK:
-                       if ((type & HW_BREAKPOINT_X) != type)
-                               return -EINVAL;
-                       break;
-               case NT_ARM_HW_WATCH:
-                       if ((type & HW_BREAKPOINT_RW) != type)
-                               return -EINVAL;
-                       break;
-               default:
+       attr->disabled = disabled;
+       if (disabled)
+               return 0;
+
+       err = arch_bp_generic_fields(ctrl, &len, &type);
+       if (err)
+               return err;
+
+       switch (note_type) {
+       case NT_ARM_HW_BREAK:
+               if ((type & HW_BREAKPOINT_X) != type)
                        return -EINVAL;
-               }
+               break;
+       case NT_ARM_HW_WATCH:
+               if ((type & HW_BREAKPOINT_RW) != type)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
        }
 
        attr->bp_len    = len;
        attr->bp_type   = type;
-       attr->disabled  = disabled;
 
        return 0;
 }
@@ -636,28 +634,27 @@ static int compat_gpr_get(struct task_struct *target,
 
        for (i = 0; i < num_regs; ++i) {
                unsigned int idx = start + i;
-               void *reg;
+               compat_ulong_t reg;
 
                switch (idx) {
                case 15:
-                       reg = (void *)&task_pt_regs(target)->pc;
+                       reg = task_pt_regs(target)->pc;
                        break;
                case 16:
-                       reg = (void *)&task_pt_regs(target)->pstate;
+                       reg = task_pt_regs(target)->pstate;
                        break;
                case 17:
-                       reg = (void *)&task_pt_regs(target)->orig_x0;
+                       reg = task_pt_regs(target)->orig_x0;
                        break;
                default:
-                       reg = (void *)&task_pt_regs(target)->regs[idx];
+                       reg = task_pt_regs(target)->regs[idx];
                }
 
-               ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t));
-
+               ret = copy_to_user(ubuf, &reg, sizeof(reg));
                if (ret)
                        break;
-               else
-                       ubuf += sizeof(compat_ulong_t);
+
+               ubuf += sizeof(reg);
        }
 
        return ret;
@@ -685,28 +682,28 @@ static int compat_gpr_set(struct task_struct *target,
 
        for (i = 0; i < num_regs; ++i) {
                unsigned int idx = start + i;
-               void *reg;
+               compat_ulong_t reg;
+
+               ret = copy_from_user(&reg, ubuf, sizeof(reg));
+               if (ret)
+                       return ret;
+
+               ubuf += sizeof(reg);
 
                switch (idx) {
                case 15:
-                       reg = (void *)&newregs.pc;
+                       newregs.pc = reg;
                        break;
                case 16:
-                       reg = (void *)&newregs.pstate;
+                       newregs.pstate = reg;
                        break;
                case 17:
-                       reg = (void *)&newregs.orig_x0;
+                       newregs.orig_x0 = reg;
                        break;
                default:
-                       reg = (void *)&newregs.regs[idx];
+                       newregs.regs[idx] = reg;
                }
 
-               ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t));
-
-               if (ret)
-                       goto out;
-               else
-                       ubuf += sizeof(compat_ulong_t);
        }
 
        if (valid_user_regs(&newregs.user_regs))
@@ -714,7 +711,6 @@ static int compat_gpr_set(struct task_struct *target,
        else
                ret = -EINVAL;
 
-out:
        return ret;
 }
 
index 0bc5e4cbc017674db8785f434fa3cff0b30d4c56..bd9bbd0e44edf176c262cfad0e32b9f62599d4b7 100644 (file)
@@ -205,6 +205,11 @@ u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
 
 void __init setup_arch(char **cmdline_p)
 {
+       /*
+        * Unmask asynchronous aborts early to catch possible system errors.
+        */
+       local_async_enable();
+
        setup_processor();
 
        setup_machine_fdt(__fdt_pointer);
index a5aeefab03c3e9cd2c0a241d4f4632bb0933b31f..a0c2ca602cf85bebc6e7996454adb9e47fe9456d 100644 (file)
@@ -160,6 +160,7 @@ asmlinkage void secondary_start_kernel(void)
 
        local_irq_enable();
        local_fiq_enable();
+       local_async_enable();
 
        /*
         * OK, it's off to the idle thread for us
index 421b99fd635dfae60c36d4c45837d73ca71a7187..0f7fec52c7f84030afb9958cdd4627bb2ceb9546 100644 (file)
@@ -111,12 +111,12 @@ ENTRY(__cpu_setup)
        bl      __flush_dcache_all
        mov     lr, x28
        ic      iallu                           // I+BTB cache invalidate
+       tlbi    vmalle1is                       // invalidate I + D TLBs
        dsb     sy
 
        mov     x0, #3 << 20
        msr     cpacr_el1, x0                   // Enable FP/ASIMD
        msr     mdscr_el1, xzr                  // Reset mdscr_el1
-       tlbi    vmalle1is                       // invalidate I + D TLBs
        /*
         * Memory region attributes for LPAE:
         *
index 7b1f2cd854008c16117cf5c39c06f4bd2115a9fa..1f121497b5177c4a3ac30d715dd98a1f623686cd 100644 (file)
@@ -298,8 +298,10 @@ static int __init set_abdac_rate(struct platform_device *pdev)
         */
        retval = clk_round_rate(pll1,
                        CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16);
-       if (retval < 0)
+       if (retval <= 0) {
+               retval = -EINVAL;
                goto out_abdac;
+       }
 
        retval = clk_set_rate(pll1, retval);
        if (retval != 0)
index d5aff36ade922f07ca18c34552b140919d598dfc..4733e38e7ae62cb111324ef17877bbd90b97a712 100644 (file)
@@ -59,7 +59,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 4abcf435d599a4a88b26ae1049b401dfcfa8a2e8..1be0ee31bd91c277753a5be27510ced4554712bf 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 18f3fa0470ff294a9755cd263d30c4a4080198e7..796e536f7bc43576d7079a41237356eb5977dbfe 100644 (file)
@@ -60,7 +60,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 06e389cfcd126e4c75111398758a5813d7fe2275..9a57da44eb6fd3390a5df2ce4d905bec1ec88c79 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 2518a1368d7caea758cfba9b152abe07b59870d0..97fe1b399b069d2965552ef78a7c3e29da1dd084 100644 (file)
@@ -59,7 +59,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 245ef6bd0fa61f56de23c1b4ce57abb51771489c..a176d24467e9d28f25e31364aa8e92b0fd3d8de0 100644 (file)
@@ -62,7 +62,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index fa6cbac6e4189c2e5a39eed8b6cb49ec44a3dd96..d1bf6dcfc47d4c289fca01896377d67cfbc62a94 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index bbd5131021a57d840bed7dede2db9d61b074e8f4..2813dd2b913876b0604c31751204b16ac6eb12fe 100644 (file)
@@ -53,7 +53,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index c1cd726f901233b1dd552cb3d28f3375682f3ad9..f8ff3a3baad4cc702ed4b374b95c21c943b0a84f 100644 (file)
@@ -42,7 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 754ae56b276739a58113bc89b87395d0b35b6ab2..992228e54e38cf56dc0cc1567c129d5ec907543b 100644 (file)
@@ -42,7 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 58589d8cc0acd829af7612b782368a907f6c3e64..b8e698b0d1fa30e2563fff8e9a0792a36b8ec3a1 100644 (file)
@@ -54,7 +54,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index c90fbf6d35bc16d60f12d1e5be4cf836f2fc9391..07bed3f7eb5e6022372ed35b6a8e303356cbbc8a 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index ba7c31e269cb0aed7b0ba9a72c1ce641cf0e346a..18db853386c81e73087c2c106d7271a415c3dce2 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 65de4431108c837334dc07facfc578fb815d55cd..91df6b2986be2a1691449bfe47953715e387060d 100644 (file)
@@ -46,7 +46,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
index 0a8bfdc420e0e6730c4ba1464de3ee92fafd8a2f..d630e089dd322c6ab735831a4ebd5424308a9a75 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 12f828ad5058d09158f8d3e2007b76a7a42cbb4a..d0f771be9e96eda02c1045bbb5702cc9b9f74b8d 100644 (file)
@@ -59,7 +59,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 static struct irqaction timer_irqaction = {
        .handler        = timer_interrupt,
        /* Oprofile uses the same irq as the timer, so allow it to be shared */
-       .flags          = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
+       .flags          = IRQF_TIMER | IRQF_SHARED,
        .name           = "avr32_comparator",
 };
 
index 32d680eb6f4842be56d17f40197c2a6fd4f77f37..db190842b80c74e026784037516df9b27471f4b8 100644 (file)
@@ -181,7 +181,7 @@ static const struct platform_suspend_ops avr32_pm_ops = {
        .enter  = avr32_pm_enter,
 };
 
-static unsigned long avr32_pm_offset(void *symbol)
+static unsigned long __init avr32_pm_offset(void *symbol)
 {
        extern u8 pm_exception[];
 
index ec1b014952b6601458f4c3b2901d8e86670b96fc..acacd348df89bb2f817855e5247e82f731539c6f 100644 (file)
@@ -50,7 +50,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_NS87415=y
-CONFIG_BLK_DEV_SIIMAGE=m
+CONFIG_PATA_SIL680=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
index e1c8d2015c8938ac0a3440d38af427b4ac8eec7a..8249ac9d9cfcc2a2e74d1111ac4b16ac54e67493 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_PA8X00=y
-CONFIG_MLONGCALLS=y
 CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
@@ -81,8 +80,6 @@ CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_PLATFORM=y
 CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
@@ -94,6 +91,8 @@ CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_ISCSI_TCP=m
 CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=y
 CONFIG_FUSION_SAS=y
@@ -114,9 +113,8 @@ CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_CM109=m
 CONFIG_SERIO_SERPORT=m
 CONFIG_SERIO_PARKBD=m
 CONFIG_SERIO_GSCPS2=m
@@ -167,34 +165,6 @@ CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_AD1889=m
 # CONFIG_SND_USB is not set
 # CONFIG_SND_GSC is not set
-CONFIG_HID_A4TECH=m
-CONFIG_HID_APPLE=m
-CONFIG_HID_BELKIN=m
-CONFIG_HID_CHERRY=m
-CONFIG_HID_CHICONY=m
-CONFIG_HID_CYPRESS=m
-CONFIG_HID_DRAGONRISE=m
-CONFIG_HID_EZKEY=m
-CONFIG_HID_KYE=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_TWINHAN=m
-CONFIG_HID_KENSINGTON=m
-CONFIG_HID_LOGITECH=m
-CONFIG_HID_LOGITECH_DJ=m
-CONFIG_HID_MICROSOFT=m
-CONFIG_HID_MONTEREY=m
-CONFIG_HID_NTRIG=m
-CONFIG_HID_ORTEK=m
-CONFIG_HID_PANTHERLORD=m
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_HID_GREENASIA=m
-CONFIG_HID_SMARTJOYPLUS=m
-CONFIG_HID_TOPSEED=m
-CONFIG_HID_THRUSTMASTER=m
-CONFIG_HID_ZEROPLUS=m
-CONFIG_USB_HID=m
 CONFIG_USB=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 5874cebee07701725f3ab9939acb6cd11f1e46f2..28c1b5de044e827d128f3165ea15d807f39ff0b6 100644 (file)
@@ -24,7 +24,6 @@ CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_PA8X00=y
-CONFIG_MLONGCALLS=y
 CONFIG_64BIT=y
 CONFIG_SMP=y
 # CONFIG_COMPACTION is not set
@@ -68,7 +67,6 @@ CONFIG_IDE_GD=m
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=m
 CONFIG_BLK_DEV_NS87415=y
-CONFIG_BLK_DEV_SIIMAGE=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
@@ -82,6 +80,7 @@ CONFIG_SCSI_ZALON=y
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_DH=y
 CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
 CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_MD_LINEAR=m
@@ -162,7 +161,7 @@ CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
-# CONFIG_INPUT_MOUSE is not set
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_INPUT_MISC=y
 CONFIG_SERIO_SERPORT=m
 # CONFIG_HP_SDC is not set
@@ -216,32 +215,7 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
-CONFIG_HID=m
 CONFIG_HIDRAW=y
-CONFIG_HID_DRAGONRISE=m
-CONFIG_DRAGONRISE_FF=y
-CONFIG_HID_KYE=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_TWINHAN=m
-CONFIG_LOGITECH_FF=y
-CONFIG_LOGIRUMBLEPAD2_FF=y
-CONFIG_HID_NTRIG=m
-CONFIG_HID_PANTHERLORD=m
-CONFIG_PANTHERLORD_FF=y
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SONY=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_HID_GREENASIA=m
-CONFIG_GREENASIA_FF=y
-CONFIG_HID_SMARTJOYPLUS=m
-CONFIG_SMARTJOYPLUS_FF=y
-CONFIG_HID_TOPSEED=m
-CONFIG_HID_THRUSTMASTER=m
-CONFIG_THRUSTMASTER_FF=y
-CONFIG_HID_ZEROPLUS=m
-CONFIG_ZEROPLUS_FF=y
-CONFIG_USB_HID=m
 CONFIG_HID_PID=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
@@ -251,13 +225,8 @@ CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_MON=m
 CONFIG_USB_WUSB_CBAF=m
 CONFIG_USB_XHCI_HCD=m
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_R8A66597_HCD=m
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_WDM=m
-CONFIG_USB_TMC=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGERS=y
index d7e3cc60dbc3693a3b8ce475fbd128bb9563a284..77e9b67c87ee1ed382670ec604b067f5b3a99b25 100644 (file)
@@ -6,5 +6,3 @@
  * This is used for 16550-compatible UARTs
  */
 #define BASE_BAUD ( 1843200 / 16 )
-
-#define SERIAL_PORT_DFNS
index 06cb3992907e67e9847b84259e5a61f3e42c2b71..608716f8496bf8dfe0acc08a71a15807ce20c557 100644 (file)
@@ -36,6 +36,9 @@
  *     HP PARISC Hardware Database
  *     Access to this database is only possible during bootup
  *     so don't reference this table after starting the init process
+ *
+ *     NOTE: Product names which are listed here and ends with a '?'
+ *     are guessed. If you know the correct name, please let us know.
  */
  
 static struct hp_hardware hp_hardware_list[] = {
@@ -222,7 +225,7 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
        {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
        {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
-       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+? (rp5470)"},
+       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+ (rp5470)?"},
        {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
        {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
        {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
@@ -276,9 +279,11 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"},
        {HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"},
        {HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak Slow"},
+       {HPHW_NPROC,0x88B,0x4,0x91,"Crestone Peak Fast?"},
        {HPHW_NPROC,0x88C,0x4,0x91,"Orca Mako+"},
        {HPHW_NPROC,0x88D,0x4,0x91,"Rainier/Medel Mako+ Slow"},
        {HPHW_NPROC,0x88E,0x4,0x91,"Rainier/Medel Mako+ Fast"},
+       {HPHW_NPROC,0x892,0x4,0x91,"Mt. Hamilton Slow Mako+?"},
        {HPHW_NPROC,0x894,0x4,0x91,"Mt. Hamilton Fast Mako+"},
        {HPHW_NPROC,0x895,0x4,0x91,"Storm Peak Slow Mako+"},
        {HPHW_NPROC,0x896,0x4,0x91,"Storm Peak Fast Mako+"},
index d2d58258aea68084c4f09cc6012a741b838b22d5..d4dc588c0dc1f6963f99e6545de14031192d4543 100644 (file)
@@ -41,9 +41,7 @@ END(boot_args)
         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
        .import $global$                /* forward declaration */
 #endif /*!CONFIG_64BIT*/
-       .export _stext,data             /* Kernel want it this way! */
-_stext:
-ENTRY(stext)
+ENTRY(parisc_kernel_start)
        .proc
        .callinfo
 
@@ -347,7 +345,7 @@ smp_slave_stext:
        .procend
 #endif /* CONFIG_SMP */
 
-ENDPROC(stext)
+ENDPROC(parisc_kernel_start)
 
 #ifndef CONFIG_64BIT
        .section .data..read_mostly
index 5dfd248e3f1a84fd6dbd961bf278002338cba4b0..0d3a9d4927b58009bfe0c4dc4114585409ddd2f5 100644 (file)
@@ -61,8 +61,15 @@ static int get_offset(struct address_space *mapping)
        return (unsigned long) mapping >> 8;
 }
 
-static unsigned long get_shared_area(struct address_space *mapping,
-               unsigned long addr, unsigned long len, unsigned long pgoff)
+static unsigned long shared_align_offset(struct file *filp, unsigned long pgoff)
+{
+       struct address_space *mapping = filp ? filp->f_mapping : NULL;
+
+       return (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+}
+
+static unsigned long get_shared_area(struct file *filp, unsigned long addr,
+               unsigned long len, unsigned long pgoff)
 {
        struct vm_unmapped_area_info info;
 
@@ -71,7 +78,7 @@ static unsigned long get_shared_area(struct address_space *mapping,
        info.low_limit = PAGE_ALIGN(addr);
        info.high_limit = TASK_SIZE;
        info.align_mask = PAGE_MASK & (SHMLBA - 1);
-       info.align_offset = (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+       info.align_offset = shared_align_offset(filp, pgoff);
        return vm_unmapped_area(&info);
 }
 
@@ -82,20 +89,18 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                return -ENOMEM;
        if (flags & MAP_FIXED) {
                if ((flags & MAP_SHARED) &&
-                   (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+                   (addr - shared_align_offset(filp, pgoff)) & (SHMLBA - 1))
                        return -EINVAL;
                return addr;
        }
        if (!addr)
                addr = TASK_UNMAPPED_BASE;
 
-       if (filp) {
-               addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
-       } else if(flags & MAP_SHARED) {
-               addr = get_shared_area(NULL, addr, len, pgoff);
-       } else {
+       if (filp || (flags & MAP_SHARED))
+               addr = get_shared_area(filp, addr, len, pgoff);
+       else
                addr = get_unshared_area(addr, len);
-       }
+
        return addr;
 }
 
index 76ed62ed785b6f4be9c1a6e663101ff3daeb6aa7..ddd988b267a9ddde0e9d2433f87e036f41e9d2a1 100644 (file)
@@ -168,7 +168,7 @@ void unwind_table_remove(struct unwind_table *table)
 }
 
 /* Called from setup_arch to import the kernel unwind info */
-int unwind_init(void)
+int __init unwind_init(void)
 {
        long start, stop;
        register unsigned long gp __asm__ ("r27");
@@ -233,7 +233,6 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
        e = find_unwind_entry(info->ip);
        if (e == NULL) {
                unsigned long sp;
-               extern char _stext[], _etext[];
 
                dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
 
@@ -281,8 +280,7 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
                                break;
                        info->prev_ip = tmp;
                        sp = info->prev_sp;
-               } while (info->prev_ip < (unsigned long)_stext ||
-                        info->prev_ip > (unsigned long)_etext);
+               } while (!kernel_text_address(info->prev_ip));
 
                info->rp = 0;
 
@@ -435,9 +433,8 @@ unsigned long return_address(unsigned int level)
        do {
                if (unwind_once(&info) < 0 || info.ip == 0)
                        return 0;
-               if (!__kernel_text_address(info.ip)) {
+               if (!kernel_text_address(info.ip))
                        return 0;
-               }
        } while (info.ip && level--);
 
        return info.ip;
index 4bb095a2f6fc2266388723cbb2634518a9570e44..0dacc5ca555afe7643da970bf9f3ae75ebc88790 100644 (file)
@@ -6,24 +6,19 @@
  *    Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *    Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
- *    Copyright (C) 2006 Helge Deller <deller@gmx.de>
- *
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *    Copyright (C) 2006-2013 Helge Deller <deller@gmx.de>
+ */
+
+/*
+ * Put page table entries (swapper_pg_dir) as the first thing in .bss. This
+ * will ensure that it has .bss alignment (PAGE_SIZE).
  */
+#define BSS_FIRST_SECTIONS     *(.data..vm0.pmd) \
+                               *(.data..vm0.pgd) \
+                               *(.data..vm0.pte)
+
 #include <asm-generic/vmlinux.lds.h>
+
 /* needed for the processor specific cache alignment size */   
 #include <asm/cache.h>
 #include <asm/page.h>
@@ -39,7 +34,7 @@ OUTPUT_FORMAT("elf64-hppa-linux")
 OUTPUT_ARCH(hppa:hppa2.0w)
 #endif
 
-ENTRY(_stext)
+ENTRY(parisc_kernel_start)
 #ifndef CONFIG_64BIT
 jiffies = jiffies_64 + 4;
 #else
@@ -49,11 +44,29 @@ SECTIONS
 {
        . = KERNEL_BINARY_TEXT_START;
 
+       __init_begin = .;
+       HEAD_TEXT_SECTION
+       INIT_TEXT_SECTION(8)
+
+       . = ALIGN(PAGE_SIZE);
+       INIT_DATA_SECTION(PAGE_SIZE)
+       /* we have to discard exit text and such at runtime, not link time */
+       .exit.text :
+       {
+               EXIT_TEXT
+       }
+       .exit.data :
+       {
+               EXIT_DATA
+       }
+       PERCPU_SECTION(8)
+       . = ALIGN(PAGE_SIZE);
+       __init_end = .;
+       /* freed after init ends here */
+
        _text = .;              /* Text and read-only data */
-       .head ALIGN(16) : {
-               HEAD_TEXT
-       } = 0
-       .text ALIGN(16) : {
+       _stext = .;
+       .text ALIGN(PAGE_SIZE) : {
                TEXT_TEXT
                SCHED_TEXT
                LOCK_TEXT
@@ -68,21 +81,28 @@ SECTIONS
                *(.lock.text)           /* out-of-line lock text */
                *(.gnu.warning)
        }
-       /* End of text section */
+       . = ALIGN(PAGE_SIZE);
        _etext = .;
+       /* End of text section */
 
        /* Start of data section */
        _sdata = .;
 
-       RODATA
+       RO_DATA_SECTION(8)
 
-       /* writeable */
-       /* Make sure this is page aligned so
-        * that we can properly leave these
-        * as writable
-        */
-       . = ALIGN(PAGE_SIZE);
-       data_start = .;
+#ifdef CONFIG_64BIT
+       . = ALIGN(16);
+       /* Linkage tables */
+       .opd : {
+               *(.opd)
+       } PROVIDE (__gp = .);
+       .plt : {
+               *(.plt)
+       }
+       .dlt : {
+               *(.dlt)
+       }
+#endif
 
        /* unwind info */
        .PARISC.unwind : {
@@ -91,7 +111,15 @@ SECTIONS
                __stop___unwind = .;
        }
 
-       EXCEPTION_TABLE(16)
+       /* writeable */
+       /* Make sure this is page aligned so
+        * that we can properly leave these
+        * as writable
+        */
+       . = ALIGN(PAGE_SIZE);
+       data_start = .;
+
+       EXCEPTION_TABLE(8)
        NOTES
 
        /* Data */
@@ -107,54 +135,8 @@ SECTIONS
        _edata = .;
 
        /* BSS */
-       __bss_start = .;
-       /* page table entries need to be PAGE_SIZE aligned */
-       . = ALIGN(PAGE_SIZE);
-       .data..vmpages : {
-               *(.data..vm0.pmd)
-               *(.data..vm0.pgd)
-               *(.data..vm0.pte)
-       }
-       .bss : {
-               *(.bss)
-               *(COMMON)
-       }
-       __bss_stop = .;
-
-#ifdef CONFIG_64BIT
-       . = ALIGN(16);
-       /* Linkage tables */
-       .opd : {
-               *(.opd)
-       } PROVIDE (__gp = .); 
-       .plt : {
-               *(.plt)
-       } 
-       .dlt : {
-               *(.dlt)
-       }
-#endif
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 8)
 
-       /* reserve space for interrupt stack by aligning __init* to 16k */
-       . = ALIGN(16384);
-       __init_begin = .;
-       INIT_TEXT_SECTION(16384)
-       . = ALIGN(PAGE_SIZE);
-       INIT_DATA_SECTION(16)
-       /* we have to discard exit text and such at runtime, not link time */
-       .exit.text :
-       {
-               EXIT_TEXT
-       }
-       .exit.data :
-       {
-               EXIT_DATA
-       }
-
-       PERCPU_SECTION(L1_CACHE_BYTES)
-       . = ALIGN(PAGE_SIZE);
-       __init_end = .;
-       /* freed after init ends here */
        _end = . ;
 
        STABS_DEBUG
index b0f96c0e6316f15531afb2a5a2a0e4684d1892a8..96f8168cf4ec1d9d50aad70ae17f54110a2c1527 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/sections.h>
 
 extern int  data_start;
+extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
 
 #if PT_NLEVELS == 3
 /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
@@ -324,8 +325,9 @@ static void __init setup_bootmem(void)
        reserve_bootmem_node(NODE_DATA(0), 0UL,
                        (unsigned long)(PAGE0->mem_free +
                                PDC_CONSOLE_IO_IODC_SIZE), BOOTMEM_DEFAULT);
-       reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
-                       (unsigned long)(_end - _text), BOOTMEM_DEFAULT);
+       reserve_bootmem_node(NODE_DATA(0), __pa(KERNEL_BINARY_TEXT_START),
+                       (unsigned long)(_end - KERNEL_BINARY_TEXT_START),
+                       BOOTMEM_DEFAULT);
        reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
                        ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT),
                        BOOTMEM_DEFAULT);
@@ -378,6 +380,17 @@ static void __init setup_bootmem(void)
        request_resource(&sysram_resources[0], &pdcdata_resource);
 }
 
+static int __init parisc_text_address(unsigned long vaddr)
+{
+       static unsigned long head_ptr __initdata;
+
+       if (!head_ptr)
+               head_ptr = PAGE_MASK & (unsigned long)
+                       dereference_function_descriptor(&parisc_kernel_start);
+
+       return core_kernel_text(vaddr) || vaddr == head_ptr;
+}
+
 static void __init map_pages(unsigned long start_vaddr,
                             unsigned long start_paddr, unsigned long size,
                             pgprot_t pgprot, int force)
@@ -466,7 +479,7 @@ static void __init map_pages(unsigned long start_vaddr,
                                 */
                                if (force)
                                        pte =  __mk_pte(address, pgprot);
-                               else if (core_kernel_text(vaddr) &&
+                               else if (parisc_text_address(vaddr) &&
                                         address != fv_addr)
                                        pte = __mk_pte(address, PAGE_KERNEL_EXEC);
                                else
index 8a2463670a5b8107243f313c7e272339570ce301..0f4344e6fbca99f621daf6776811d1538e1e69af 100644 (file)
@@ -75,8 +75,10 @@ LDEMULATION  := lppc
 GNUTARGET      := powerpcle
 MULTIPLEWORD   := -mno-multiple
 else
+ifeq ($(call cc-option-yn,-mbig-endian),y)
 override CC    += -mbig-endian
 override AS    += -mbig-endian
+endif
 override LD    += -EB
 LDEMULATION    := ppc
 GNUTARGET      := powerpc
@@ -128,7 +130,12 @@ CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
 CFLAGS-$(CONFIG_POWER6_CPU) += $(call cc-option,-mcpu=power6)
 CFLAGS-$(CONFIG_POWER7_CPU) += $(call cc-option,-mcpu=power7)
 
+# Altivec option not allowed with e500mc64 in GCC.
+ifeq ($(CONFIG_ALTIVEC),y)
+E5500_CPU := -mcpu=powerpc64
+else
 E5500_CPU := $(call cc-option,-mcpu=e500mc64,-mcpu=powerpc64)
+endif
 CFLAGS-$(CONFIG_E5500_CPU) += $(E5500_CPU)
 CFLAGS-$(CONFIG_E6500_CPU) += $(call cc-option,-mcpu=e6500,$(E5500_CPU))
 
index bd14c00e5146b31a90c8913e2b605c06d40184f1..2d7cb04ac962ba3cfed781f408646d7669e50d7d 100644 (file)
@@ -77,7 +77,6 @@
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     /* 66 MHz ips bus */
index cc00f4ddd9a7c1e1d5d3d8b2f869050b85204fa6..c409cbafb12678b0782edce46af71f5040f933f5 100644 (file)
                tlu@2f000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x2f000 0x1000>;
-                       interupts = <61 2 >;
+                       interrupts = <61 2>;
                        interrupt-parent = <&mpic>;
                };
 
                tlu@15000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x15000 0x1000>;
-                       interupts = <75 2>;
+                       interrupts = <75 2>;
                        interrupt-parent = <&mpic>;
                };
        };
index 53c1c6a9752f953a543b3d44ac134f0dfe321cc2..04cb410da48b78337b04fcfdc6b8940471917bda 100644 (file)
                tlu@2f000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x2f000 0x1000>;
-                       interupts = <61 2 >;
+                       interrupts = <61 2>;
                        interrupt-parent = <&mpic>;
                };
 
                tlu@15000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x15000 0x1000>;
-                       interupts = <75 2>;
+                       interrupts = <75 2>;
                        interrupt-parent = <&mpic>;
                };
        };
index 2152259831509ea89b1e64e2676c6e580de59c0f..73f8620f1ce7eeb714d6691b01d588a0c935f055 100644 (file)
                tlu@2f000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x2f000 0x1000>;
-                       interupts = <61 2 >;
+                       interrupts = <61 2>;
                        interrupt-parent = <&mpic>;
                };
 
                tlu@15000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x15000 0x1000>;
-                       interupts = <75 2>;
+                       interrupts = <75 2>;
                        interrupt-parent = <&mpic>;
                };
        };
index 11dbda10d7563dbe574e2cb60e13b09cb0927f01..cd0ea2b993622a8fc389b24a3387b2be72932948 100644 (file)
                tlu@2f000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x2f000 0x1000>;
-                       interupts = <61 2 >;
+                       interrupts = <61 2>;
                        interrupt-parent = <&mpic>;
                };
 
                tlu@15000 {
                        compatible = "fsl,mpc8572-tlu", "fsl_tlu";
                        reg = <0x15000 0x1000>;
-                       interupts = <75 2>;
+                       interrupts = <75 2>;
                        interrupt-parent = <&mpic>;
                };
        };
index 5143228e3e5fe975a1d19eacbd2393b210622497..6636b1d7821b6e5d5bcd8126674a8f3d8499601f 100644 (file)
@@ -71,18 +71,32 @@ udelay:
        add     r4,r4,r5
        addi    r4,r4,-1
        divw    r4,r4,r5        /* BUS ticks */
+#ifdef CONFIG_8xx
+1:     mftbu   r5
+       mftb    r6
+       mftbu   r7
+#else
 1:     mfspr   r5, SPRN_TBRU
        mfspr   r6, SPRN_TBRL
        mfspr   r7, SPRN_TBRU
+#endif
        cmpw    0,r5,r7
        bne     1b              /* Get [synced] base time */
        addc    r9,r6,r4        /* Compute end time */
        addze   r8,r5
+#ifdef CONFIG_8xx
+2:     mftbu   r5
+#else
 2:     mfspr   r5, SPRN_TBRU
+#endif
        cmpw    0,r5,r8
        blt     2b
        bgt     3f
+#ifdef CONFIG_8xx
+       mftb    r6
+#else
        mfspr   r6, SPRN_TBRL
+#endif
        cmpw    0,r6,r9
        blt     2b
 3:     blr
index 69b57daf402e056d0739e4ec50303f8349b78c0d..0b88c7b30bb9a4a5697cc87fe8fd6486bfca6bf4 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_EXPERT=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
@@ -71,6 +70,8 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index f3638ae0a627ceb6c481dae4bbc588616864548c..104a332e79ab961f2881776ea0ca80539b4444b7 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_LITE5200=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SPARSE_IRQ=y
@@ -59,6 +58,8 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 0c7de9620ea64a1715a836866c244dc1317e38d4..0d13ad7e44782fdf9adafa6f3a82231920048c98 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_EXPERT=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
@@ -84,6 +83,8 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 22e719575c60b33cb64cee5fcb840c2507f942c8..430aa182fa1ceab8f53ca6af410ca39772095f3b 100644 (file)
@@ -21,7 +21,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_HZ_100=y
@@ -87,6 +86,8 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 716a37be16e33b5d071416592ca8eb39fc7cca2f..7af4c5bb7c63b30d23a058d885a26cbe40b179ee 100644 (file)
@@ -17,7 +17,6 @@ CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -86,6 +85,8 @@ CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_DS1374=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 6640a35bebb7ac74d88d63f5c4420510088e088a..8b682d1cf4d6c49e90f83182db293fc6f1db6264 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_PPC_MEDIA5200=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 CONFIG_PPC_MPC5200_LPBFIFO=m
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SIMPLE_GPIO=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -125,6 +124,8 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index bd8a6f71944f153367df2312fa121ed97977ce27..cec044a3ff69dd6c05dcfec122fcb53653b412f8 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_PPC64=y
 CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -45,8 +44,9 @@ CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_SLRAM=y
 CONFIG_MTD_PHRAM=y
@@ -88,7 +88,6 @@ CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_MII=y
 CONFIG_TIGON3=y
 CONFIG_E1000=y
 CONFIG_PASEMI_MAC=y
@@ -174,8 +173,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_CRC_CCITT=y
 CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
index 4a594b76674d4e536ce714b40c183f598bf380d6..bc23b1ba798068b1c5a1f21e93da8bd47018ff55 100644 (file)
@@ -192,6 +192,10 @@ extern void kvmppc_load_up_vsx(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
 extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
+extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
+                                struct kvm_vcpu *vcpu);
+extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
+                                  struct kvmppc_book3s_shadow_vcpu *svcpu);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
index 0bd9348a4db91264d5e8a104f17ed77afcd5f815..192917d2239c4ed5a0eafd36b1206d176f0dddaa 100644 (file)
@@ -79,6 +79,7 @@ struct kvmppc_host_state {
        ulong vmhandler;
        ulong scratch0;
        ulong scratch1;
+       ulong scratch2;
        u8 in_guest;
        u8 restore_hid5;
        u8 napping;
@@ -106,6 +107,7 @@ struct kvmppc_host_state {
 };
 
 struct kvmppc_book3s_shadow_vcpu {
+       bool in_use;
        ulong gpr[14];
        u32 cr;
        u32 xer;
index 033c06be1d840da02423d596121940d0aa11adb5..7bdcf340016c412285df77ac56162aaa94982416 100644 (file)
@@ -720,13 +720,13 @@ int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe,
 int64_t opal_pci_poll(uint64_t phb_id);
 int64_t opal_return_cpu(void);
 
-int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, uint64_t *val);
+int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, __be64 *val);
 int64_t opal_xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val);
 
 int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
                       uint32_t addr, uint32_t data, uint32_t sz);
 int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type,
-                     uint32_t addr, uint32_t *data, uint32_t sz);
+                     uint32_t addr, __be32 *data, uint32_t sz);
 int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
index 27b2386f738a681fbea5a305b958e3681374df35..842846c1b71185b1a5e086e8521ed65342ae9cb0 100644 (file)
@@ -84,10 +84,8 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       struct page *page = page_address(table);
-
        tlb_flush_pgtable(tlb, address);
-       pgtable_page_dtor(page);
-       pgtable_free_tlb(tlb, page, 0);
+       pgtable_page_dtor(table);
+       pgtable_free_tlb(tlb, page_address(table), 0);
 }
 #endif /* _ASM_POWERPC_PGALLOC_32_H */
index 16cb92d215d27850f3ba15a0b7417cc0d1719f13..4b0be20fcbfdeee22498ea67f7a6b2adb3b55213 100644 (file)
@@ -16,6 +16,7 @@ struct vmemmap_backing {
        unsigned long phys;
        unsigned long virt_addr;
 };
+extern struct vmemmap_backing *vmemmap_list;
 
 /*
  * Functions that deal with pagetables that could be at any level of
@@ -147,11 +148,9 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       struct page *page = page_address(table);
-
        tlb_flush_pgtable(tlb, address);
-       pgtable_page_dtor(page);
-       pgtable_free_tlb(tlb, page, 0);
+       pgtable_page_dtor(table);
+       pgtable_free_tlb(tlb, page_address(table), 0);
 }
 
 #else /* if CONFIG_PPC_64K_PAGES */
index 3c1acc31a09280bdc8c706813879571587f3d75e..f595b98079ee1ec75064640001998a407524ad59 100644 (file)
@@ -366,6 +366,8 @@ BEGIN_FTR_SECTION_NESTED(96);               \
        cmpwi dest,0;                   \
        beq-  90b;                      \
 END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
+#elif defined(CONFIG_8xx)
+#define MFTB(dest)                     mftb dest
 #else
 #define MFTB(dest)                     mfspr dest, SPRN_TBRL
 #endif
index 5c45787d551e80c45c5d776bd972c868c19d9a14..fa8388ed94c52e6086110bc382c7196ea32f1ad0 100644 (file)
 
 #else /* __powerpc64__ */
 
+#if defined(CONFIG_8xx)
+#define mftbl()                ({unsigned long rval;   \
+                       asm volatile("mftbl %0" : "=r" (rval)); rval;})
+#define mftbu()                ({unsigned long rval;   \
+                       asm volatile("mftbu %0" : "=r" (rval)); rval;})
+#else
 #define mftbl()                ({unsigned long rval;   \
                        asm volatile("mfspr %0, %1" : "=r" (rval) : \
                                "i" (SPRN_TBRL)); rval;})
 #define mftbu()                ({unsigned long rval;   \
                        asm volatile("mfspr %0, %1" : "=r" (rval) : \
                                "i" (SPRN_TBRU)); rval;})
+#endif
 #endif /* !__powerpc64__ */
 
 #define mttbl(v)       asm volatile("mttbl %0":: "r"(v))
index 9ee12610af02bdca7fd61b9b7f6b16f2c74d36d0..aace90547614db30ea638945d30d143fbdfb336e 100644 (file)
@@ -35,7 +35,7 @@ extern void giveup_vsx(struct task_struct *);
 extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
-extern void switch_booke_debug_regs(struct thread_struct *new_thread);
+extern void switch_booke_debug_regs(struct debug_reg *new_debug);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
index 18908caa1f3b3c0209e8324474f4ce2b6473da63..2cf846edb3fcc4e941e44a8fc032eecd789b22d7 100644 (file)
@@ -29,7 +29,11 @@ static inline cycles_t get_cycles(void)
        ret = 0;
 
        __asm__ __volatile__(
+#ifdef CONFIG_8xx
+               "97:    mftb %0\n"
+#else
                "97:    mfspr %0, %2\n"
+#endif
                "99:\n"
                ".section __ftr_fixup,\"a\"\n"
                ".align 2\n"
@@ -41,7 +45,11 @@ static inline cycles_t get_cycles(void)
                "       .long 0\n"
                "       .long 0\n"
                ".previous"
+#ifdef CONFIG_8xx
+               : "=r" (ret) : "i" (CPU_FTR_601));
+#else
                : "=r" (ret) : "i" (CPU_FTR_601), "i" (SPRN_TBRL));
+#endif
        return ret;
 #endif
 }
index 2ea5cc033ec8b633febb50071c43cfd31958f4f3..d3de01066f7dd786cd531614046b801ff7ebb18f 100644 (file)
@@ -576,6 +576,7 @@ int main(void)
        HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
        HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
        HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+       HSTATE_FIELD(HSTATE_SCRATCH2, scratch2);
        HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
        HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
        HSTATE_FIELD(HSTATE_NAPPING, napping);
index 779a78c2643502a4414af7d646f4dce810deba72..11c1d069d920a1fc97ec601ab0542c41708d7cc1 100644 (file)
@@ -124,15 +124,15 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
 void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
 {
        unsigned long addr;
-       const u32 *basep, *sizep;
+       const __be32 *basep, *sizep;
        unsigned int rtas_start = 0, rtas_end = 0;
 
        basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
        sizep = of_get_property(rtas.dev, "rtas-size", NULL);
 
        if (basep && sizep) {
-               rtas_start = *basep;
-               rtas_end = *basep + *sizep;
+               rtas_start = be32_to_cpup(basep);
+               rtas_end = rtas_start + be32_to_cpup(sizep);
        }
 
        for (addr = begin; addr < end; addr += PAGE_SIZE) {
index e1ec57e87b3b435b88ef55c4598d32c37c8e2e07..75d4f7340da893bc2825f97dda750409d8963323 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ftrace.h>
 
 #include <asm/machdep.h>
+#include <asm/pgalloc.h>
 #include <asm/prom.h>
 #include <asm/sections.h>
 
@@ -75,6 +76,17 @@ void arch_crash_save_vmcoreinfo(void)
 #ifndef CONFIG_NEED_MULTIPLE_NODES
        VMCOREINFO_SYMBOL(contig_page_data);
 #endif
+#if defined(CONFIG_PPC64) && defined(CONFIG_SPARSEMEM_VMEMMAP)
+       VMCOREINFO_SYMBOL(vmemmap_list);
+       VMCOREINFO_SYMBOL(mmu_vmemmap_psize);
+       VMCOREINFO_SYMBOL(mmu_psize_defs);
+       VMCOREINFO_STRUCT_SIZE(vmemmap_backing);
+       VMCOREINFO_OFFSET(vmemmap_backing, list);
+       VMCOREINFO_OFFSET(vmemmap_backing, phys);
+       VMCOREINFO_OFFSET(vmemmap_backing, virt_addr);
+       VMCOREINFO_STRUCT_SIZE(mmu_psize_def);
+       VMCOREINFO_OFFSET(mmu_psize_def, shift);
+#endif
 }
 
 /*
@@ -136,7 +148,7 @@ void __init reserve_crashkernel(void)
                 * a small SLB (128MB) since the crash kernel needs to place
                 * itself and some stacks to be in the first segment.
                 */
-               crashk_res.start = min(0x80000000ULL, (ppc64_rma_size / 2));
+               crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
 #else
                crashk_res.start = KDUMP_KERNELBASE;
 #endif
index e59caf874d05ed60e500579b06bfcdf38bd85125..64bf8db12b15be3e8dbc903b6c8bb27173940fc1 100644 (file)
@@ -246,8 +246,8 @@ _GLOBAL(__bswapdi2)
        or      r3,r7,r9
        blr
 
-#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
 _GLOBAL(rmci_on)
        sync
        isync
@@ -277,6 +277,9 @@ _GLOBAL(rmci_off)
        isync
        sync
        blr
+#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
+
+#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 
 /*
  * Do an IO access in real mode
index fd82c289ab1c1c76c52c9fe147503d277870874c..28b898e681850ab22996a2043d46c867e96232be 100644 (file)
@@ -210,7 +210,7 @@ static void __init nvram_print_partitions(char * label)
        printk(KERN_WARNING "--------%s---------\n", label);
        printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
        list_for_each_entry(tmp_part, &nvram_partitions, partition) {
-               printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%12s\n",
+               printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%12.12s\n",
                       tmp_part->index, tmp_part->header.signature,
                       tmp_part->header.checksum, tmp_part->header.length,
                       tmp_part->header.name);
index 3386d8ab7eb0607b3c9d6f03e68824d4abe4bd88..4a96556fd2d49e484c143ed3643db6c8a24962df 100644 (file)
@@ -339,7 +339,7 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 #endif
 }
 
-static void prime_debug_regs(struct thread_struct *thread)
+static void prime_debug_regs(struct debug_reg *debug)
 {
        /*
         * We could have inherited MSR_DE from userspace, since
@@ -348,22 +348,22 @@ static void prime_debug_regs(struct thread_struct *thread)
         */
        mtmsr(mfmsr() & ~MSR_DE);
 
-       mtspr(SPRN_IAC1, thread->debug.iac1);
-       mtspr(SPRN_IAC2, thread->debug.iac2);
+       mtspr(SPRN_IAC1, debug->iac1);
+       mtspr(SPRN_IAC2, debug->iac2);
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
-       mtspr(SPRN_IAC3, thread->debug.iac3);
-       mtspr(SPRN_IAC4, thread->debug.iac4);
+       mtspr(SPRN_IAC3, debug->iac3);
+       mtspr(SPRN_IAC4, debug->iac4);
 #endif
-       mtspr(SPRN_DAC1, thread->debug.dac1);
-       mtspr(SPRN_DAC2, thread->debug.dac2);
+       mtspr(SPRN_DAC1, debug->dac1);
+       mtspr(SPRN_DAC2, debug->dac2);
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-       mtspr(SPRN_DVC1, thread->debug.dvc1);
-       mtspr(SPRN_DVC2, thread->debug.dvc2);
+       mtspr(SPRN_DVC1, debug->dvc1);
+       mtspr(SPRN_DVC2, debug->dvc2);
 #endif
-       mtspr(SPRN_DBCR0, thread->debug.dbcr0);
-       mtspr(SPRN_DBCR1, thread->debug.dbcr1);
+       mtspr(SPRN_DBCR0, debug->dbcr0);
+       mtspr(SPRN_DBCR1, debug->dbcr1);
 #ifdef CONFIG_BOOKE
-       mtspr(SPRN_DBCR2, thread->debug.dbcr2);
+       mtspr(SPRN_DBCR2, debug->dbcr2);
 #endif
 }
 /*
@@ -371,11 +371,11 @@ static void prime_debug_regs(struct thread_struct *thread)
  * debug registers, set the debug registers from the values
  * stored in the new thread.
  */
-void switch_booke_debug_regs(struct thread_struct *new_thread)
+void switch_booke_debug_regs(struct debug_reg *new_debug)
 {
        if ((current->thread.debug.dbcr0 & DBCR0_IDM)
-               || (new_thread->debug.dbcr0 & DBCR0_IDM))
-                       prime_debug_regs(new_thread);
+               || (new_debug->dbcr0 & DBCR0_IDM))
+                       prime_debug_regs(new_debug);
 }
 EXPORT_SYMBOL_GPL(switch_booke_debug_regs);
 #else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
@@ -683,7 +683,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-       switch_booke_debug_regs(&new->thread);
+       switch_booke_debug_regs(&new->thread.debug);
 #else
 /*
  * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would
index 75fb40498b419c3e8c1f2c639acfaa4f61f419d2..2e3d2bf536c5662c00f02e07cf36cd1e4b111825 100644 (file)
@@ -1555,7 +1555,7 @@ long arch_ptrace(struct task_struct *child, long request,
 
                        flush_fp_to_thread(child);
                        if (fpidx < (PT_FPSCR - PT_FPR0))
-                               memcpy(&tmp, &child->thread.fp_state.fpr,
+                               memcpy(&tmp, &child->thread.TS_FPR(fpidx),
                                       sizeof(long));
                        else
                                tmp = child->thread.fp_state.fpscr;
@@ -1588,7 +1588,7 @@ long arch_ptrace(struct task_struct *child, long request,
 
                        flush_fp_to_thread(child);
                        if (fpidx < (PT_FPSCR - PT_FPR0))
-                               memcpy(&child->thread.fp_state.fpr, &data,
+                               memcpy(&child->thread.TS_FPR(fpidx), &data,
                                       sizeof(long));
                        else
                                child->thread.fp_state.fpscr = data;
index febc80445d25850acf2578943c60357d8436b1c2..bc76cc6b419c2a8d0b5491637afadfe046278142 100644 (file)
@@ -479,7 +479,7 @@ void __init smp_setup_cpu_maps(void)
        if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
            (dn = of_find_node_by_path("/rtas"))) {
                int num_addr_cell, num_size_cell, maxcpus;
-               const unsigned int *ireg;
+               const __be32 *ireg;
 
                num_addr_cell = of_n_addr_cells(dn);
                num_size_cell = of_n_size_cells(dn);
@@ -489,7 +489,7 @@ void __init smp_setup_cpu_maps(void)
                if (!ireg)
                        goto out;
 
-               maxcpus = ireg[num_addr_cell + num_size_cell];
+               maxcpus = be32_to_cpup(ireg + num_addr_cell + num_size_cell);
 
                /* Double maxcpus for processors which have SMT capability */
                if (cpu_has_feature(CPU_FTR_SMT))
index 1844298f5ea49ea913111c761fb324398c5ed530..68027bfa5f8e3c4a958deeb13db1b6a9fcf89325 100644 (file)
@@ -445,6 +445,12 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
 #endif /* CONFIG_ALTIVEC */
        if (copy_fpr_to_user(&frame->mc_fregs, current))
                return 1;
+
+       /*
+        * Clear the MSR VSX bit to indicate there is no valid state attached
+        * to this context, except in the specific case below where we set it.
+        */
+       msr &= ~MSR_VSX;
 #ifdef CONFIG_VSX
        /*
         * Copy VSR 0-31 upper half from thread_struct to local
@@ -457,15 +463,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
                if (copy_vsx_to_user(&frame->mc_vsregs, current))
                        return 1;
                msr |= MSR_VSX;
-       } else if (!ctx_has_vsx_region)
-               /*
-                * With a small context structure we can't hold the VSX
-                * registers, hence clear the MSR value to indicate the state
-                * was not saved.
-                */
-               msr &= ~MSR_VSX;
-
-
+       }
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_SPE
        /* save spe registers */
index e66f67b8b9e67c1ca4bddbfaa6fb9e32e86c24a9..42991045349f815e124e18dba78c9a914c8b8b84 100644 (file)
@@ -122,6 +122,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
        flush_fp_to_thread(current);
        /* copy fpr regs and fpscr */
        err |= copy_fpr_to_user(&sc->fp_regs, current);
+
+       /*
+        * Clear the MSR VSX bit to indicate there is no valid state attached
+        * to this context, except in the specific case below where we set it.
+        */
+       msr &= ~MSR_VSX;
 #ifdef CONFIG_VSX
        /*
         * Copy VSX low doubleword to local buffer for formatting,
index a3b64f3bf9a298b057cfdc57b008ea01eebecf63..c1cf4a1522d9940bf3bb97a3e995a2642dee41ca 100644 (file)
@@ -580,7 +580,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 int cpu_to_core_id(int cpu)
 {
        struct device_node *np;
-       const int *reg;
+       const __be32 *reg;
        int id = -1;
 
        np = of_get_cpu_node(cpu, NULL);
@@ -591,7 +591,7 @@ int cpu_to_core_id(int cpu)
        if (!reg)
                goto out;
 
-       id = *reg;
+       id = be32_to_cpup(reg);
 out:
        of_node_put(np);
        return id;
index 6b1f2a6d55178c445a4d1a657dc72b0a53ae7a4a..6b2b69616e7762507f3375300513834f328bb503 100644 (file)
@@ -232,9 +232,15 @@ __do_get_tspec:
        lwz     r6,(CFG_TB_ORIG_STAMP+4)(r9)
 
        /* Get a stable TB value */
+#ifdef CONFIG_8xx
+2:     mftbu   r3
+       mftbl   r4
+       mftbu   r0
+#else
 2:     mfspr   r3, SPRN_TBRU
        mfspr   r4, SPRN_TBRL
        mfspr   r0, SPRN_TBRU
+#endif
        cmplw   cr0,r3,r0
        bne-    2b
 
index f3ff587a8b7d58e064e6364606e98a0e6473f106..c5d148434c08197034eba8ababd951176adb6a1f 100644 (file)
@@ -469,11 +469,14 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
                slb_v = vcpu->kvm->arch.vrma_slb_v;
        }
 
+       preempt_disable();
        /* Find the HPTE in the hash table */
        index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
                                         HPTE_V_VALID | HPTE_V_ABSENT);
-       if (index < 0)
+       if (index < 0) {
+               preempt_enable();
                return -ENOENT;
+       }
        hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
        v = hptep[0] & ~HPTE_V_HVLOCK;
        gr = kvm->arch.revmap[index].guest_rpte;
@@ -481,6 +484,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        /* Unlock the HPTE */
        asm volatile("lwsync" : : : "memory");
        hptep[0] = v;
+       preempt_enable();
 
        gpte->eaddr = eaddr;
        gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
@@ -665,6 +669,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        return -EFAULT;
        } else {
                page = pages[0];
+               pfn = page_to_pfn(page);
                if (PageHuge(page)) {
                        page = compound_head(page);
                        pte_size <<= compound_order(page);
@@ -689,7 +694,6 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        }
                        rcu_read_unlock_sched();
                }
-               pfn = page_to_pfn(page);
        }
 
        ret = -EFAULT;
@@ -707,8 +711,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                r = (r & ~(HPTE_R_W|HPTE_R_I|HPTE_R_G)) | HPTE_R_M;
        }
 
-       /* Set the HPTE to point to pfn */
-       r = (r & ~(HPTE_R_PP0 - pte_size)) | (pfn << PAGE_SHIFT);
+       /*
+        * Set the HPTE to point to pfn.
+        * Since the pfn is at PAGE_SIZE granularity, make sure we
+        * don't mask out lower-order bits if psize < PAGE_SIZE.
+        */
+       if (psize < PAGE_SIZE)
+               psize = PAGE_SIZE;
+       r = (r & ~(HPTE_R_PP0 - psize)) | ((pfn << PAGE_SHIFT) & ~(psize - 1));
        if (hpte_is_writable(r) && !write_ok)
                r = hpte_make_readonly(r);
        ret = RESUME_GUEST;
index 072287f1c3bc7347b6ff4f959843c97053fa4aa1..b51d5db780684ea5dcb3b6dae5c5bc70224dca43 100644 (file)
@@ -131,8 +131,9 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
 static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE &&
            vc->preempt_tb != TB_NIL) {
                vc->stolen_tb += mftb() - vc->preempt_tb;
@@ -143,19 +144,20 @@ static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
                vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt;
                vcpu->arch.busy_preempt = TB_NIL;
        }
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
                vc->preempt_tb = mftb();
        if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
                vcpu->arch.busy_preempt = mftb();
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
@@ -486,11 +488,11 @@ static u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now)
         */
        if (vc->vcore_state != VCORE_INACTIVE &&
            vc->runner->arch.run_task != current) {
-               spin_lock(&vc->runner->arch.tbacct_lock);
+               spin_lock_irq(&vc->runner->arch.tbacct_lock);
                p = vc->stolen_tb;
                if (vc->preempt_tb != TB_NIL)
                        p += now - vc->preempt_tb;
-               spin_unlock(&vc->runner->arch.tbacct_lock);
+               spin_unlock_irq(&vc->runner->arch.tbacct_lock);
        } else {
                p = vc->stolen_tb;
        }
@@ -512,10 +514,10 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
        core_stolen = vcore_stolen_time(vc, now);
        stolen = core_stolen - vcpu->arch.stolen_logged;
        vcpu->arch.stolen_logged = core_stolen;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        stolen += vcpu->arch.busy_stolen;
        vcpu->arch.busy_stolen = 0;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        if (!dt || !vpa)
                return;
        memset(dt, 0, sizeof(struct dtl_entry));
@@ -589,7 +591,9 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                if (list_empty(&vcpu->kvm->arch.rtas_tokens))
                        return RESUME_HOST;
 
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
                rc = kvmppc_rtas_hcall(vcpu);
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
                if (rc == -ENOENT)
                        return RESUME_HOST;
@@ -1115,13 +1119,13 @@ static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 
        if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                return;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        now = mftb();
        vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) -
                vcpu->arch.stolen_logged;
        vcpu->arch.busy_preempt = now;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        --vc->n_runnable;
        list_del(&vcpu->arch.run_list);
 }
index 9c515440ad1ae7e0451d3b3b67dd029ab06a0ebb..8689e2e308573b0df26996e2ebfed77e235df59c 100644 (file)
@@ -225,6 +225,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                is_io = pa & (HPTE_R_I | HPTE_R_W);
                pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
                pa &= PAGE_MASK;
+               pa |= gpa & ~PAGE_MASK;
        } else {
                /* Translate to host virtual address */
                hva = __gfn_to_hva_memslot(memslot, gfn);
@@ -238,13 +239,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                                ptel = hpte_make_readonly(ptel);
                        is_io = hpte_cache_bits(pte_val(pte));
                        pa = pte_pfn(pte) << PAGE_SHIFT;
+                       pa |= hva & (pte_size - 1);
+                       pa |= gpa & ~PAGE_MASK;
                }
        }
 
        if (pte_size < psize)
                return H_PARAMETER;
-       if (pa && pte_size > psize)
-               pa |= gpa & (pte_size - 1);
 
        ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
@@ -749,6 +750,10 @@ static int slb_base_page_shift[4] = {
        20,     /* 1M, unsupported */
 };
 
+/* When called from virtmode, this func should be protected by
+ * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
+ * can trigger deadlock issue.
+ */
 long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
                              unsigned long valid)
 {
index bc8de75b1925cd34ad1d11379fee8c09f1d275e5..be4fa04a37c96d56d5f07d241395afe22e1627dd 100644 (file)
@@ -153,7 +153,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 13:    b       machine_check_fwnmi
 
-
 /*
  * We come in here when wakened from nap mode on a secondary hw thread.
  * Relocation is off and most register values are lost.
@@ -224,6 +223,11 @@ kvm_start_guest:
        /* Clear our vcpu pointer so we don't come back in early */
        li      r0, 0
        std     r0, HSTATE_KVM_VCPU(r13)
+       /*
+        * Make sure we clear HSTATE_KVM_VCPU(r13) before incrementing
+        * the nap_count, because once the increment to nap_count is
+        * visible we could be given another vcpu.
+        */
        lwsync
        /* Clear any pending IPI - we're an offline thread */
        ld      r5, HSTATE_XICS_PHYS(r13)
@@ -241,7 +245,6 @@ kvm_start_guest:
        /* increment the nap count and then go to nap mode */
        ld      r4, HSTATE_KVM_VCORE(r13)
        addi    r4, r4, VCORE_NAP_COUNT
-       lwsync                          /* make previous updates visible */
 51:    lwarx   r3, 0, r4
        addi    r3, r3, 1
        stwcx.  r3, 0, r4
@@ -751,15 +754,14 @@ kvmppc_interrupt_hv:
         * guest CR, R12 saved in shadow VCPU SCRATCH1/0
         * guest R13 saved in SPRN_SCRATCH0
         */
-       /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
-       std     r9, HSTATE_HOST_R2(r13)
+       std     r9, HSTATE_SCRATCH2(r13)
 
        lbz     r9, HSTATE_IN_GUEST(r13)
        cmpwi   r9, KVM_GUEST_MODE_HOST_HV
        beq     kvmppc_bad_host_intr
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        cmpwi   r9, KVM_GUEST_MODE_GUEST
-       ld      r9, HSTATE_HOST_R2(r13)
+       ld      r9, HSTATE_SCRATCH2(r13)
        beq     kvmppc_interrupt_pr
 #endif
        /* We're now back in the host but in guest MMU context */
@@ -779,7 +781,7 @@ kvmppc_interrupt_hv:
        std     r6, VCPU_GPR(R6)(r9)
        std     r7, VCPU_GPR(R7)(r9)
        std     r8, VCPU_GPR(R8)(r9)
-       ld      r0, HSTATE_HOST_R2(r13)
+       ld      r0, HSTATE_SCRATCH2(r13)
        std     r0, VCPU_GPR(R9)(r9)
        std     r10, VCPU_GPR(R10)(r9)
        std     r11, VCPU_GPR(R11)(r9)
@@ -990,14 +992,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
         */
        /* Increment the threads-exiting-guest count in the 0xff00
           bits of vcore->entry_exit_count */
-       lwsync
        ld      r5,HSTATE_KVM_VCORE(r13)
        addi    r6,r5,VCORE_ENTRY_EXIT
 41:    lwarx   r3,0,r6
        addi    r0,r3,0x100
        stwcx.  r0,0,r6
        bne     41b
-       lwsync
+       isync           /* order stwcx. vs. reading napping_threads */
 
        /*
         * At this point we have an interrupt that we have to pass
@@ -1030,6 +1031,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        sld     r0,r0,r4
        andc.   r3,r3,r0                /* no sense IPI'ing ourselves */
        beq     43f
+       /* Order entry/exit update vs. IPIs */
+       sync
        mulli   r4,r4,PACA_SIZE         /* get paca for thread 0 */
        subf    r6,r4,r13
 42:    andi.   r0,r3,1
@@ -1638,10 +1641,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        bge     kvm_cede_exit
        stwcx.  r4,0,r6
        bne     31b
+       /* order napping_threads update vs testing entry_exit_count */
+       isync
        li      r0,1
        stb     r0,HSTATE_NAPPING(r13)
-       /* order napping_threads update vs testing entry_exit_count */
-       lwsync
        mr      r4,r3
        lwz     r7,VCORE_ENTRY_EXIT(r5)
        cmpwi   r7,0x100
index f4dd041c14eac9400fb012beae92792fe9c9cfd1..f779450cb07c728681ede6d566ef85920117337e 100644 (file)
@@ -129,29 +129,32 @@ kvm_start_lightweight:
         * R12      = exit handler id
         * R13      = PACA
         * SVCPU.*  = guest *
+        * MSR.EE   = 1
         *
         */
 
+       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
+       /*
+        * kvmppc_copy_from_svcpu can clobber volatile registers, save
+        * the exit handler id to the vcpu and restore it from there later.
+        */
+       stw     r12, VCPU_TRAP(r3)
+
        /* Transfer reg values from shadow vcpu back to vcpu struct */
        /* On 64-bit, interrupts are still off at this point */
-       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
        GET_SHADOW_VCPU(r4)
        bl      FUNC(kvmppc_copy_from_svcpu)
        nop
 
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Re-enable interrupts */
-       ld      r3, HSTATE_HOST_MSR(r13)
-       ori     r3, r3, MSR_EE
-       MTMSR_EERI(r3)
-
        /*
         * Reload kernel SPRG3 value.
         * No need to save guest value as usermode can't modify SPRG3.
         */
        ld      r3, PACA_SPRG3(r13)
        mtspr   SPRN_SPRG3, r3
-
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
        /* R7 = vcpu */
@@ -177,7 +180,7 @@ kvm_start_lightweight:
        PPC_STL r31, VCPU_GPR(R31)(r7)
 
        /* Pass the exit number as 3rd argument to kvmppc_handle_exit */
-       mr      r5, r12
+       lwz     r5, VCPU_TRAP(r7)
 
        /* Restore r3 (kvm_run) and r4 (vcpu) */
        REST_2GPRS(3, r1)
index fe14ca3dd171cd60b3c07191fa3bdd78a141e2a6..5b9e9063cfaf0c407be267a67ab26d35fcc84a93 100644 (file)
@@ -66,6 +66,7 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->in_use = 0;
        svcpu_put(svcpu);
 #endif
        vcpu->cpu = smp_processor_id();
@@ -78,6 +79,9 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       if (svcpu->in_use) {
+               kvmppc_copy_from_svcpu(vcpu, svcpu);
+       }
        memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
        svcpu_put(svcpu);
@@ -110,12 +114,26 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
        svcpu->ctr = vcpu->arch.ctr;
        svcpu->lr  = vcpu->arch.lr;
        svcpu->pc  = vcpu->arch.pc;
+       svcpu->in_use = true;
 }
 
 /* Copy data touched by real-mode code from shadow vcpu back to vcpu */
 void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
                            struct kvmppc_book3s_shadow_vcpu *svcpu)
 {
+       /*
+        * vcpu_put would just call us again because in_use hasn't
+        * been updated yet.
+        */
+       preempt_disable();
+
+       /*
+        * Maybe we were already preempted and synced the svcpu from
+        * our preempt notifiers. Don't bother touching this svcpu then.
+        */
+       if (!svcpu->in_use)
+               goto out;
+
        vcpu->arch.gpr[0] = svcpu->gpr[0];
        vcpu->arch.gpr[1] = svcpu->gpr[1];
        vcpu->arch.gpr[2] = svcpu->gpr[2];
@@ -139,6 +157,10 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
        vcpu->arch.fault_dar   = svcpu->fault_dar;
        vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
        vcpu->arch.last_inst   = svcpu->last_inst;
+       svcpu->in_use = false;
+
+out:
+       preempt_enable();
 }
 
 static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)
index a38c4c9edab87aca16929b5e96377368b5016fbd..c3c5231adade6f3871709a318fed1abc752040fe 100644 (file)
@@ -153,15 +153,11 @@ _GLOBAL(kvmppc_entry_trampoline)
 
        li      r6, MSR_IR | MSR_DR
        andc    r6, r5, r6      /* Clear DR and IR in MSR value */
-#ifdef CONFIG_PPC_BOOK3S_32
        /*
         * Set EE in HOST_MSR so that it's enabled when we get into our
-        * C exit handler function.  On 64-bit we delay enabling
-        * interrupts until we have finished transferring stuff
-        * to or from the PACA.
+        * C exit handler function.
         */
        ori     r5, r5, MSR_EE
-#endif
        mtsrr0  r7
        mtsrr1  r6
        RFI
index 53e65a210b9a451ab1089bfe788277ddda071cf3..0591e05db74b1a1a1f906af6a2a67cf9770320fa 100644 (file)
@@ -681,7 +681,7 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        int ret, s;
-       struct thread_struct thread;
+       struct debug_reg debug;
 #ifdef CONFIG_PPC_FPU
        struct thread_fp_state fp;
        int fpexc_mode;
@@ -723,9 +723,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
        /* Switch to guest debug context */
-       thread.debug = vcpu->arch.shadow_dbg_reg;
-       switch_booke_debug_regs(&thread);
-       thread.debug = current->thread.debug;
+       debug = vcpu->arch.shadow_dbg_reg;
+       switch_booke_debug_regs(&debug);
+       debug = current->thread.debug;
        current->thread.debug = vcpu->arch.shadow_dbg_reg;
 
        kvmppc_fix_ee_before_entry();
@@ -736,8 +736,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
           We also get here with interrupts enabled. */
 
        /* Switch back to user space debug context */
-       switch_booke_debug_regs(&thread);
-       current->thread.debug = thread.debug;
+       switch_booke_debug_regs(&debug);
+       current->thread.debug = debug;
 
 #ifdef CONFIG_PPC_FPU
        kvmppc_save_guest_fp(vcpu);
index 3bc700655fc88255ae39fe854341e467cd9910a5..74551b5e41e5156b0720c65ec9cdd1adf988260a 100644 (file)
@@ -117,6 +117,5 @@ void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
        struct hstate *hstate = hstate_file(vma->vm_file);
        unsigned long tsize = huge_page_shift(hstate) - 10;
 
-       __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, tsize, 0);
-
+       __flush_tlb_page(vma->vm_mm, vmaddr, tsize, 0);
 }
index 41cd68dee68164c38f3436ee7a40e60326ecc8cb..358d743031385ae7a269ba65200483227126d372 100644 (file)
@@ -305,7 +305,7 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
 #ifdef CONFIG_HUGETLB_PAGE
-       if (is_vm_hugetlb_page(vma))
+       if (vma && is_vm_hugetlb_page(vma))
                flush_hugetlb_page(vma, vmaddr);
 #endif
 
index 132f8726a257c4ed7608534a8f61496d89b69d80..bca2465a9c347ad65f3617a7a51f2e4f2a73034a 100644 (file)
@@ -404,13 +404,27 @@ config PPC_DOORBELL
 
 endmenu
 
-config CPU_LITTLE_ENDIAN
-       bool "Build little endian kernel"
-       default n
+choice
+       prompt "Endianness selection"
+       default CPU_BIG_ENDIAN
        help
          This option selects whether a big endian or little endian kernel will
          be built.
 
+config CPU_BIG_ENDIAN
+       bool "Build big endian kernel"
+       help
+         Build a big endian kernel.
+
+         If unsure, select this option.
+
+config CPU_LITTLE_ENDIAN
+       bool "Build little endian kernel"
+       help
+         Build a little endian kernel.
+
          Note that if cross compiling a little endian kernel,
          CROSS_COMPILE must point to a toolchain capable of targeting
          little endian powerpc.
+
+endchoice
index e7e59e4f9892deb85b8ff96b502a6c14fe989d19..79d83cad3d6709c543dad5bb96eafba2ff8756a7 100644 (file)
@@ -24,25 +24,25 @@ static int opal_lpc_chip_id = -1;
 static u8 opal_lpc_inb(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xffff)
                return 0xff;
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 1);
-       return rc ? 0xff : data;
+       return rc ? 0xff : be32_to_cpu(data);
 }
 
 static __le16 __opal_lpc_inw(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xfffe)
                return 0xffff;
        if (port & 1)
                return (__le16)opal_lpc_inb(port) << 8 | opal_lpc_inb(port + 1);
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 2);
-       return rc ? 0xffff : data;
+       return rc ? 0xffff : be32_to_cpu(data);
 }
 static u16 opal_lpc_inw(unsigned long port)
 {
@@ -52,7 +52,7 @@ static u16 opal_lpc_inw(unsigned long port)
 static __le32 __opal_lpc_inl(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xfffc)
                return 0xffffffff;
@@ -62,7 +62,7 @@ static __le32 __opal_lpc_inl(unsigned long port)
                       (__le32)opal_lpc_inb(port + 2) <<  8 |
                               opal_lpc_inb(port + 3);
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 4);
-       return rc ? 0xffffffff : data;
+       return rc ? 0xffffffff : be32_to_cpu(data);
 }
 
 static u32 opal_lpc_inl(unsigned long port)
index 4d99a8fd55acf2a286e8f7877cd919d2150355bf..4fbf276ac99eeb4e2900196e3905a3343bedc988 100644 (file)
@@ -96,9 +96,11 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
 {
        struct opal_scom_map *m = map;
        int64_t rc;
+       __be64 v;
 
        reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_read(m->chip, m->addr + reg, (uint64_t *)__pa(value));
+       rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v));
+       *value = be64_to_cpu(v);
        return opal_xscom_err_xlate(rc);
 }
 
index 084cdfa40682b2be9f35fde51eb2e4e201accfe9..2c6d173842b2f1056d3702826b3c2a1d84d614ad 100644 (file)
@@ -720,6 +720,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
                tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
        }
        iommu_init_table(tbl, phb->hose->node);
+       iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
 
        if (pe->pdev)
                set_iommu_table_base(&pe->pdev->dev, tbl);
index e738007eae643262d72942c599a6418b252b4849..c9fecf09b8fada71dec94e9833c35be524b498e4 100644 (file)
@@ -157,7 +157,7 @@ static void parse_ppp_data(struct seq_file *m)
 {
        struct hvcall_ppp_data ppp_data;
        struct device_node *root;
-       const int *perf_level;
+       const __be32 *perf_level;
        int rc;
 
        rc = h_get_ppp(&ppp_data);
@@ -201,7 +201,7 @@ static void parse_ppp_data(struct seq_file *m)
                perf_level = of_get_property(root,
                                "ibm,partition-performance-parameters-level",
                                             NULL);
-               if (perf_level && (*perf_level >= 1)) {
+               if (perf_level && (be32_to_cpup(perf_level) >= 1)) {
                        seq_printf(m,
                            "physical_procs_allocated_to_virtualization=%d\n",
                                   ppp_data.phys_platform_procs);
@@ -435,7 +435,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        int partition_potential_processors;
        int partition_active_processors;
        struct device_node *rtas_node;
-       const int *lrdrp = NULL;
+       const __be32 *lrdrp = NULL;
 
        rtas_node = of_find_node_by_path("/rtas");
        if (rtas_node)
@@ -444,7 +444,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        if (lrdrp == NULL) {
                partition_potential_processors = vdso_data->processorCount;
        } else {
-               partition_potential_processors = *(lrdrp + 4);
+               partition_potential_processors = be32_to_cpup(lrdrp + 4);
        }
        of_node_put(rtas_node);
 
@@ -654,7 +654,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
        const char *model = "";
        const char *system_id = "";
        const char *tmp;
-       const unsigned int *lp_index_ptr;
+       const __be32 *lp_index_ptr;
        unsigned int lp_index = 0;
 
        seq_printf(m, "%s %s\n", MODULE_NAME, MODULE_VERS);
@@ -670,7 +670,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
                lp_index_ptr = of_get_property(rootdn, "ibm,partition-no",
                                        NULL);
                if (lp_index_ptr)
-                       lp_index = *lp_index_ptr;
+                       lp_index = be32_to_cpup(lp_index_ptr);
                of_node_put(rootdn);
        }
        seq_printf(m, "serial_number=%s\n", system_id);
index 6d2f0abce6fae652d207b499ac99a47e20a500f2..0c882e83c4ce29373f6d3957b7de34979d9fae98 100644 (file)
@@ -130,7 +130,8 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 {
        struct device_node *dn;
        struct pci_dn *pdn;
-       const u32 *req_msi;
+       const __be32 *p;
+       u32 req_msi;
 
        pdn = pci_get_pdn(pdev);
        if (!pdn)
@@ -138,19 +139,20 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 
        dn = pdn->node;
 
-       req_msi = of_get_property(dn, prop_name, NULL);
-       if (!req_msi) {
+       p = of_get_property(dn, prop_name, NULL);
+       if (!p) {
                pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name);
                return -ENOENT;
        }
 
-       if (*req_msi < nvec) {
+       req_msi = be32_to_cpup(p);
+       if (req_msi < nvec) {
                pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec);
 
-               if (*req_msi == 0) /* Be paranoid */
+               if (req_msi == 0) /* Be paranoid */
                        return -ENOSPC;
 
-               return *req_msi;
+               return req_msi;
        }
 
        return 0;
@@ -171,7 +173,7 @@ static int check_req_msix(struct pci_dev *pdev, int nvec)
 static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
 {
        struct device_node *dn;
-       const u32 *p;
+       const __be32 *p;
 
        dn = of_node_get(pci_device_to_OF_node(dev));
        while (dn) {
@@ -179,7 +181,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
                if (p) {
                        pr_debug("rtas_msi: found prop on dn %s\n",
                                dn->full_name);
-                       *total = *p;
+                       *total = be32_to_cpup(p);
                        return dn;
                }
 
@@ -232,13 +234,13 @@ struct msi_counts {
 static void *count_non_bridge_devices(struct device_node *dn, void *data)
 {
        struct msi_counts *counts = data;
-       const u32 *p;
+       const __be32 *p;
        u32 class;
 
        pr_debug("rtas_msi: counting %s\n", dn->full_name);
 
        p = of_get_property(dn, "class-code", NULL);
-       class = p ? *p : 0;
+       class = p ? be32_to_cpup(p) : 0;
 
        if ((class >> 8) != PCI_CLASS_BRIDGE_PCI)
                counts->num_devices++;
@@ -249,7 +251,7 @@ static void *count_non_bridge_devices(struct device_node *dn, void *data)
 static void *count_spare_msis(struct device_node *dn, void *data)
 {
        struct msi_counts *counts = data;
-       const u32 *p;
+       const __be32 *p;
        int req;
 
        if (dn == counts->requestor)
@@ -260,11 +262,11 @@ static void *count_spare_msis(struct device_node *dn, void *data)
                req = 0;
                p = of_get_property(dn, "ibm,req#msi", NULL);
                if (p)
-                       req = *p;
+                       req = be32_to_cpup(p);
 
                p = of_get_property(dn, "ibm,req#msi-x", NULL);
                if (p)
-                       req = max(req, (int)*p);
+                       req = max(req, (int)be32_to_cpup(p));
        }
 
        if (req < counts->quota)
index 7bfaf58d4664460db12c94499fc151e251f47f68..d7096f2f7751a5a0e41cb30ee48fef3242901f09 100644 (file)
@@ -43,8 +43,8 @@ static char nvram_buf[NVRW_CNT];      /* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
 struct err_log_info {
-       int error_type;
-       unsigned int seq_num;
+       __be32 error_type;
+       __be32 seq_num;
 };
 
 struct nvram_os_partition {
@@ -79,9 +79,9 @@ static const char *pseries_nvram_os_partitions[] = {
 };
 
 struct oops_log_info {
-       u16 version;
-       u16 report_length;
-       u64 timestamp;
+       __be16 version;
+       __be16 report_length;
+       __be64 timestamp;
 } __attribute__((packed));
 
 static void oops_to_nvram(struct kmsg_dumper *dumper,
@@ -291,8 +291,8 @@ int nvram_write_os_partition(struct nvram_os_partition *part, char * buff,
                length = part->size;
        }
 
-       info.error_type = err_type;
-       info.seq_num = error_log_cnt;
+       info.error_type = cpu_to_be32(err_type);
+       info.seq_num = cpu_to_be32(error_log_cnt);
 
        tmp_index = part->index;
 
@@ -364,8 +364,8 @@ int nvram_read_partition(struct nvram_os_partition *part, char *buff,
        }
 
        if (part->os_partition) {
-               *error_log_cnt = info.seq_num;
-               *err_type = info.error_type;
+               *error_log_cnt = be32_to_cpu(info.seq_num);
+               *err_type = be32_to_cpu(info.error_type);
        }
 
        return 0;
@@ -529,9 +529,9 @@ static int zip_oops(size_t text_len)
                pr_err("nvram: logging uncompressed oops/panic report\n");
                return -1;
        }
-       oops_hdr->version = OOPS_HDR_VERSION;
-       oops_hdr->report_length = (u16) zipped_len;
-       oops_hdr->timestamp = get_seconds();
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(zipped_len);
+       oops_hdr->timestamp = cpu_to_be64(get_seconds());
        return 0;
 }
 
@@ -574,9 +574,9 @@ static int nvram_pstore_write(enum pstore_type_id type,
                                clobbering_unread_rtas_event())
                return -1;
 
-       oops_hdr->version = OOPS_HDR_VERSION;
-       oops_hdr->report_length = (u16) size;
-       oops_hdr->timestamp = get_seconds();
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(size);
+       oops_hdr->timestamp = cpu_to_be64(get_seconds());
 
        if (compressed)
                err_type = ERR_TYPE_KERNEL_PANIC_GZ;
@@ -670,16 +670,16 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
                size_t length, hdr_size;
 
                oops_hdr = (struct oops_log_info *)buff;
-               if (oops_hdr->version < OOPS_HDR_VERSION) {
+               if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
                        /* Old format oops header had 2-byte record size */
                        hdr_size = sizeof(u16);
-                       length = oops_hdr->version;
+                       length = be16_to_cpu(oops_hdr->version);
                        time->tv_sec = 0;
                        time->tv_nsec = 0;
                } else {
                        hdr_size = sizeof(*oops_hdr);
-                       length = oops_hdr->report_length;
-                       time->tv_sec = oops_hdr->timestamp;
+                       length = be16_to_cpu(oops_hdr->report_length);
+                       time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
                        time->tv_nsec = 0;
                }
                *buf = kmalloc(length, GFP_KERNEL);
@@ -889,13 +889,13 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
                kmsg_dump_get_buffer(dumper, false,
                                     oops_data, oops_data_sz, &text_len);
                err_type = ERR_TYPE_KERNEL_PANIC;
-               oops_hdr->version = OOPS_HDR_VERSION;
-               oops_hdr->report_length = (u16) text_len;
-               oops_hdr->timestamp = get_seconds();
+               oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+               oops_hdr->report_length = cpu_to_be16(text_len);
+               oops_hdr->timestamp = cpu_to_be64(get_seconds());
        }
 
        (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
+               (int) (sizeof(*oops_hdr) + text_len), err_type,
                ++oops_count);
 
        spin_unlock_irqrestore(&lock, flags);
index 5f93856cdf479a3950cd053288174e1a85db4cad..70670a2d9cf2ddd691a936dbe489d8e338ed4029 100644 (file)
@@ -113,7 +113,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
        struct device_node *dn, *pdn;
        struct pci_bus *bus;
-       const uint32_t *pcie_link_speed_stats;
+       const __be32 *pcie_link_speed_stats;
 
        bus = bridge->bus;
 
@@ -122,7 +122,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
 
        for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
-               pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn,
+               pcie_link_speed_stats = of_get_property(pdn,
                        "ibm,pcie-link-speed-stats", NULL);
                if (pcie_link_speed_stats)
                        break;
@@ -135,7 +135,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
        }
 
-       switch (pcie_link_speed_stats[0]) {
+       switch (be32_to_cpup(pcie_link_speed_stats)) {
        case 0x01:
                bus->max_bus_speed = PCIE_SPEED_2_5GT;
                break;
@@ -147,7 +147,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                break;
        }
 
-       switch (pcie_link_speed_stats[1]) {
+       switch (be32_to_cpup(pcie_link_speed_stats)) {
        case 0x01:
                bus->cur_bus_speed = PCIE_SPEED_2_5GT;
                break;
index b7c43453236dfac7d001b583e554d8938b0ba426..85d9e37f5ccbf76c93c2cf71c1d70677d7a14366 100644 (file)
@@ -339,7 +339,7 @@ void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
                if (IS_ERR_VALUE(offset))
                        continue;
 
-               ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
+               ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
                if (!ocm_blk) {
                        printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
                        rh_free(ocm_reg->rh, offset);
index 314fced4fc14a50f2785d273c87fd590d241e9da..1e1a03d2d19fbbb35804d4fc28d8d9eac355a9c4 100644 (file)
@@ -101,7 +101,7 @@ config S390
        select GENERIC_CPU_DEVICES if !SMP
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_SMP_IDLE_THREAD
-       select GENERIC_TIME_VSYSCALL_OLD
+       select GENERIC_TIME_VSYSCALL
        select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
        select HAVE_ARCH_SECCOMP_FILTER
@@ -347,14 +347,14 @@ config SMP
          Even if you don't know what to do here, say Y.
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-64)"
-       range 2 64
+       int "Maximum number of CPUs (2-256)"
+       range 2 256
        depends on SMP
        default "32" if !64BIT
        default "64" if 64BIT
        help
          This allows you to specify the maximum number of CPUs which this
-         kernel will support.  The maximum supported value is 64 and the
+         kernel will support. The maximum supported value is 256 and the
          minimum value which makes sense is 2.
 
          This is purely to save memory - each supported CPU adds
index 46cae138ece2efa3617447d1fccf82fa504d4e7d..b3feabd39f31f8eead0a69f4340a8abc0ea17da6 100644 (file)
@@ -35,7 +35,6 @@ static u8 *ctrblk;
 static char keylen_flag;
 
 struct s390_aes_ctx {
-       u8 iv[AES_BLOCK_SIZE];
        u8 key[AES_MAX_KEY_SIZE];
        long enc;
        long dec;
@@ -56,8 +55,7 @@ struct pcc_param {
 
 struct s390_xts_ctx {
        u8 key[32];
-       u8 xts_param[16];
-       struct pcc_param pcc;
+       u8 pcc_key[32];
        long enc;
        long dec;
        int key_len;
@@ -441,30 +439,36 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        return aes_set_key(tfm, in_key, key_len);
 }
 
-static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
+static int cbc_aes_crypt(struct blkcipher_desc *desc, long func,
                         struct blkcipher_walk *walk)
 {
+       struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
        int ret = blkcipher_walk_virt(desc, walk);
        unsigned int nbytes = walk->nbytes;
+       struct {
+               u8 iv[AES_BLOCK_SIZE];
+               u8 key[AES_MAX_KEY_SIZE];
+       } param;
 
        if (!nbytes)
                goto out;
 
-       memcpy(param, walk->iv, AES_BLOCK_SIZE);
+       memcpy(param.iv, walk->iv, AES_BLOCK_SIZE);
+       memcpy(param.key, sctx->key, sctx->key_len);
        do {
                /* only use complete blocks */
                unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
                u8 *out = walk->dst.virt.addr;
                u8 *in = walk->src.virt.addr;
 
-               ret = crypt_s390_kmc(func, param, out, in, n);
+               ret = crypt_s390_kmc(func, &param, out, in, n);
                if (ret < 0 || ret != n)
                        return -EIO;
 
                nbytes &= AES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
        } while ((nbytes = walk->nbytes));
-       memcpy(walk->iv, param, AES_BLOCK_SIZE);
+       memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
 
 out:
        return ret;
@@ -481,7 +485,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
                return fallback_blk_enc(desc, dst, src, nbytes);
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
+       return cbc_aes_crypt(desc, sctx->enc, &walk);
 }
 
 static int cbc_aes_decrypt(struct blkcipher_desc *desc,
@@ -495,7 +499,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
                return fallback_blk_dec(desc, dst, src, nbytes);
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
+       return cbc_aes_crypt(desc, sctx->dec, &walk);
 }
 
 static struct crypto_alg cbc_aes_alg = {
@@ -586,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                xts_ctx->enc = KM_XTS_128_ENCRYPT;
                xts_ctx->dec = KM_XTS_128_DECRYPT;
                memcpy(xts_ctx->key + 16, in_key, 16);
-               memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16);
+               memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
                break;
        case 48:
                xts_ctx->enc = 0;
@@ -597,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                xts_ctx->enc = KM_XTS_256_ENCRYPT;
                xts_ctx->dec = KM_XTS_256_DECRYPT;
                memcpy(xts_ctx->key, in_key, 32);
-               memcpy(xts_ctx->pcc.key, in_key + 32, 32);
+               memcpy(xts_ctx->pcc_key, in_key + 32, 32);
                break;
        default:
                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -616,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
        unsigned int nbytes = walk->nbytes;
        unsigned int n;
        u8 *in, *out;
-       void *param;
+       struct pcc_param pcc_param;
+       struct {
+               u8 key[32];
+               u8 init[16];
+       } xts_param;
 
        if (!nbytes)
                goto out;
 
-       memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block));
-       memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit));
-       memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts));
-       memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
-       param = xts_ctx->pcc.key + offset;
-       ret = crypt_s390_pcc(func, param);
+       memset(pcc_param.block, 0, sizeof(pcc_param.block));
+       memset(pcc_param.bit, 0, sizeof(pcc_param.bit));
+       memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
+       memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
+       memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
+       ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
        if (ret < 0)
                return -EIO;
 
-       memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
-       param = xts_ctx->key + offset;
+       memcpy(xts_param.key, xts_ctx->key, 32);
+       memcpy(xts_param.init, pcc_param.xts, 16);
        do {
                /* only use complete blocks */
                n = nbytes & ~(AES_BLOCK_SIZE - 1);
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
 
-               ret = crypt_s390_km(func, param, out, in, n);
+               ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
                if (ret < 0 || ret != n)
                        return -EIO;
 
index 316c8503a3b4fda3824ca071065f145038b34a0c..114258eeaacdbbd796a07605e74c53d9610ba3be 100644 (file)
@@ -48,33 +48,21 @@ static inline void clear_page(void *page)
                : "memory", "cc");
 }
 
+/*
+ * copy_page uses the mvcl instruction with 0xb0 padding byte in order to
+ * bypass caches when copying a page. Especially when copying huge pages
+ * this keeps L1 and L2 data caches alive.
+ */
 static inline void copy_page(void *to, void *from)
 {
-       if (MACHINE_HAS_MVPG) {
-               register unsigned long reg0 asm ("0") = 0;
-               asm volatile(
-                       "       mvpg    %0,%1"
-                       : : "a" (to), "a" (from), "d" (reg0)
-                       : "memory", "cc");
-       } else
-               asm volatile(
-                       "       mvc     0(256,%0),0(%1)\n"
-                       "       mvc     256(256,%0),256(%1)\n"
-                       "       mvc     512(256,%0),512(%1)\n"
-                       "       mvc     768(256,%0),768(%1)\n"
-                       "       mvc     1024(256,%0),1024(%1)\n"
-                       "       mvc     1280(256,%0),1280(%1)\n"
-                       "       mvc     1536(256,%0),1536(%1)\n"
-                       "       mvc     1792(256,%0),1792(%1)\n"
-                       "       mvc     2048(256,%0),2048(%1)\n"
-                       "       mvc     2304(256,%0),2304(%1)\n"
-                       "       mvc     2560(256,%0),2560(%1)\n"
-                       "       mvc     2816(256,%0),2816(%1)\n"
-                       "       mvc     3072(256,%0),3072(%1)\n"
-                       "       mvc     3328(256,%0),3328(%1)\n"
-                       "       mvc     3584(256,%0),3584(%1)\n"
-                       "       mvc     3840(256,%0),3840(%1)\n"
-                       : : "a" (to), "a" (from) : "memory");
+       register void *reg2 asm ("2") = to;
+       register unsigned long reg3 asm ("3") = 0x1000;
+       register void *reg4 asm ("4") = from;
+       register unsigned long reg5 asm ("5") = 0xb0001000;
+       asm volatile(
+               "       mvcl    2,4"
+               : "+d" (reg2), "+d" (reg3), "+d" (reg4), "+d" (reg5)
+               : : "memory", "cc");
 }
 
 #define clear_user_page(page, vaddr, pg)       clear_page(page)
index 30ef748bc161eb3a7f52084ea763d54fe6ed09fc..2f390956c7c1c930722320956a54d1e65ada5673 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <asm/chpid.h>
+#include <asm/cpu.h>
 
 #define SCLP_CHP_INFO_MASK_SIZE                32
 
@@ -37,7 +38,7 @@ struct sclp_cpu_info {
        unsigned int standby;
        unsigned int combined;
        int has_cpu_type;
-       struct sclp_cpu_entry cpu[255];
+       struct sclp_cpu_entry cpu[MAX_CPU_ADDRESS + 1];
 };
 
 int sclp_get_cpu_info(struct sclp_cpu_info *info);
index a73eb2e1e918351356005b99940629235ef6ee98..bc9746a7d47c53edf219c4b4b1f500bc0728a284 100644 (file)
@@ -26,8 +26,9 @@ struct vdso_data {
        __u64 wtom_clock_nsec;          /*                              0x28 */
        __u32 tz_minuteswest;           /* Minutes west of Greenwich    0x30 */
        __u32 tz_dsttime;               /* Type of dst correction       0x34 */
-       __u32 ectg_available;
-       __u32 ntp_mult;                 /* NTP adjusted multiplier      0x3C */
+       __u32 ectg_available;           /* ECTG instruction present     0x38 */
+       __u32 tk_mult;                  /* Mult. used for xtime_nsec    0x3c */
+       __u32 tk_shift;                 /* Shift used for xtime_nsec    0x40 */
 };
 
 struct vdso_per_cpu_data {
index 2416138ebd3e5fa5584d897737e27ab7e0978383..e4c99a1836511b16b90de5b4591bea5dc9fc8e69 100644 (file)
@@ -65,12 +65,14 @@ int main(void)
        DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
        DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
        DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
-       DEFINE(__VDSO_NTP_MULT, offsetof(struct vdso_data, ntp_mult));
+       DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult));
+       DEFINE(__VDSO_TK_SHIFT, offsetof(struct vdso_data, tk_shift));
        DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));
        DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));
        /* constants used by the vdso */
        DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
        DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+       DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
        DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
        BLANK();
        /* idle data offsets */
index 6e24429784097c034d41072929e446a5ef49cab4..95e7ba0fbb7eb1323b45300c4f6afcae04103dc8 100644 (file)
@@ -194,7 +194,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
                return -EINVAL;
 
        /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
-       regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+       regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
                (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 |
                (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 |
                (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE);
index 4a460c44e17ec15763da0cf24207ed048fa929f9..813ec7260878662d097ba90ef04d90b6f183367d 100644 (file)
@@ -78,7 +78,7 @@ PGM_CHECK_DEFAULT                     /* 34 */
 PGM_CHECK_DEFAULT                      /* 35 */
 PGM_CHECK_DEFAULT                      /* 36 */
 PGM_CHECK_DEFAULT                      /* 37 */
-PGM_CHECK_DEFAULT                      /* 38 */
+PGM_CHECK_64BIT(do_dat_exception)      /* 38 */
 PGM_CHECK_64BIT(do_dat_exception)      /* 39 */
 PGM_CHECK_64BIT(do_dat_exception)      /* 3a */
 PGM_CHECK_64BIT(do_dat_exception)      /* 3b */
index fb535874a2464853168c9a9182620acf10e37c74..d8fd508ccd1e180b7679d24939b253d31a56bc26 100644 (file)
@@ -94,7 +94,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
                return -EINVAL;
 
        /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
-       regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+       regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
                (user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
        /* Check for invalid user address space control. */
        if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
index 064c3082ab33604c4d360d7267ecd5e0f6ac1ac1..dd95f1631621722ca9d35a5d67269b152cb630d2 100644 (file)
@@ -108,20 +108,10 @@ static void fixup_clock_comparator(unsigned long long delta)
        set_clock_comparator(S390_lowcore.clock_comparator);
 }
 
-static int s390_next_ktime(ktime_t expires,
+static int s390_next_event(unsigned long delta,
                           struct clock_event_device *evt)
 {
-       struct timespec ts;
-       u64 nsecs;
-
-       ts.tv_sec = ts.tv_nsec = 0;
-       monotonic_to_bootbased(&ts);
-       nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires));
-       do_div(nsecs, 125);
-       S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9);
-       /* Program the maximum value if we have an overflow (== year 2042) */
-       if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc))
-               S390_lowcore.clock_comparator = -1ULL;
+       S390_lowcore.clock_comparator = get_tod_clock() + delta;
        set_clock_comparator(S390_lowcore.clock_comparator);
        return 0;
 }
@@ -146,15 +136,14 @@ void init_cpu_timer(void)
        cpu = smp_processor_id();
        cd = &per_cpu(comparators, cpu);
        cd->name                = "comparator";
-       cd->features            = CLOCK_EVT_FEAT_ONESHOT |
-                                 CLOCK_EVT_FEAT_KTIME;
+       cd->features            = CLOCK_EVT_FEAT_ONESHOT;
        cd->mult                = 16777;
        cd->shift               = 12;
        cd->min_delta_ns        = 1;
        cd->max_delta_ns        = LONG_MAX;
        cd->rating              = 400;
        cd->cpumask             = cpumask_of(cpu);
-       cd->set_next_ktime      = s390_next_ktime;
+       cd->set_next_event      = s390_next_event;
        cd->set_mode            = s390_set_mode;
 
        clockevents_register_device(cd);
@@ -221,21 +210,30 @@ struct clocksource * __init clocksource_default_clock(void)
        return &clocksource_tod;
 }
 
-void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
-                       struct clocksource *clock, u32 mult)
+void update_vsyscall(struct timekeeper *tk)
 {
-       if (clock != &clocksource_tod)
+       u64 nsecps;
+
+       if (tk->clock != &clocksource_tod)
                return;
 
        /* Make userspace gettimeofday spin until we're done. */
        ++vdso_data->tb_update_count;
        smp_wmb();
-       vdso_data->xtime_tod_stamp = clock->cycle_last;
-       vdso_data->xtime_clock_sec = wall_time->tv_sec;
-       vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
-       vdso_data->wtom_clock_sec = wtm->tv_sec;
-       vdso_data->wtom_clock_nsec = wtm->tv_nsec;
-       vdso_data->ntp_mult = mult;
+       vdso_data->xtime_tod_stamp = tk->clock->cycle_last;
+       vdso_data->xtime_clock_sec = tk->xtime_sec;
+       vdso_data->xtime_clock_nsec = tk->xtime_nsec;
+       vdso_data->wtom_clock_sec =
+               tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
+       vdso_data->wtom_clock_nsec = tk->xtime_nsec +
+               + (tk->wall_to_monotonic.tv_nsec << tk->shift);
+       nsecps = (u64) NSEC_PER_SEC << tk->shift;
+       while (vdso_data->wtom_clock_nsec >= nsecps) {
+               vdso_data->wtom_clock_nsec -= nsecps;
+               vdso_data->wtom_clock_sec++;
+       }
+       vdso_data->tk_mult = tk->mult;
+       vdso_data->tk_shift = tk->shift;
        smp_wmb();
        ++vdso_data->tb_update_count;
 }
index a84476f2a9bb3ae488eb7a936021a744a822dd31..613649096783401e0cf9acf73069dff48a35e438 100644 (file)
@@ -125,7 +125,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
                psal[i] = 0x80000000;
 
        lowcore->paste[4] = (u32)(addr_t) psal;
-       psal[0] = 0x20000000;
+       psal[0] = 0x02000000;
        psal[2] = (u32)(addr_t) aste;
        *(unsigned long *) (aste + 2) = segment_table +
                _ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT;
index b2224e0b974ce5beff26c4d1e7838d48e0232ae9..65fc3979c2f11bb037fd7f646c18a1188b4c4553 100644 (file)
@@ -38,25 +38,21 @@ __kernel_clock_gettime:
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,2f
        ahi     %r0,-1
-2:     ms      %r0,__VDSO_NTP_MULT(%r5)        /* cyc2ns(clock,cycle_delta) */
+2:     ms      %r0,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
        lr      %r2,%r0
-       l       %r0,__VDSO_NTP_MULT(%r5)
+       l       %r0,__VDSO_TK_MULT(%r5)
        ltr     %r1,%r1
        mr      %r0,%r0
        jnm     3f
-       a       %r0,__VDSO_NTP_MULT(%r5)
+       a       %r0,__VDSO_TK_MULT(%r5)
 3:     alr     %r0,%r2
-       srdl    %r0,12
-       al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + xtime */
-       al      %r1,__VDSO_XTIME_NSEC+4(%r5)
-       brc     12,4f
-       ahi     %r0,1
-4:     l       %r2,__VDSO_XTIME_SEC+4(%r5)
-       al      %r0,__VDSO_WTOM_NSEC(%r5)       /*  + wall_to_monotonic */
+       al      %r0,__VDSO_WTOM_NSEC(%r5)
        al      %r1,__VDSO_WTOM_NSEC+4(%r5)
        brc     12,5f
        ahi     %r0,1
-5:     al      %r2,__VDSO_WTOM_SEC+4(%r5)
+5:     l       %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
+       srdl    %r0,0(%r2)                      /*  >> tk->shift */
+       l       %r2,__VDSO_WTOM_SEC+4(%r5)
        cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
        jne     1b
        basr    %r5,0
@@ -86,20 +82,21 @@ __kernel_clock_gettime:
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,12f
        ahi     %r0,-1
-12:    ms      %r0,__VDSO_NTP_MULT(%r5)        /* cyc2ns(clock,cycle_delta) */
+12:    ms      %r0,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
        lr      %r2,%r0
-       l       %r0,__VDSO_NTP_MULT(%r5)
+       l       %r0,__VDSO_TK_MULT(%r5)
        ltr     %r1,%r1
        mr      %r0,%r0
        jnm     13f
-       a       %r0,__VDSO_NTP_MULT(%r5)
+       a       %r0,__VDSO_TK_MULT(%r5)
 13:    alr     %r0,%r2
-       srdl    %r0,12
-       al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + xtime */
+       al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
        al      %r1,__VDSO_XTIME_NSEC+4(%r5)
        brc     12,14f
        ahi     %r0,1
-14:    l       %r2,__VDSO_XTIME_SEC+4(%r5)
+14:    l       %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
+       srdl    %r0,0(%r2)                      /*  >> tk->shift */
+       l       %r2,__VDSO_XTIME_SEC+4(%r5)
        cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
        jne     11b
        basr    %r5,0
index 2d3633175e3be520850ad6b48b30e94c88058072..fd621a950f7c70e917ea6ca44bb4a5fd5b9869ab 100644 (file)
@@ -35,15 +35,14 @@ __kernel_gettimeofday:
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,3f
        ahi     %r0,-1
-3:     ms      %r0,__VDSO_NTP_MULT(%r5)        /* cyc2ns(clock,cycle_delta) */
+3:     ms      %r0,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
        st      %r0,24(%r15)
-       l       %r0,__VDSO_NTP_MULT(%r5)
+       l       %r0,__VDSO_TK_MULT(%r5)
        ltr     %r1,%r1
        mr      %r0,%r0
        jnm     4f
-       a       %r0,__VDSO_NTP_MULT(%r5)
+       a       %r0,__VDSO_TK_MULT(%r5)
 4:     al      %r0,24(%r15)
-       srdl    %r0,12
        al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + xtime */
        al      %r1,__VDSO_XTIME_NSEC+4(%r5)
        brc     12,5f
@@ -51,6 +50,8 @@ __kernel_gettimeofday:
 5:     mvc     24(4,%r15),__VDSO_XTIME_SEC+4(%r5)
        cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
        jne     1b
+       l       %r4,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
+       srdl    %r0,0(%r4)                      /*  >> tk->shift */
        l       %r4,24(%r15)                    /* get tv_sec from stack */
        basr    %r5,0
 6:     ltr     %r0,%r0
index 176e1f75f9aa6c1554dbf0818b7d4cd6661c0846..34deba7c7ed1d8b18036b0b07f9b7cd9d41e9259 100644 (file)
@@ -23,7 +23,9 @@ __kernel_clock_getres:
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC
        je      0f
-       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
+       je      0f
+       cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        jne     2f
        larl    %r5,_vdso_data
        icm     %r0,15,__LC_ECTG_OK(%r5)
index d46c95ed5f19ae8c25f9255b32338e8cc3197906..91940ed33a4ab21686f890481545cbfdd9404468 100644 (file)
@@ -22,7 +22,9 @@ __kernel_clock_gettime:
        larl    %r5,_vdso_data
        cghi    %r2,__CLOCK_REALTIME
        je      4f
-       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
+       je      9f
+       cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        je      9f
        cghi    %r2,__CLOCK_MONOTONIC
        jne     12f
@@ -34,14 +36,13 @@ __kernel_clock_gettime:
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     0b
        stck    48(%r15)                        /* Store TOD clock */
+       lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
+       lg      %r0,__VDSO_WTOM_SEC(%r5)
        lg      %r1,48(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
-       msgf    %r1,__VDSO_NTP_MULT(%r5)        /*  * NTP adjustment */
-       srlg    %r1,%r1,12                      /* cyc2ns(clock,cycle_delta) */
-       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + xtime */
-       lg      %r0,__VDSO_XTIME_SEC(%r5)
-       alg     %r1,__VDSO_WTOM_NSEC(%r5)       /*  + wall_to_monotonic */
-       alg     %r0,__VDSO_WTOM_SEC(%r5)
+       msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
+       alg     %r1,__VDSO_WTOM_NSEC(%r5)
+       srlg    %r1,%r1,0(%r2)                  /*  >> tk->shift */
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     0b
        larl    %r5,13f
@@ -62,12 +63,13 @@ __kernel_clock_gettime:
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     5b
        stck    48(%r15)                        /* Store TOD clock */
+       lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
        lg      %r1,48(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
-       msgf    %r1,__VDSO_NTP_MULT(%r5)        /*  * NTP adjustment */
-       srlg    %r1,%r1,12                      /* cyc2ns(clock,cycle_delta) */
-       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + xtime */
-       lg      %r0,__VDSO_XTIME_SEC(%r5)
+       msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
+       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
+       srlg    %r1,%r1,0(%r2)                  /*  >> tk->shift */
+       lg      %r0,__VDSO_XTIME_SEC(%r5)       /* tk->xtime_sec */
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     5b
        larl    %r5,13f
index 36ee674722ec3a76b3439fe78752f024ba5ba434..d0860d1d0cccfafe86320a07380ea14ddff1a284 100644 (file)
@@ -31,12 +31,13 @@ __kernel_gettimeofday:
        stck    48(%r15)                        /* Store TOD clock */
        lg      %r1,48(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
-       msgf    %r1,__VDSO_NTP_MULT(%r5)        /*  * NTP adjustment */
-       srlg    %r1,%r1,12                      /* cyc2ns(clock,cycle_delta) */
-       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + xtime.tv_nsec */
-       lg      %r0,__VDSO_XTIME_SEC(%r5)       /* xtime.tv_sec */
+       msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
+       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
+       lg      %r0,__VDSO_XTIME_SEC(%r5)       /* tk->xtime_sec */
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     0b
+       lgf     %r5,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
+       srlg    %r1,%r1,0(%r5)                  /*  >> tk->shift */
        larl    %r5,5f
 2:     clg     %r1,0(%r5)
        jl      3f
index 97e03caf782598a20857ab276ff03df701c4c3f9..dbdab3e7a1a6266ca3b96cd692d298896bc9902f 100644 (file)
@@ -78,11 +78,14 @@ static size_t copy_in_kernel(size_t count, void __user *to,
  * contains the (negative) exception code.
  */
 #ifdef CONFIG_64BIT
+
 static unsigned long follow_table(struct mm_struct *mm,
                                  unsigned long address, int write)
 {
        unsigned long *table = (unsigned long *)__pa(mm->pgd);
 
+       if (unlikely(address > mm->context.asce_limit - 1))
+               return -0x38UL;
        switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
        case _ASCE_TYPE_REGION1:
                table = table + ((address >> 53) & 0x7ff);
index 7b95f29e31749ec180e67028424580fadda1c3af..3baff31e58cf22c30b2d770162ee3c4b10c087ea 100644 (file)
@@ -6,7 +6,7 @@ lib-y  = delay.o memmove.o memchr.o \
         checksum.o strlen.o div64.o div64-generic.o
 
 # Extracted from libgcc
-lib-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
+obj-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
         ashlsi3.o ashrsi3.o ashiftrt.o lshrsi3.o \
         udiv_qrnnd.o
 
index 8358dc144959aacc8b369830c21c130593b9a804..0f9e94537eee78d9d41fffe82e32fc0098811ed2 100644 (file)
@@ -619,7 +619,7 @@ static inline unsigned long pte_present(pte_t pte)
 }
 
 #define pte_accessible pte_accessible
-static inline unsigned long pte_accessible(pte_t a)
+static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
 {
        return pte_val(a) & _PAGE_VALID;
 }
@@ -847,7 +847,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
         * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
         *             and SUN4V pte layout, so this inline test is fine.
         */
-       if (likely(mm != &init_mm) && pte_accessible(orig))
+       if (likely(mm != &init_mm) && pte_accessible(mm, orig))
                tlb_batch_add(mm, addr, ptep, orig, fullmm);
 }
 
index 48d92bbe62e9eae2460df5fb99bdd83974b9aecb..36e658a4291c685e12d554dfd74ac153179591dc 100644 (file)
@@ -33,12 +33,11 @@ MODE_INCLUDE        += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
 HEADER_ARCH    := $(SUBARCH)
 
-# Additional ARCH settings for x86
-ifeq ($(SUBARCH),i386)
-        HEADER_ARCH := x86
+ifneq ($(filter $(SUBARCH),x86 x86_64 i386),)
+       HEADER_ARCH := x86
 endif
-ifeq ($(SUBARCH),x86_64)
-        HEADER_ARCH := x86
+
+ifdef CONFIG_64BIT
        KBUILD_CFLAGS += -mcmodel=large
 endif
 
index 4d6fdf68edf31cf31b993081a6d9432dff6e3c5b..799d7e413bf57247f258b25ad6306a91b363e67c 100644 (file)
@@ -19,7 +19,7 @@ struct stack_frame {
        unsigned long return_address;
 };
 
-static void print_stack_trace(unsigned long *sp, unsigned long bp)
+static void do_stack_trace(unsigned long *sp, unsigned long bp)
 {
        int reliable;
        unsigned long addr;
@@ -94,5 +94,5 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        }
        printk(KERN_CONT "\n");
 
-       print_stack_trace(sp, bp);
+       do_stack_trace(sp, bp);
 }
index e903c71f7e69822d2ce5240b957399dbab783037..0952ecd60ecaf7e8fcadb4360731ba22dea22c22 100644 (file)
@@ -26,6 +26,7 @@ config X86
        select HAVE_AOUT if X86_32
        select HAVE_UNSTABLE_SCHED_CLOCK
        select ARCH_SUPPORTS_NUMA_BALANCING
+       select ARCH_SUPPORTS_INT128 if X86_64
        select ARCH_WANTS_PROT_NUMA_PROT_NONE
        select HAVE_IDE
        select HAVE_OPROFILE
index 41250fb33985e179f63b399cfb6a2d10c93a4e29..57d021507120ed2a2b04d8b7a673a11bf73f0afc 100644 (file)
@@ -31,6 +31,9 @@ ifeq ($(CONFIG_X86_32),y)
 
         KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return
 
+        # Don't autogenerate MMX or SSE instructions
+        KBUILD_CFLAGS += -mno-mmx -mno-sse
+
         # Never want PIC in a 32-bit kernel, prevent breakage with GCC built
         # with nonstandard options
         KBUILD_CFLAGS += -fno-pic
@@ -57,8 +60,11 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
+        # Don't autogenerate MMX or SSE instructions
+        KBUILD_CFLAGS += -mno-mmx -mno-sse
+
        # Use -mpreferred-stack-boundary=3 if supported.
-       KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3)
+       KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
 
         # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
         cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
index dce69a2568963bf97efa8a3598be4645cc93834b..d9c11956fce0e9128bfa5432ee3c752f2acd4999 100644 (file)
@@ -53,18 +53,18 @@ $(obj)/cpustr.h: $(obj)/mkcpustr FORCE
 
 # How to compile the 16-bit code.  Note we always compile for -march=i386,
 # that way we can complain to the user if the CPU is insufficient.
-KBUILD_CFLAGS  := $(USERINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+KBUILD_CFLAGS  := $(USERINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ \
                   -DDISABLE_BRANCH_PROFILING \
                   -Wall -Wstrict-prototypes \
                   -march=i386 -mregparm=3 \
                   -include $(srctree)/$(src)/code16gcc.h \
                   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
+                  -mno-mmx -mno-sse \
                   $(call cc-option, -ffreestanding) \
                   $(call cc-option, -fno-toplevel-reorder,\
-                       $(call cc-option, -fno-unit-at-a-time)) \
+                  $(call cc-option, -fno-unit-at-a-time)) \
                   $(call cc-option, -fno-stack-protector) \
                   $(call cc-option, -mpreferred-stack-boundary=2)
-KBUILD_CFLAGS  += $(call cc-option, -m32)
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
 
index dcd90df10ab4e271dd6ee0e3ed737015326efa18..c8a6792e78423ac2efcb091f8d2553a35fb34c68 100644 (file)
@@ -13,6 +13,7 @@ KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 cflags-$(CONFIG_X86_32) := -march=i386
 cflags-$(CONFIG_X86_64) := -mcmodel=small
 KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -mno-mmx -mno-sse
 KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
 KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
 
index 7d6ba9db1be99696784aeba62343eeebff9c32dd..e0fc24db234ac1263c96fdc18d0bf4f553647198 100644 (file)
@@ -3,8 +3,9 @@
 #
 
 avx_supported := $(call as-instr,vpxor %xmm0$(comma)%xmm0$(comma)%xmm0,yes,no)
+avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\
+                               $(comma)4)$(comma)%ymm2,yes,no)
 
-obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o
 obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o
 
 obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
index f80e668785c0bf5f36383e5ab49495c24f93f843..835488b745eed5ce9484a40dfe56bf839f51d33d 100644 (file)
@@ -34,7 +34,7 @@
 #include <asm/cpu_device_id.h>
 #include <asm/i387.h>
 #include <asm/crypto/aes.h>
-#include <asm/crypto/ablk_helper.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/internal/aead.h>
 #include <linux/workqueue.h>
index 414fe5d7946be077c25ba19160496c4bf910b1ab..4209a76fcdaad4225fb9c15fb954dfb5ad495c74 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/ctr.h>
 #include <crypto/lrw.h>
@@ -21,7 +22,6 @@
 #include <asm/xcr.h>
 #include <asm/xsave.h>
 #include <asm/crypto/camellia.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 #define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
index 37fd0c0a81ea8861f30a649b01cee8a6c11db4e5..87a041a10f4ac1fe7cceccc82eb24fcb03f92fa4 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/ctr.h>
 #include <crypto/lrw.h>
@@ -21,7 +22,6 @@
 #include <asm/xcr.h>
 #include <asm/xsave.h>
 #include <asm/crypto/camellia.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 #define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
index c6631813dc115c609e186044790aa5461cb6f0c7..e6a3700489b94119c514177f4a2a0b52e5423c13 100644 (file)
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/cast5.h>
 #include <crypto/cryptd.h>
 #include <crypto/ctr.h>
 #include <asm/xcr.h>
 #include <asm/xsave.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 #define CAST5_PARALLEL_BLOCKS 16
index 8d0dfb86a5593554e0d536a48c28572ecc92c91d..09f3677393e4b888895c83bae05d114df0d5184c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/cast6.h>
 #include <crypto/cryptd.h>
@@ -37,7 +38,6 @@
 #include <crypto/xts.h>
 #include <asm/xcr.h>
 #include <asm/xsave.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 #define CAST6_PARALLEL_BLOCKS 8
index 23aabc6c20a5376fa81cf49ff9893ec76b6cdf05..2fae489b15246525991e6e606b8e01923e298263 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/ctr.h>
 #include <crypto/lrw.h>
@@ -22,7 +23,6 @@
 #include <asm/xcr.h>
 #include <asm/xsave.h>
 #include <asm/crypto/serpent-avx.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 #define SERPENT_AVX2_PARALLEL_BLOCKS 16
index 9ae83cf8d21e987e2e3bf9656a51ecaf61644427..ff487087097254f8368d035db08d02472dc9b76e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/serpent.h>
 #include <crypto/cryptd.h>
@@ -38,7 +39,6 @@
 #include <asm/xcr.h>
 #include <asm/xsave.h>
 #include <asm/crypto/serpent-avx.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 /* 8-way parallel cipher functions */
index 97a356ece24d2b74d18090760e988c45d2bc914a..8c95f86373061680f4d8f4418d4da77f9123c111 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/serpent.h>
 #include <crypto/cryptd.h>
@@ -42,7 +43,6 @@
 #include <crypto/lrw.h>
 #include <crypto/xts.h>
 #include <asm/crypto/serpent-sse2.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 
 static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
index 50226c4b86ed338da70cb285a53e1e86d210d5f4..f248546da1caa956014dfd9648814ad37f2ca8d3 100644 (file)
@@ -281,7 +281,7 @@ static int __init sha256_ssse3_mod_init(void)
        /* allow AVX to override SSSE3, it's a little faster */
        if (avx_usable()) {
 #ifdef CONFIG_AS_AVX2
-               if (boot_cpu_has(X86_FEATURE_AVX2))
+               if (boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_BMI2))
                        sha256_transform_asm = sha256_transform_rorx;
                else
 #endif
@@ -319,4 +319,4 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated");
 
 MODULE_ALIAS("sha256");
-MODULE_ALIAS("sha384");
+MODULE_ALIAS("sha224");
index a62ba541884ef1a15da1082d9d2ca48296c563ec..4e3c665be1296f16cedde6f402249316b75bc4ed 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <crypto/ablk_helper.h>
 #include <crypto/algapi.h>
 #include <crypto/twofish.h>
 #include <crypto/cryptd.h>
@@ -39,7 +40,6 @@
 #include <asm/xcr.h>
 #include <asm/xsave.h>
 #include <asm/crypto/twofish.h>
-#include <asm/crypto/ablk_helper.h>
 #include <asm/crypto/glue_helper.h>
 #include <crypto/scatterwalk.h>
 #include <linux/workqueue.h>
index da31c8b8a92ddd0459bc1b6a0a7058f4d1f93766..b17f4f48ecd7d9a48646a295c7ffaaa544399fa8 100644 (file)
@@ -77,7 +77,7 @@ static inline void atomic_sub(int i, atomic_t *v)
  */
 static inline int atomic_sub_and_test(int i, atomic_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", "e");
 }
 
 /**
@@ -141,7 +141,7 @@ static inline int atomic_inc_and_test(atomic_t *v)
  */
 static inline int atomic_add_negative(int i, atomic_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", "s");
 }
 
 /**
index 3f065c985aeed272d120e3cec19f04b9ee9f5254..46e9052bbd28cdea457130607cd5a50ddc5c6204 100644 (file)
@@ -72,7 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)
  */
 static inline int atomic64_sub_and_test(long i, atomic64_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", "e");
 }
 
 /**
@@ -138,7 +138,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v)
  */
 static inline int atomic64_add_negative(long i, atomic64_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", "s");
 }
 
 /**
index 6d76d093598930ce24476118fd68d690bb78035c..9fc1af74dc8393a5107742f12f82dd47be1db0ea 100644 (file)
@@ -205,7 +205,7 @@ static inline void change_bit(long nr, volatile unsigned long *addr)
  */
 static inline int test_and_set_bit(long nr, volatile unsigned long *addr)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, "Ir", nr, "%0", "c");
 }
 
 /**
@@ -251,7 +251,7 @@ static inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
  */
 static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, "Ir", nr, "%0", "c");
 }
 
 /**
@@ -304,7 +304,7 @@ static inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
  */
 static inline int test_and_change_bit(long nr, volatile unsigned long *addr)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, "Ir", nr, "%0", "c");
 }
 
 static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
index 5b23e605e707cb21e254f7ce964029a48b69ee54..4ad6560847b1f5f7c20644b52e27505339880e79 100644 (file)
@@ -52,7 +52,7 @@ static inline void local_sub(long i, local_t *l)
  */
 static inline int local_sub_and_test(long i, local_t *l)
 {
-       GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, "er", i, "%0", "e");
 }
 
 /**
@@ -92,7 +92,7 @@ static inline int local_inc_and_test(local_t *l)
  */
 static inline int local_add_negative(long i, local_t *l)
 {
-       GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, "er", i, "%0", "s");
 }
 
 /**
index 3d1999458709231affdc977df99530acf3a833ac..bbc8b12fa443d47ee9a8faa59b36767e7aec866c 100644 (file)
@@ -452,9 +452,16 @@ static inline int pte_present(pte_t a)
 }
 
 #define pte_accessible pte_accessible
-static inline int pte_accessible(pte_t a)
+static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
 {
-       return pte_flags(a) & _PAGE_PRESENT;
+       if (pte_flags(a) & _PAGE_PRESENT)
+               return true;
+
+       if ((pte_flags(a) & (_PAGE_PROTNONE | _PAGE_NUMA)) &&
+                       mm_tlb_flush_pending(mm))
+               return true;
+
+       return false;
 }
 
 static inline int pte_hidden(pte_t pte)
index 8729723636fd1632eebd92197dd292fa26de10d7..c8b051933b1b384ccd723267d99c9ff052875dff 100644 (file)
@@ -7,6 +7,12 @@
 
 DECLARE_PER_CPU(int, __preempt_count);
 
+/*
+ * We use the PREEMPT_NEED_RESCHED bit as an inverted NEED_RESCHED such
+ * that a decrement hitting 0 means we can and should reschedule.
+ */
+#define PREEMPT_ENABLED        (0 + PREEMPT_NEED_RESCHED)
+
 /*
  * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
  * that think a non-zero value indicates we cannot preempt.
@@ -74,6 +80,11 @@ static __always_inline void __preempt_count_sub(int val)
        __this_cpu_add_4(__preempt_count, -val);
 }
 
+/*
+ * Because we keep PREEMPT_NEED_RESCHED set when we do _not_ need to reschedule
+ * a decrement which hits zero means we have no preempt_count and should
+ * reschedule.
+ */
 static __always_inline bool __preempt_count_dec_and_test(void)
 {
        GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e");
index 1ff990f1de8e3f58f21fda00bc1a646b96eaba2b..8f7866a5b9a41df67475892353979c005ce8c09b 100644 (file)
@@ -16,8 +16,8 @@ cc_label:                                                             \
 #define GEN_UNARY_RMWcc(op, var, arg0, cc)                             \
        __GEN_RMWcc(op " " arg0, var, cc)
 
-#define GEN_BINARY_RMWcc(op, var, val, arg0, cc)                       \
-       __GEN_RMWcc(op " %1, " arg0, var, cc, "er" (val))
+#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
+       __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val))
 
 #else /* !CC_HAVE_ASM_GOTO */
 
@@ -33,8 +33,8 @@ do {                                                                  \
 #define GEN_UNARY_RMWcc(op, var, arg0, cc)                             \
        __GEN_RMWcc(op " " arg0, var, cc)
 
-#define GEN_BINARY_RMWcc(op, var, val, arg0, cc)                       \
-       __GEN_RMWcc(op " %2, " arg0, var, cc, "er" (val))
+#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
+       __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val))
 
 #endif /* CC_HAVE_ASM_GOTO */
 
diff --git a/arch/x86/include/asm/simd.h b/arch/x86/include/asm/simd.h
new file mode 100644 (file)
index 0000000..ee80b92
--- /dev/null
@@ -0,0 +1,11 @@
+
+#include <asm/i387.h>
+
+/*
+ * may_use_simd - whether it is allowable at this time to issue SIMD
+ *                instructions or access the SIMD register file
+ */
+static __must_check inline bool may_use_simd(void)
+{
+       return irq_fpu_usable();
+}
index 2874df24e7a448cd56631d87f5ac9e0fdd00cbc7..4cab890007a7267ecc7ce148eaa1fdfbee4a49df 100644 (file)
@@ -71,6 +71,17 @@ DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi);
  */
 DEFINE_IRQ_VECTOR_EVENT(irq_work);
 
+/*
+ * We must dis-allow sampling irq_work_exit() because perf event sampling
+ * itself can cause irq_work, which would lead to an infinite loop;
+ *
+ *  1) irq_work_exit happens
+ *  2) generates perf sample
+ *  3) generates irq_work
+ *  4) goto 1
+ */
+TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0);
+
 /*
  * call_function - called when entering/exiting a call function interrupt
  * vector handler
index dc1ec0dff939ecff5e55bcccaeb5bea322ad982a..ea04b342c026f8c8871f70a0c383d80651e12524 100644 (file)
@@ -387,7 +387,8 @@ static void init_intel(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_PEBS);
        }
 
-       if (c->x86 == 6 && c->x86_model == 29 && cpu_has_clflush)
+       if (c->x86 == 6 && cpu_has_clflush &&
+           (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
                set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
 
 #ifdef CONFIG_X86_64
index fd00bb29425d4da50194241c6ae3835775e12e6e..c1a861829d817a2749372060df21c6d689294fff 100644 (file)
@@ -262,11 +262,20 @@ struct cpu_hw_events {
        __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
 
-#define EVENT_CONSTRAINT_END           \
-       EVENT_CONSTRAINT(0, 0, 0)
+/*
+ * We define the end marker as having a weight of -1
+ * to enable blacklisting of events using a counter bitmask
+ * of zero and thus a weight of zero.
+ * The end marker has a weight that cannot possibly be
+ * obtained from counting the bits in the bitmask.
+ */
+#define EVENT_CONSTRAINT_END { .weight = -1 }
 
+/*
+ * Check for end marker with weight == -1
+ */
 #define for_each_event_constraint(e, c)        \
-       for ((e) = (c); (e)->weight; (e)++)
+       for ((e) = (c); (e)->weight != -1; (e)++)
 
 /*
  * Extra registers for specific events.
index da3c599584a3307f024c76f80c94e721016765e3..c752cb43e52f192f431a5f2ab91b9366e42ef5b0 100644 (file)
@@ -558,6 +558,17 @@ void native_machine_shutdown(void)
 {
        /* Stop the cpus and apics */
 #ifdef CONFIG_X86_IO_APIC
+       /*
+        * Disabling IO APIC before local APIC is a workaround for
+        * erratum AVR31 in "Intel Atom Processor C2000 Product Family
+        * Specification Update". In this situation, interrupts that target
+        * a Logical Processor whose Local APIC is either in the process of
+        * being hardware disabled or software disabled are neither delivered
+        * nor discarded. When this erratum occurs, the processor may hang.
+        *
+        * Even without the erratum, it still makes sense to quiet IO APIC
+        * before disabling Local APIC.
+        */
        disable_IO_APIC();
 #endif
 
index 5439117d5c4cccfa00d28dd64fb5aa8fd488261e..dec48bfaddb8ff79ee7f7734cebfca7f36844461 100644 (file)
@@ -143,6 +143,8 @@ static inline int kvm_apic_id(struct kvm_lapic *apic)
        return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
 }
 
+#define KVM_X2APIC_CID_BITS 0
+
 static void recalculate_apic_map(struct kvm *kvm)
 {
        struct kvm_apic_map *new, *old = NULL;
@@ -180,7 +182,8 @@ static void recalculate_apic_map(struct kvm *kvm)
                if (apic_x2apic_mode(apic)) {
                        new->ldr_bits = 32;
                        new->cid_shift = 16;
-                       new->cid_mask = new->lid_mask = 0xffff;
+                       new->cid_mask = (1 << KVM_X2APIC_CID_BITS) - 1;
+                       new->lid_mask = 0xffff;
                } else if (kvm_apic_sw_enabled(apic) &&
                                !new->cid_mask /* flat mode */ &&
                                kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {
@@ -841,7 +844,8 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
        ASSERT(apic != NULL);
 
        /* if initial count is 0, current count should also be 0 */
-       if (kvm_apic_get_reg(apic, APIC_TMICT) == 0)
+       if (kvm_apic_get_reg(apic, APIC_TMICT) == 0 ||
+               apic->lapic_timer.period == 0)
                return 0;
 
        remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
@@ -1691,7 +1695,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
 {
        u32 data;
-       void *vapic;
 
        if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention))
                apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic);
@@ -1699,9 +1702,8 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
        if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
                return;
 
-       vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
-       data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
-       kunmap_atomic(vapic);
+       kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+                               sizeof(u32));
 
        apic_set_tpr(vcpu->arch.apic, data & 0xff);
 }
@@ -1737,7 +1739,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
        u32 data, tpr;
        int max_irr, max_isr;
        struct kvm_lapic *apic = vcpu->arch.apic;
-       void *vapic;
 
        apic_sync_pv_eoi_to_guest(vcpu, apic);
 
@@ -1753,18 +1754,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
                max_isr = 0;
        data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
 
-       vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
-       *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
-       kunmap_atomic(vapic);
+       kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+                               sizeof(u32));
 }
 
-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
 {
-       vcpu->arch.apic->vapic_addr = vapic_addr;
-       if (vapic_addr)
+       if (vapic_addr) {
+               if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+                                       &vcpu->arch.apic->vapic_cache,
+                                       vapic_addr, sizeof(u32)))
+                       return -EINVAL;
                __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
-       else
+       } else {
                __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
+       }
+
+       vcpu->arch.apic->vapic_addr = vapic_addr;
+       return 0;
 }
 
 int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
index c730ac9fe80188d15957bf9b556918036db892ab..c8b0d0d2da5ce2d67f9342fba000e60e1aec84eb 100644 (file)
@@ -34,7 +34,7 @@ struct kvm_lapic {
         */
        void *regs;
        gpa_t vapic_addr;
-       struct page *vapic_page;
+       struct gfn_to_hva_cache vapic_cache;
        unsigned long pending_events;
        unsigned int sipi_vector;
 };
@@ -76,7 +76,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
 void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset);
 void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector);
 
-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
 
index 21ef1ba184ae8500a70061f566ea55fde76cbfd2..5d004da1e35da9bdad0260f5d6b0f287330b194c 100644 (file)
@@ -3214,8 +3214,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&va, argp, sizeof va))
                        goto out;
-               r = 0;
-               kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
+               r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
                break;
        }
        case KVM_X86_SETUP_MCE: {
@@ -5739,36 +5738,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
                        !kvm_event_needs_reinjection(vcpu);
 }
 
-static int vapic_enter(struct kvm_vcpu *vcpu)
-{
-       struct kvm_lapic *apic = vcpu->arch.apic;
-       struct page *page;
-
-       if (!apic || !apic->vapic_addr)
-               return 0;
-
-       page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-       if (is_error_page(page))
-               return -EFAULT;
-
-       vcpu->arch.apic->vapic_page = page;
-       return 0;
-}
-
-static void vapic_exit(struct kvm_vcpu *vcpu)
-{
-       struct kvm_lapic *apic = vcpu->arch.apic;
-       int idx;
-
-       if (!apic || !apic->vapic_addr)
-               return;
-
-       idx = srcu_read_lock(&vcpu->kvm->srcu);
-       kvm_release_page_dirty(apic->vapic_page);
-       mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-       srcu_read_unlock(&vcpu->kvm->srcu, idx);
-}
-
 static void update_cr8_intercept(struct kvm_vcpu *vcpu)
 {
        int max_irr, tpr;
@@ -6069,11 +6038,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
        struct kvm *kvm = vcpu->kvm;
 
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-       r = vapic_enter(vcpu);
-       if (r) {
-               srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
-               return r;
-       }
 
        r = 1;
        while (r > 0) {
@@ -6132,8 +6096,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 
        srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 
-       vapic_exit(vcpu);
-
        return r;
 }
 
index dd74e46828c0fc243740b61a18c2dea654fafb5e..0596e8e0cc1992b1fc32a00277a4f879cd07a8f3 100644 (file)
@@ -83,6 +83,12 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                pte_t pte = gup_get_pte(ptep);
                struct page *page;
 
+               /* Similar to the PMD case, NUMA hinting must take slow path */
+               if (pte_numa(pte)) {
+                       pte_unmap(ptep);
+                       return 0;
+               }
+
                if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
                        pte_unmap(ptep);
                        return 0;
@@ -167,6 +173,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
                if (unlikely(pmd_large(pmd))) {
+                       /*
+                        * NUMA hinting faults need to be handled in the GUP
+                        * slowpath for accounting purposes and so that they
+                        * can be serialised against THP migration.
+                        */
+                       if (pmd_numa(pmd))
+                               return 0;
                        if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
                                return 0;
                } else {
index 6599a0027b76bb9ab3b390fe31e5ba0ae10ed124..81b506d5befd46e5a494d6cbef7aa71edceca7f1 100644 (file)
@@ -142,7 +142,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
                        efi_y += font->height;
                }
 
-               if (efi_y + font->height >= si->lfb_height) {
+               if (efi_y + font->height > si->lfb_height) {
                        u32 i;
 
                        efi_y -= font->height;
index 92c02344a060f2dacc7997185d6fd6bc04ed225e..cceb813044efc5dfdcbaf9fddbd076b23b2d1dc1 100644 (file)
@@ -690,13 +690,6 @@ void __init efi_init(void)
 
        set_bit(EFI_MEMMAP, &x86_efi_facility);
 
-#ifdef CONFIG_X86_32
-       if (efi_is_native()) {
-               x86_platform.get_wallclock = efi_get_time;
-               x86_platform.set_wallclock = efi_set_rtc_mmss;
-       }
-#endif
-
 #if EFI_DEBUG
        print_efi_memmap();
 #endif
index 0f92173a12b6ee1a1d5512c867585cd1ee07fc12..efe4d7220397ea81e13c88524f9234d0673b19cd 100644 (file)
@@ -1070,12 +1070,13 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        unsigned long status;
 
        bcp = &per_cpu(bau_control, cpu);
-       stat = bcp->statp;
-       stat->s_enters++;
 
        if (bcp->nobau)
                return cpumask;
 
+       stat = bcp->statp;
+       stat->s_enters++;
+
        if (bcp->busy) {
                descriptor_status =
                        read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_0);
index 88692871823f9910aeb071ad44a86d8c5c251411..9cac82588cbc49d86bc9457586941c69763d7749 100644 (file)
@@ -73,9 +73,10 @@ KBUILD_CFLAGS        := $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \
                   -march=i386 -mregparm=3 \
                   -include $(srctree)/$(src)/../../boot/code16gcc.h \
                   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
+                  -mno-mmx -mno-sse \
                   $(call cc-option, -ffreestanding) \
                   $(call cc-option, -fno-toplevel-reorder,\
-                       $(call cc-option, -fno-unit-at-a-time)) \
+                  $(call cc-option, -fno-unit-at-a-time)) \
                   $(call cc-option, -fno-stack-protector) \
                   $(call cc-option, -mpreferred-stack-boundary=2)
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
index 1610b22edf0992da4cdeb1657688527d5867e76c..86154eab95239fdd6300ddc665f03650b80f1a5b 100644 (file)
@@ -435,9 +435,9 @@ static inline uint64_t blkg_stat_read(struct blkg_stat *stat)
        uint64_t v;
 
        do {
-               start = u64_stats_fetch_begin(&stat->syncp);
+               start = u64_stats_fetch_begin_bh(&stat->syncp);
                v = stat->cnt;
-       } while (u64_stats_fetch_retry(&stat->syncp, start));
+       } while (u64_stats_fetch_retry_bh(&stat->syncp, start));
 
        return v;
 }
@@ -508,9 +508,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
        struct blkg_rwstat tmp;
 
        do {
-               start = u64_stats_fetch_begin(&rwstat->syncp);
+               start = u64_stats_fetch_begin_bh(&rwstat->syncp);
                tmp = *rwstat;
-       } while (u64_stats_fetch_retry(&rwstat->syncp, start));
+       } while (u64_stats_fetch_retry_bh(&rwstat->syncp, start));
 
        return tmp;
 }
index 331e627301eaacbced43537469cb9f9914b6747c..fb6f3c0ffa494f4f2adcce6fc35c95ecf383c9a8 100644 (file)
@@ -502,15 +502,6 @@ void blk_abort_flushes(struct request_queue *q)
        }
 }
 
-static void bio_end_flush(struct bio *bio, int err)
-{
-       if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       if (bio->bi_private)
-               complete(bio->bi_private);
-       bio_put(bio);
-}
-
 /**
  * blkdev_issue_flush - queue a flush
  * @bdev:      blockdev to issue flush for
@@ -526,7 +517,6 @@ static void bio_end_flush(struct bio *bio, int err)
 int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                sector_t *error_sector)
 {
-       DECLARE_COMPLETION_ONSTACK(wait);
        struct request_queue *q;
        struct bio *bio;
        int ret = 0;
@@ -548,13 +538,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                return -ENXIO;
 
        bio = bio_alloc(gfp_mask, 0);
-       bio->bi_end_io = bio_end_flush;
        bio->bi_bdev = bdev;
-       bio->bi_private = &wait;
 
-       bio_get(bio);
-       submit_bio(WRITE_FLUSH, bio);
-       wait_for_completion_io(&wait);
+       ret = submit_bio_wait(WRITE_FLUSH, bio);
 
        /*
         * The driver must store the error location in ->bi_sector, if
@@ -564,9 +550,6 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
        if (error_sector)
                *error_sector = bio->bi_sector;
 
-       if (!bio_flagged(bio, BIO_UPTODATE))
-               ret = -EIO;
-
        bio_put(bio);
        return ret;
 }
index ba6cf8e9aa0a598a50d4b24eb2c8f2914bf5c5ef..b91ce75bd35db9e00edb4c4af0a0e3036fd66df8 100644 (file)
@@ -335,9 +335,22 @@ static struct kobj_type blk_mq_hw_ktype = {
 void blk_mq_unregister_disk(struct gendisk *disk)
 {
        struct request_queue *q = disk->queue;
+       struct blk_mq_hw_ctx *hctx;
+       struct blk_mq_ctx *ctx;
+       int i, j;
+
+       queue_for_each_hw_ctx(q, hctx, i) {
+               hctx_for_each_ctx(hctx, ctx, j) {
+                       kobject_del(&ctx->kobj);
+                       kobject_put(&ctx->kobj);
+               }
+               kobject_del(&hctx->kobj);
+               kobject_put(&hctx->kobj);
+       }
 
        kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
        kobject_del(&q->mq_kobj);
+       kobject_put(&q->mq_kobj);
 
        kobject_put(&disk_to_dev(disk)->kobj);
 }
index cdc629cf075b74f27f7801565ec3d90f3e299ce0..c79126e110308e8b1ea4b322506a425ceeb3085c 100644 (file)
@@ -202,10 +202,12 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
                if (rq) {
                        blk_mq_rq_ctx_init(q, ctx, rq, rw);
                        break;
-               } else if (!(gfp & __GFP_WAIT))
-                       break;
+               }
 
                blk_mq_put_ctx(ctx);
+               if (!(gfp & __GFP_WAIT))
+                       break;
+
                __blk_mq_run_hw_queue(hctx);
                blk_mq_wait_for_tags(hctx->tags);
        } while (1);
@@ -222,7 +224,8 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
                return NULL;
 
        rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved);
-       blk_mq_put_ctx(rq->mq_ctx);
+       if (rq)
+               blk_mq_put_ctx(rq->mq_ctx);
        return rq;
 }
 
@@ -235,7 +238,8 @@ struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw,
                return NULL;
 
        rq = blk_mq_alloc_request_pinned(q, rw, gfp, true);
-       blk_mq_put_ctx(rq->mq_ctx);
+       if (rq)
+               blk_mq_put_ctx(rq->mq_ctx);
        return rq;
 }
 EXPORT_SYMBOL(blk_mq_alloc_reserved_request);
@@ -308,12 +312,12 @@ void blk_mq_complete_request(struct request *rq, int error)
 
        blk_account_io_completion(rq, bytes);
 
+       blk_account_io_done(rq);
+
        if (rq->end_io)
                rq->end_io(rq, error);
        else
                blk_mq_free_request(rq);
-
-       blk_account_io_done(rq);
 }
 
 void __blk_mq_end_io(struct request *rq, int error)
index 4ae5734fb4733bb8e264565867fa6d73d7b11f6b..7bcb70d216e14b1b811e8924bb15cbf01f5acf80 100644 (file)
@@ -174,9 +174,8 @@ config CRYPTO_TEST
        help
          Quick & dirty crypto test module.
 
-config CRYPTO_ABLK_HELPER_X86
+config CRYPTO_ABLK_HELPER
        tristate
-       depends on X86
        select CRYPTO_CRYPTD
 
 config CRYPTO_GLUE_HELPER_X86
@@ -695,7 +694,7 @@ config CRYPTO_AES_NI_INTEL
        select CRYPTO_AES_X86_64 if 64BIT
        select CRYPTO_AES_586 if !64BIT
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_ALGAPI
        select CRYPTO_GLUE_HELPER_X86 if 64BIT
        select CRYPTO_LRW
@@ -895,7 +894,7 @@ config CRYPTO_CAMELLIA_AESNI_AVX_X86_64
        depends on CRYPTO
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_CAMELLIA_X86_64
        select CRYPTO_LRW
@@ -917,7 +916,7 @@ config CRYPTO_CAMELLIA_AESNI_AVX2_X86_64
        depends on CRYPTO
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_CAMELLIA_X86_64
        select CRYPTO_CAMELLIA_AESNI_AVX_X86_64
@@ -969,7 +968,7 @@ config CRYPTO_CAST5_AVX_X86_64
        depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_CAST_COMMON
        select CRYPTO_CAST5
        help
@@ -992,7 +991,7 @@ config CRYPTO_CAST6_AVX_X86_64
        depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_CAST_COMMON
        select CRYPTO_CAST6
@@ -1110,7 +1109,7 @@ config CRYPTO_SERPENT_SSE2_X86_64
        depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_SERPENT
        select CRYPTO_LRW
@@ -1132,7 +1131,7 @@ config CRYPTO_SERPENT_SSE2_586
        depends on X86 && !64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_SERPENT
        select CRYPTO_LRW
@@ -1154,7 +1153,7 @@ config CRYPTO_SERPENT_AVX_X86_64
        depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_SERPENT
        select CRYPTO_LRW
@@ -1176,7 +1175,7 @@ config CRYPTO_SERPENT_AVX2_X86_64
        depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_SERPENT
        select CRYPTO_SERPENT_AVX_X86_64
@@ -1292,7 +1291,7 @@ config CRYPTO_TWOFISH_AVX_X86_64
        depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_CRYPTD
-       select CRYPTO_ABLK_HELPER_X86
+       select CRYPTO_ABLK_HELPER
        select CRYPTO_GLUE_HELPER_X86
        select CRYPTO_TWOFISH_COMMON
        select CRYPTO_TWOFISH_X86_64
index b3a7e807e08bca306619a3e7250afbc9160fecbe..989c510da8cc98af911976874d6c16db865ee1b3 100644 (file)
@@ -2,8 +2,13 @@
 # Cryptographic API
 #
 
+# memneq MUST be built with -Os or -O0 to prevent early-return optimizations
+# that will defeat memneq's actual purpose to prevent timing attacks.
+CFLAGS_REMOVE_memneq.o := -O1 -O2 -O3
+CFLAGS_memneq.o := -Os
+
 obj-$(CONFIG_CRYPTO) += crypto.o
-crypto-y := api.o cipher.o compress.o
+crypto-y := api.o cipher.o compress.o memneq.o
 
 obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o
 
@@ -105,3 +110,4 @@ obj-$(CONFIG_XOR_BLOCKS) += xor.o
 obj-$(CONFIG_ASYNC_CORE) += async_tx/
 obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
 obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
+obj-$(CONFIG_CRYPTO_ABLK_HELPER) += ablk_helper.o
similarity index 95%
rename from arch/x86/crypto/ablk_helper.c
rename to crypto/ablk_helper.c
index 43282fe04a8b726e57048d8e67fd96d209c76041..ffe7278d4bd83bd9b8ee5e7392af7bd417e037ae 100644 (file)
 #include <linux/crypto.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 #include <crypto/algapi.h>
 #include <crypto/cryptd.h>
-#include <asm/i387.h>
-#include <asm/crypto/ablk_helper.h>
+#include <crypto/ablk_helper.h>
+#include <asm/simd.h>
 
 int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
                 unsigned int key_len)
@@ -70,11 +71,11 @@ int ablk_encrypt(struct ablkcipher_request *req)
        struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
        struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
 
-       if (!irq_fpu_usable()) {
+       if (!may_use_simd()) {
                struct ablkcipher_request *cryptd_req =
                        ablkcipher_request_ctx(req);
 
-               memcpy(cryptd_req, req, sizeof(*req));
+               *cryptd_req = *req;
                ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
 
                return crypto_ablkcipher_encrypt(cryptd_req);
@@ -89,11 +90,11 @@ int ablk_decrypt(struct ablkcipher_request *req)
        struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
        struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
 
-       if (!irq_fpu_usable()) {
+       if (!may_use_simd()) {
                struct ablkcipher_request *cryptd_req =
                        ablkcipher_request_ctx(req);
 
-               memcpy(cryptd_req, req, sizeof(*req));
+               *cryptd_req = *req;
                ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
 
                return crypto_ablkcipher_decrypt(cryptd_req);
index 7d4a8d28277e181386981dcef2d73ec377aefe9a..40886c489903b72a50c1b718869c38744d142aa4 100644 (file)
@@ -16,9 +16,7 @@
 #include <crypto/internal/skcipher.h>
 #include <linux/cpumask.h>
 #include <linux/err.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/rtnetlink.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -30,8 +28,6 @@
 
 #include "internal.h"
 
-static const char *skcipher_default_geniv __read_mostly;
-
 struct ablkcipher_buffer {
        struct list_head        entry;
        struct scatter_walk     dst;
@@ -527,8 +523,7 @@ const char *crypto_default_geniv(const struct crypto_alg *alg)
            alg->cra_blocksize)
                return "chainiv";
 
-       return alg->cra_flags & CRYPTO_ALG_ASYNC ?
-              "eseqiv" : skcipher_default_geniv;
+       return "eseqiv";
 }
 
 static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
@@ -709,17 +704,3 @@ err:
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
-
-static int __init skcipher_module_init(void)
-{
-       skcipher_default_geniv = num_possible_cpus() > 1 ?
-                                "eseqiv" : "chainiv";
-       return 0;
-}
-
-static void skcipher_module_exit(void)
-{
-}
-
-module_init(skcipher_module_init);
-module_exit(skcipher_module_exit);
index ef5356cd280a54c086e4f8ff964245e38748a391..850246206b1258a697f83e86c39acc9b0a17f973 100644 (file)
@@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
        struct hash_ctx *ctx = ask->private;
        int err;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        lock_sock(sk);
        sg_init_table(ctx->sgl.sg, 1);
        sg_set_page(ctx->sgl.sg, page, size, offset);
index 6a6dfc062d2a47f04449fbb0e1c3f3852be337dc..a19c027b29bde504ac8eae4b4572947a69ed2335 100644 (file)
@@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
        struct skcipher_sg_list *sgl;
        int err = -EINVAL;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        lock_sock(sk);
        if (!ctx->more && ctx->used)
                goto unlock;
index c0bb3778f1ae06976fbaf07c7e1b075fc0c581e7..666f1962a160f5d547579b918b6229de0232607b 100644 (file)
@@ -230,11 +230,11 @@ remainder:
         */
        if (byte_count < DEFAULT_BLK_SZ) {
 empty_rbuf:
-               for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
-                       ctx->rand_data_valid++) {
+               while (ctx->rand_data_valid < DEFAULT_BLK_SZ) {
                        *ptr = ctx->rand_data[ctx->rand_data_valid];
                        ptr++;
                        byte_count--;
+                       ctx->rand_data_valid++;
                        if (byte_count == 0)
                                goto done;
                }
index 90a17f59ba2800d197366dbcb0835a9adc598320..459cf97a75e2e223798e2cd157a60bf048f01117 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <crypto/algapi.h>
 #include "public_key.h"
 
 MODULE_LICENSE("GPL");
@@ -189,12 +190,12 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
                }
        }
 
-       if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) {
+       if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
                kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
                return -EBADMSG;
        }
 
-       if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) {
+       if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
                kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
                return -EKEYREJECTED;
        }
index f83300b6e8c13033e5e239be8d48e7fb379668de..382ef0d2ff2e5e030c0068d1076155364d48f43d 100644 (file)
 #include <linux/asn1_decoder.h>
 #include <keys/asymmetric-subtype.h>
 #include <keys/asymmetric-parser.h>
-#include <keys/system_keyring.h>
 #include <crypto/hash.h>
 #include "asymmetric_keys.h"
 #include "public_key.h"
 #include "x509_parser.h"
 
-/*
- * Find a key in the given keyring by issuer and authority.
- */
-static struct key *x509_request_asymmetric_key(
-       struct key *keyring,
-       const char *signer, size_t signer_len,
-       const char *authority, size_t auth_len)
-{
-       key_ref_t key;
-       char *id;
-
-       /* Construct an identifier. */
-       id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
-       if (!id)
-               return ERR_PTR(-ENOMEM);
-
-       memcpy(id, signer, signer_len);
-       id[signer_len + 0] = ':';
-       id[signer_len + 1] = ' ';
-       memcpy(id + signer_len + 2, authority, auth_len);
-       id[signer_len + 2 + auth_len] = 0;
-
-       pr_debug("Look up: \"%s\"\n", id);
-
-       key = keyring_search(make_key_ref(keyring, 1),
-                            &key_type_asymmetric, id);
-       if (IS_ERR(key))
-               pr_debug("Request for module key '%s' err %ld\n",
-                        id, PTR_ERR(key));
-       kfree(id);
-
-       if (IS_ERR(key)) {
-               switch (PTR_ERR(key)) {
-                       /* Hide some search errors */
-               case -EACCES:
-               case -ENOTDIR:
-               case -EAGAIN:
-                       return ERR_PTR(-ENOKEY);
-               default:
-                       return ERR_CAST(key);
-               }
-       }
-
-       pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
-       return key_ref_to_ptr(key);
-}
-
 /*
  * Set up the signature parameters in an X.509 certificate.  This involves
  * digesting the signed data and extracting the signature.
@@ -150,33 +102,6 @@ int x509_check_signature(const struct public_key *pub,
 }
 EXPORT_SYMBOL_GPL(x509_check_signature);
 
-/*
- * Check the new certificate against the ones in the trust keyring.  If one of
- * those is the signing key and validates the new certificate, then mark the
- * new certificate as being trusted.
- *
- * Return 0 if the new certificate was successfully validated, 1 if we couldn't
- * find a matching parent certificate in the trusted list and an error if there
- * is a matching certificate but the signature check fails.
- */
-static int x509_validate_trust(struct x509_certificate *cert,
-                              struct key *trust_keyring)
-{
-       const struct public_key *pk;
-       struct key *key;
-       int ret = 1;
-
-       key = x509_request_asymmetric_key(trust_keyring,
-                                         cert->issuer, strlen(cert->issuer),
-                                         cert->authority,
-                                         strlen(cert->authority));
-       if (!IS_ERR(key))  {
-               pk = key->payload.data;
-               ret = x509_check_signature(pk, cert);
-       }
-       return ret;
-}
-
 /*
  * Attempt to parse a data blob for a key as an X509 certificate.
  */
@@ -230,13 +155,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
        /* Check the signature on the key if it appears to be self-signed */
        if (!cert->authority ||
            strcmp(cert->fingerprint, cert->authority) == 0) {
-               ret = x509_check_signature(cert->pub, cert); /* self-signed */
+               ret = x509_check_signature(cert->pub, cert);
                if (ret < 0)
                        goto error_free_cert;
-       } else {
-               ret = x509_validate_trust(cert, system_trusted_keyring);
-               if (!ret)
-                       prep->trusted = 1;
        }
 
        /* Propose a description */
index ffce19de05cf958853dc0e13f7e3cf1efa30cd4f..e1223559d5dfd233cbc15184c9dc607fb34fae2e 100644 (file)
@@ -52,40 +52,52 @@ static void authenc_request_complete(struct aead_request *req, int err)
                aead_request_complete(req, err);
 }
 
-static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
-                                unsigned int keylen)
+int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
+                              unsigned int keylen)
 {
-       unsigned int authkeylen;
-       unsigned int enckeylen;
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct crypto_ahash *auth = ctx->auth;
-       struct crypto_ablkcipher *enc = ctx->enc;
-       struct rtattr *rta = (void *)key;
+       struct rtattr *rta = (struct rtattr *)key;
        struct crypto_authenc_key_param *param;
-       int err = -EINVAL;
 
        if (!RTA_OK(rta, keylen))
-               goto badkey;
+               return -EINVAL;
        if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
+               return -EINVAL;
        if (RTA_PAYLOAD(rta) < sizeof(*param))
-               goto badkey;
+               return -EINVAL;
 
        param = RTA_DATA(rta);
-       enckeylen = be32_to_cpu(param->enckeylen);
+       keys->enckeylen = be32_to_cpu(param->enckeylen);
 
        key += RTA_ALIGN(rta->rta_len);
        keylen -= RTA_ALIGN(rta->rta_len);
 
-       if (keylen < enckeylen)
-               goto badkey;
+       if (keylen < keys->enckeylen)
+               return -EINVAL;
 
-       authkeylen = keylen - enckeylen;
+       keys->authkeylen = keylen - keys->enckeylen;
+       keys->authkey = key;
+       keys->enckey = key + keys->authkeylen;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_authenc_extractkeys);
+
+static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
+                                unsigned int keylen)
+{
+       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct crypto_ahash *auth = ctx->auth;
+       struct crypto_ablkcipher *enc = ctx->enc;
+       struct crypto_authenc_keys keys;
+       int err = -EINVAL;
+
+       if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
+               goto badkey;
 
        crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
        crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) &
                                    CRYPTO_TFM_REQ_MASK);
-       err = crypto_ahash_setkey(auth, keyauthkeylen);
+       err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen);
        crypto_aead_set_flags(authenc, crypto_ahash_get_flags(auth) &
                                       CRYPTO_TFM_RES_MASK);
 
@@ -95,7 +107,7 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
        crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
        crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) &
                                         CRYPTO_TFM_REQ_MASK);
-       err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
+       err = crypto_ablkcipher_setkey(enc, keys.enckey, keys.enckeylen);
        crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) &
                                       CRYPTO_TFM_RES_MASK);
 
@@ -188,7 +200,7 @@ static void authenc_verify_ahash_update_done(struct crypto_async_request *areq,
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
 
-       err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
        if (err)
                goto out;
 
@@ -227,7 +239,7 @@ static void authenc_verify_ahash_done(struct crypto_async_request *areq,
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
 
-       err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
        if (err)
                goto out;
 
@@ -368,9 +380,10 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
        if (!err) {
                struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
                struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-               struct ablkcipher_request *abreq = aead_request_ctx(areq);
-               u8 *iv = (u8 *)(abreq + 1) +
-                        crypto_ablkcipher_reqsize(ctx->enc);
+               struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq);
+               struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+                                                           + ctx->reqoff);
+               u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc);
 
                err = crypto_authenc_genicv(areq, iv, 0);
        }
@@ -462,7 +475,7 @@ static int crypto_authenc_verify(struct aead_request *req,
        ihash = ohash + authsize;
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
-       return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
+       return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
 }
 
 static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
index ab53762fc309c5db55ccaab948f1862bcc7a237a..4be0dd4373a9a2e8a15b62adbf8dbdd6e374eacd 100644 (file)
@@ -59,37 +59,19 @@ static void authenc_esn_request_complete(struct aead_request *req, int err)
 static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
                                     unsigned int keylen)
 {
-       unsigned int authkeylen;
-       unsigned int enckeylen;
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
        struct crypto_ahash *auth = ctx->auth;
        struct crypto_ablkcipher *enc = ctx->enc;
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
+       struct crypto_authenc_keys keys;
        int err = -EINVAL;
 
-       if (!RTA_OK(rta, keylen))
+       if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
                goto badkey;
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
-               goto badkey;
-
-       param = RTA_DATA(rta);
-       enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
-
-       if (keylen < enckeylen)
-               goto badkey;
-
-       authkeylen = keylen - enckeylen;
 
        crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
        crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
                                     CRYPTO_TFM_REQ_MASK);
-       err = crypto_ahash_setkey(auth, keyauthkeylen);
+       err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen);
        crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
                                           CRYPTO_TFM_RES_MASK);
 
@@ -99,7 +81,7 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *
        crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
        crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
                                         CRYPTO_TFM_REQ_MASK);
-       err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
+       err = crypto_ablkcipher_setkey(enc, keys.enckey, keys.enckeylen);
        crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
                                           CRYPTO_TFM_RES_MASK);
 
@@ -247,7 +229,7 @@ static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *ar
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
 
-       err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
        if (err)
                goto out;
 
@@ -296,7 +278,7 @@ static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *a
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
 
-       err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
        if (err)
                goto out;
 
@@ -336,7 +318,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
 
-       err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
        if (err)
                goto out;
 
@@ -568,7 +550,7 @@ static int crypto_authenc_esn_verify(struct aead_request *req)
        ihash = ohash + authsize;
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
-       return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
+       return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
 }
 
 static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
index 499c91717d937bfaba9364a5bcde94988626195c..1df84217f7c9320dbfc5174f91ce394667c36447 100644 (file)
@@ -271,7 +271,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
        }
 
        /* compute plaintext into mac */
-       get_data_to_compute(cipher, pctx, plain, cryptlen);
+       if (cryptlen)
+               get_data_to_compute(cipher, pctx, plain, cryptlen);
 
 out:
        return err;
@@ -363,7 +364,7 @@ static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
 
        if (!err) {
                err = crypto_ccm_auth(req, req->dst, cryptlen);
-               if (!err && memcmp(pctx->auth_tag, pctx->odata, authsize))
+               if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
                        err = -EBADMSG;
        }
        aead_request_complete(req, err);
@@ -422,7 +423,7 @@ static int crypto_ccm_decrypt(struct aead_request *req)
                return err;
 
        /* verify */
-       if (memcmp(authtag, odata, authsize))
+       if (crypto_memneq(authtag, odata, authsize))
                return -EBADMSG;
 
        return err;
index 43e1fb05ea54878cbe136231a1a92c847b6d3119..b4f01793900409a0398faeb958b74416a5d1637d 100644 (file)
@@ -582,7 +582,7 @@ static int crypto_gcm_verify(struct aead_request *req,
 
        crypto_xor(auth_tag, iauth_tag, 16);
        scatterwalk_map_and_copy(iauth_tag, req->src, cryptlen, authsize, 0);
-       return memcmp(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
+       return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
 }
 
 static void gcm_decrypt_done(struct crypto_async_request *areq, int err)
diff --git a/crypto/memneq.c b/crypto/memneq.c
new file mode 100644 (file)
index 0000000..cd01622
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Constant-time equality testing of memory regions.
+ *
+ * Authors:
+ *
+ *   James Yonan <james@openvpn.net>
+ *   Daniel Borkmann <dborkman@redhat.com>
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 OpenVPN Technologies, Inc. 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 OpenVPN Technologies, Inc. All rights reserved.
+ *
+ * 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 OpenVPN Technologies nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <crypto/algapi.h>
+
+#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ
+
+/* Generic path for arbitrary size */
+static inline unsigned long
+__crypto_memneq_generic(const void *a, const void *b, size_t size)
+{
+       unsigned long neq = 0;
+
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       while (size >= sizeof(unsigned long)) {
+               neq |= *(unsigned long *)a ^ *(unsigned long *)b;
+               a += sizeof(unsigned long);
+               b += sizeof(unsigned long);
+               size -= sizeof(unsigned long);
+       }
+#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+       while (size > 0) {
+               neq |= *(unsigned char *)a ^ *(unsigned char *)b;
+               a += 1;
+               b += 1;
+               size -= 1;
+       }
+       return neq;
+}
+
+/* Loop-free fast-path for frequently used 16-byte size */
+static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
+{
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       if (sizeof(unsigned long) == 8)
+               return ((*(unsigned long *)(a)   ^ *(unsigned long *)(b))
+                     | (*(unsigned long *)(a+8) ^ *(unsigned long *)(b+8)));
+       else if (sizeof(unsigned int) == 4)
+               return ((*(unsigned int *)(a)    ^ *(unsigned int *)(b))
+                      | (*(unsigned int *)(a+4)  ^ *(unsigned int *)(b+4))
+                     | (*(unsigned int *)(a+8)  ^ *(unsigned int *)(b+8))
+                     | (*(unsigned int *)(a+12) ^ *(unsigned int *)(b+12)));
+       else
+#endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
+               return ((*(unsigned char *)(a)    ^ *(unsigned char *)(b))
+                     | (*(unsigned char *)(a+1)  ^ *(unsigned char *)(b+1))
+                     | (*(unsigned char *)(a+2)  ^ *(unsigned char *)(b+2))
+                     | (*(unsigned char *)(a+3)  ^ *(unsigned char *)(b+3))
+                     | (*(unsigned char *)(a+4)  ^ *(unsigned char *)(b+4))
+                     | (*(unsigned char *)(a+5)  ^ *(unsigned char *)(b+5))
+                     | (*(unsigned char *)(a+6)  ^ *(unsigned char *)(b+6))
+                     | (*(unsigned char *)(a+7)  ^ *(unsigned char *)(b+7))
+                     | (*(unsigned char *)(a+8)  ^ *(unsigned char *)(b+8))
+                     | (*(unsigned char *)(a+9)  ^ *(unsigned char *)(b+9))
+                     | (*(unsigned char *)(a+10) ^ *(unsigned char *)(b+10))
+                     | (*(unsigned char *)(a+11) ^ *(unsigned char *)(b+11))
+                     | (*(unsigned char *)(a+12) ^ *(unsigned char *)(b+12))
+                     | (*(unsigned char *)(a+13) ^ *(unsigned char *)(b+13))
+                     | (*(unsigned char *)(a+14) ^ *(unsigned char *)(b+14))
+                     | (*(unsigned char *)(a+15) ^ *(unsigned char *)(b+15)));
+}
+
+/* Compare two areas of memory without leaking timing information,
+ * and with special optimizations for common sizes.  Users should
+ * not call this function directly, but should instead use
+ * crypto_memneq defined in crypto/algapi.h.
+ */
+noinline unsigned long __crypto_memneq(const void *a, const void *b,
+                                      size_t size)
+{
+       switch (size) {
+       case 16:
+               return __crypto_memneq_16(a, b);
+       default:
+               return __crypto_memneq_generic(a, b, size);
+       }
+}
+EXPORT_SYMBOL(__crypto_memneq);
+
+#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */
index 1ab8258fcf560735237a198b2037c102e229d20b..001f07cdb828d59101521162109b9f101c34a319 100644 (file)
@@ -1242,6 +1242,10 @@ static int do_test(int m)
                ret += tcrypt_test("cmac(des3_ede)");
                break;
 
+       case 155:
+               ret += tcrypt_test("authenc(hmac(sha1),cbc(aes))");
+               break;
+
        case 200:
                test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
                                speed_template_16_24_32);
index 432afc03e7c3f9c1040ac54033950eb9e17c0727..77955507f6f1f73a044554a7d738074c98f9829e 100644 (file)
@@ -503,16 +503,16 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                goto out;
                        }
 
-                       sg_init_one(&sg[0], input,
-                                   template[i].ilen + (enc ? authsize : 0));
-
                        if (diff_dst) {
                                output = xoutbuf[0];
                                output += align_offset;
+                               sg_init_one(&sg[0], input, template[i].ilen);
                                sg_init_one(&sgout[0], output,
+                                           template[i].rlen);
+                       } else {
+                               sg_init_one(&sg[0], input,
                                            template[i].ilen +
                                                (enc ? authsize : 0));
-                       } else {
                                output = input;
                        }
 
@@ -612,12 +612,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                memcpy(q, template[i].input + temp,
                                       template[i].tap[k]);
 
-                               n = template[i].tap[k];
-                               if (k == template[i].np - 1 && enc)
-                                       n += authsize;
-                               if (offset_in_page(q) + n < PAGE_SIZE)
-                                       q[n] = 0;
-
                                sg_set_buf(&sg[k], q, template[i].tap[k]);
 
                                if (diff_dst) {
@@ -625,13 +619,17 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                            offset_in_page(IDX[k]);
 
                                        memset(q, 0, template[i].tap[k]);
-                                       if (offset_in_page(q) + n < PAGE_SIZE)
-                                               q[n] = 0;
 
                                        sg_set_buf(&sgout[k], q,
                                                   template[i].tap[k]);
                                }
 
+                               n = template[i].tap[k];
+                               if (k == template[i].np - 1 && enc)
+                                       n += authsize;
+                               if (offset_in_page(q) + n < PAGE_SIZE)
+                                       q[n] = 0;
+
                                temp += template[i].tap[k];
                        }
 
@@ -650,10 +648,10 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                        goto out;
                                }
 
-                               sg[k - 1].length += authsize;
-
                                if (diff_dst)
                                        sgout[k - 1].length += authsize;
+                               else
+                                       sg[k - 1].length += authsize;
                        }
 
                        sg_init_table(asg, template[i].anp);
index 5d9248526d780b06c51bee967cdd088c9c90e5e5..4770de5707b9b9eb0a4c27f14c7ec9ad13035257 100644 (file)
@@ -348,7 +348,6 @@ source "drivers/acpi/apei/Kconfig"
 config ACPI_EXTLOG
        tristate "Extended Error Log support"
        depends on X86_MCE && X86_LOCAL_APIC
-       select EFI
        select UEFI_CPER
        default n
        help
index 6745fe137b9ea541ae729429035eaeca8fc8fc07..e603905973721c415a912c04e2c7f3926fcd5634 100644 (file)
@@ -162,6 +162,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
        { "80860F14", (unsigned long)&byt_sdio_dev_desc },
        { "80860F41", (unsigned long)&byt_i2c_dev_desc },
        { "INT33B2", },
+       { "INT33FC", },
 
        { "INT3430", (unsigned long)&lpt_dev_desc },
        { "INT3431", (unsigned long)&lpt_dev_desc },
index f691d0e4d9fa091faeb0ebc231e8701b399c264b..ff97430455cbe923d3bad4f453635371b9388867 100644 (file)
@@ -184,7 +184,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
                             struct acpi_buffer *output_buffer);
 
 acpi_status
-acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
+acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
                             struct acpi_buffer *output_buffer);
 
 acpi_status
@@ -227,8 +227,8 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                        u32 aml_buffer_length, acpi_size * size_needed);
 
 acpi_status
-acpi_rs_get_aml_length(struct acpi_resource *linked_list_buffer,
-                      acpi_size * size_needed);
+acpi_rs_get_aml_length(struct acpi_resource *resource_list,
+                      acpi_size resource_list_size, acpi_size * size_needed);
 
 acpi_status
 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
index 243737363fb8ea51c80f77a16908659a29271a48..fd1ff54cda1911a1e520440afd8a48125d927069 100644 (file)
@@ -106,6 +106,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name)
 void acpi_ns_delete_node(struct acpi_namespace_node *node)
 {
        union acpi_operand_object *obj_desc;
+       union acpi_operand_object *next_desc;
 
        ACPI_FUNCTION_NAME(ns_delete_node);
 
@@ -114,12 +115,13 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
        acpi_ns_detach_object(node);
 
        /*
-        * Delete an attached data object if present (an object that was created
-        * and attached via acpi_attach_data). Note: After any normal object is
-        * detached above, the only possible remaining object is a data object.
+        * Delete an attached data object list if present (objects that were
+        * attached via acpi_attach_data). Note: After any normal object is
+        * detached above, the only possible remaining object(s) are data
+        * objects, in a linked list.
         */
        obj_desc = node->object;
-       if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
+       while (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
 
                /* Invoke the attached data deletion handler if present */
 
@@ -127,7 +129,15 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
                        obj_desc->data.handler(node, obj_desc->data.pointer);
                }
 
+               next_desc = obj_desc->common.next_object;
                acpi_ut_remove_reference(obj_desc);
+               obj_desc = next_desc;
+       }
+
+       /* Special case for the statically allocated root node */
+
+       if (node == acpi_gbl_root_node) {
+               return;
        }
 
        /* Now we can delete the node */
index cc2fea94c5f0939fcbfe87c676c0e869171a14f5..4a0665b6bcc11c6c6eb8aad3ee62be15b6122694 100644 (file)
@@ -593,24 +593,26 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
 
 void acpi_ns_terminate(void)
 {
-       union acpi_operand_object *obj_desc;
+       acpi_status status;
 
        ACPI_FUNCTION_TRACE(ns_terminate);
 
        /*
-        * 1) Free the entire namespace -- all nodes and objects
-        *
-        * Delete all object descriptors attached to namepsace nodes
+        * Free the entire namespace -- all nodes and all objects
+        * attached to the nodes
         */
        acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
 
-       /* Detach any objects attached to the root */
+       /* Delete any objects attached to the root node */
 
-       obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
-       if (obj_desc) {
-               acpi_ns_detach_object(acpi_gbl_root_node);
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               return_VOID;
        }
 
+       acpi_ns_delete_node(acpi_gbl_root_node);
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
        return_VOID;
 }
index b62a0f4f4f9bb527cd49fc95279b7032ba1a689a..b60c9cf82862f9e94dfb254b6a30b003e2dd5426 100644 (file)
@@ -174,6 +174,7 @@ acpi_rs_stream_option_length(u32 resource_length,
  * FUNCTION:    acpi_rs_get_aml_length
  *
  * PARAMETERS:  resource            - Pointer to the resource linked list
+ *              resource_list_size  - Size of the resource linked list
  *              size_needed         - Where the required size is returned
  *
  * RETURN:      Status
@@ -185,16 +186,20 @@ acpi_rs_stream_option_length(u32 resource_length,
  ******************************************************************************/
 
 acpi_status
-acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
+acpi_rs_get_aml_length(struct acpi_resource *resource,
+                      acpi_size resource_list_size, acpi_size * size_needed)
 {
        acpi_size aml_size_needed = 0;
+       struct acpi_resource *resource_end;
        acpi_rs_length total_size;
 
        ACPI_FUNCTION_TRACE(rs_get_aml_length);
 
        /* Traverse entire list of internal resource descriptors */
 
-       while (resource) {
+       resource_end =
+           ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
+       while (resource < resource_end) {
 
                /* Validate the descriptor type */
 
index 65f3e1c5b5989f61bdcb03e6620cdd1a7371dba9..3a2ace93e62cf5d11690a4a4a907ae5539007f9e 100644 (file)
@@ -418,22 +418,21 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
  *
  * FUNCTION:    acpi_rs_create_aml_resources
  *
- * PARAMETERS:  linked_list_buffer      - Pointer to the resource linked list
- *              output_buffer           - Pointer to the user's buffer
+ * PARAMETERS:  resource_list           - Pointer to the resource list buffer
+ *              output_buffer           - Where the AML buffer is returned
  *
  * RETURN:      Status  AE_OK if okay, else a valid acpi_status code.
  *              If the output_buffer is too small, the error will be
  *              AE_BUFFER_OVERFLOW and output_buffer->Length will point
  *              to the size buffer needed.
  *
- * DESCRIPTION: Takes the linked list of device resources and
- *              creates a bytestream to be used as input for the
- *              _SRS control method.
+ * DESCRIPTION: Converts a list of device resources to an AML bytestream
+ *              to be used as input for the _SRS control method.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
+acpi_rs_create_aml_resources(struct acpi_buffer *resource_list,
                             struct acpi_buffer *output_buffer)
 {
        acpi_status status;
@@ -441,16 +440,16 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
 
        ACPI_FUNCTION_TRACE(rs_create_aml_resources);
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n",
-                         linked_list_buffer));
+       /* Params already validated, no need to re-validate here */
 
-       /*
-        * Params already validated, so we don't re-validate here
-        *
-        * Pass the linked_list_buffer into a module that calculates
-        * the buffer size needed for the byte stream.
-        */
-       status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ResourceList Buffer = %p\n",
+                         resource_list->pointer));
+
+       /* Get the buffer size needed for the AML byte stream */
+
+       status = acpi_rs_get_aml_length(resource_list->pointer,
+                                       resource_list->length,
+                                       &aml_size_needed);
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
                          (u32)aml_size_needed, acpi_format_exception(status)));
@@ -467,10 +466,9 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
 
        /* Do the conversion */
 
-       status =
-           acpi_rs_convert_resources_to_aml(linked_list_buffer,
-                                            aml_size_needed,
-                                            output_buffer->pointer);
+       status = acpi_rs_convert_resources_to_aml(resource_list->pointer,
+                                                 aml_size_needed,
+                                                 output_buffer->pointer);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
index aef303d56d86fecc84e397cad3c24280a874dbb4..14a7982c9961088ae50c0283bfefb4b4b5ccb488 100644 (file)
@@ -753,7 +753,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
         * Convert the linked list into a byte stream
         */
        buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
-       status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
+       status = acpi_rs_create_aml_resources(in_buffer, &buffer);
        if (ACPI_FAILURE(status)) {
                goto cleanup;
        }
index 1a67b3944b3b8db426fb3edf7b878153785b7631..03ae8affe48f097b1aae7346edd25a165f23186a 100644 (file)
@@ -185,6 +185,7 @@ acpi_debug_print(u32 requested_debug_level,
                }
 
                acpi_gbl_prev_thread_id = thread_id;
+               acpi_gbl_nesting_level = 0;
        }
 
        /*
@@ -193,13 +194,21 @@ acpi_debug_print(u32 requested_debug_level,
         */
        acpi_os_printf("%9s-%04ld ", module_name, line_number);
 
+#ifdef ACPI_EXEC_APP
+       /*
+        * For acpi_exec only, emit the thread ID and nesting level.
+        * Note: nesting level is really only useful during a single-thread
+        * execution. Otherwise, multiple threads will keep resetting the
+        * level.
+        */
        if (ACPI_LV_THREADS & acpi_dbg_level) {
                acpi_os_printf("[%u] ", (u32)thread_id);
        }
 
-       acpi_os_printf("[%02ld] %-22.22s: ",
-                      acpi_gbl_nesting_level,
-                      acpi_ut_trim_function_name(function_name));
+       acpi_os_printf("[%02ld] ", acpi_gbl_nesting_level);
+#endif
+
+       acpi_os_printf("%-22.22s: ", acpi_ut_trim_function_name(function_name));
 
        va_start(args, format);
        acpi_os_vprintf(format, args);
@@ -420,7 +429,9 @@ acpi_ut_exit(u32 line_number,
                                 component_id, "%s\n", acpi_gbl_fn_exit_str);
        }
 
-       acpi_gbl_nesting_level--;
+       if (acpi_gbl_nesting_level) {
+               acpi_gbl_nesting_level--;
+       }
 }
 
 ACPI_EXPORT_SYMBOL(acpi_ut_exit)
@@ -467,7 +478,9 @@ acpi_ut_status_exit(u32 line_number,
                }
        }
 
-       acpi_gbl_nesting_level--;
+       if (acpi_gbl_nesting_level) {
+               acpi_gbl_nesting_level--;
+       }
 }
 
 ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
@@ -504,7 +517,9 @@ acpi_ut_value_exit(u32 line_number,
                                 ACPI_FORMAT_UINT64(value));
        }
 
-       acpi_gbl_nesting_level--;
+       if (acpi_gbl_nesting_level) {
+               acpi_gbl_nesting_level--;
+       }
 }
 
 ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
@@ -540,7 +555,9 @@ acpi_ut_ptr_exit(u32 line_number,
                                 ptr);
        }
 
-       acpi_gbl_nesting_level--;
+       if (acpi_gbl_nesting_level) {
+               acpi_gbl_nesting_level--;
+       }
 }
 
 #endif
index 786294bb682c104f111525ca17df7ccfafab0d88..3650b21832279a91568266208059296fadfab94c 100644 (file)
@@ -2,7 +2,6 @@ config ACPI_APEI
        bool "ACPI Platform Error Interface (APEI)"
        select MISC_FILESYSTEMS
        select PSTORE
-       select EFI
        select UEFI_CPER
        depends on X86
        help
index 26311f23c824f91354b3e47fe6fa5e5e448275dc..cb1d557fc22c054fa36beb1f74bfae42ea49f2c2 100644 (file)
@@ -942,6 +942,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info erst_info = {
        .owner          = THIS_MODULE,
        .name           = "erst",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = erst_open_pstore,
        .close          = erst_close_pstore,
        .read           = erst_reader,
index 266bc58ce0ce165eb4c1a6bf707c7af5d5080c36..386a9fe497b451d0da6ebed2bc4b6f1a2dacda71 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/acpi_io.h>
-#include <acpi/acpiosxf.h>
 
 /* ACPI NVS regions, APEI may use it */
 
index 0703bff5e60ecaf2f9d207f9ffc1691d50380384..20360e480bd8d81c0070cc25b5cd2cddd05d0447 100644 (file)
@@ -65,6 +65,9 @@ static struct acpi_scan_handler pci_root_handler = {
        .ids = root_device_ids,
        .attach = acpi_pci_root_add,
        .detach = acpi_pci_root_remove,
+       .hotplug = {
+               .ignore = true,
+       },
 };
 
 static DEFINE_MUTEX(osc_lock);
index 15daa21fcd056cf75b50eccf34a08482e0e24e8a..fd39459926b1564c2faa3d367a4dbbf05aa60031 100644 (file)
@@ -1772,7 +1772,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type)
         */
        list_for_each_entry(hwid, &pnp.ids, list) {
                handler = acpi_scan_match_handler(hwid->id, NULL);
-               if (handler) {
+               if (handler && !handler->hotplug.ignore) {
                        acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
                                        acpi_hotplug_notify_cb, handler);
                        break;
index 14df30580e154802aca352176ada8214f7ea6067..721e949e606edff0e2b62dc1e4d12e201bbbad4d 100644 (file)
@@ -525,7 +525,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
         * generate wakeup events.
         */
        if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
-               acpi_event_status pwr_btn_status;
+               acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED;
 
                acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
 
index db5293650f622108e80a09124097f469c727547f..6dbc3ca45223a1ba30f995f016ecd965dd4861f7 100644 (file)
@@ -309,7 +309,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
                sprintf(table_attr->name + ACPI_NAME_SIZE, "%d",
                        table_attr->instance);
 
-       table_attr->attr.size = 0;
+       table_attr->attr.size = table_header->length;
        table_attr->attr.read = acpi_table_show;
        table_attr->attr.attr.name = table_attr->name;
        table_attr->attr.attr.mode = 0400;
@@ -354,8 +354,9 @@ static int acpi_tables_sysfs_init(void)
 {
        struct acpi_table_attr *table_attr;
        struct acpi_table_header *table_header = NULL;
-       int table_index = 0;
-       int result;
+       int table_index;
+       acpi_status status;
+       int ret;
 
        tables_kobj = kobject_create_and_add("tables", acpi_kobj);
        if (!tables_kobj)
@@ -365,33 +366,34 @@ static int acpi_tables_sysfs_init(void)
        if (!dynamic_tables_kobj)
                goto err_dynamic_tables;
 
-       do {
-               result = acpi_get_table_by_index(table_index, &table_header);
-               if (!result) {
-                       table_index++;
-                       table_attr = NULL;
-                       table_attr =
-                           kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
-                       if (!table_attr)
-                               return -ENOMEM;
-
-                       acpi_table_attr_init(table_attr, table_header);
-                       result =
-                           sysfs_create_bin_file(tables_kobj,
-                                                 &table_attr->attr);
-                       if (result) {
-                               kfree(table_attr);
-                               return result;
-                       } else
-                               list_add_tail(&table_attr->node,
-                                             &acpi_table_attr_list);
+       for (table_index = 0;; table_index++) {
+               status = acpi_get_table_by_index(table_index, &table_header);
+
+               if (status == AE_BAD_PARAMETER)
+                       break;
+
+               if (ACPI_FAILURE(status))
+                       continue;
+
+               table_attr = NULL;
+               table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
+               if (!table_attr)
+                       return -ENOMEM;
+
+               acpi_table_attr_init(table_attr, table_header);
+               ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr);
+               if (ret) {
+                       kfree(table_attr);
+                       return ret;
                }
-       } while (!result);
+               list_add_tail(&table_attr->node, &acpi_table_attr_list);
+       }
+
        kobject_uevent(tables_kobj, KOBJ_ADD);
        kobject_uevent(dynamic_tables_kobj, KOBJ_ADD);
-       result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL);
+       status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL);
 
-       return result == AE_OK ? 0 : -EINVAL;
+       return ACPI_FAILURE(status) ? -EINVAL : 0;
 err_dynamic_tables:
        kobject_put(tables_kobj);
 err:
index e2903d03180e1190410c3054ee78990a007e93b2..c0ed4f273cf22b50a486b08f08c811e563781b07 100644 (file)
@@ -435,6 +435,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on some Gigabyte */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
          .driver_data = board_ahci_yes_fbs },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
+         .driver_data = board_ahci_yes_fbs },
 
        /* Promise */
        { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
@@ -1236,15 +1238,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       /* AHCI controllers often implement SFF compatible interface.
-        * Grab all PCI BARs just in case.
-        */
-       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
-       if (rc == -EBUSY)
-               pcim_pin_device(pdev);
-       if (rc)
-               return rc;
-
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
            (pdev->device == 0x2652 || pdev->device == 0x2653)) {
                u8 map;
@@ -1261,6 +1254,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+       /* AHCI controllers often implement SFF compatible interface.
+        * Grab all PCI BARs just in case.
+        */
+       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
+       if (rc == -EBUSY)
+               pcim_pin_device(pdev);
+       if (rc)
+               return rc;
+
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
index ae2d73fe321e2f2c62d8e5709a788905edfd5a89..3e23e9941dad0080d629581723243c6550d4d476 100644 (file)
@@ -113,7 +113,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
        /*
         * set PHY Paremeters, two steps to configure the GPR13,
         * one write for rest of parameters, mask of first write
-        * is 0x07fffffd, and the other one write for setting
+        * is 0x07ffffff, and the other one write for setting
         * the mpll_clk_en.
         */
        regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
@@ -124,6 +124,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
                        | IMX6Q_GPR13_SATA_TX_ATTEN_MASK
                        | IMX6Q_GPR13_SATA_TX_BOOST_MASK
                        | IMX6Q_GPR13_SATA_TX_LVL_MASK
+                       | IMX6Q_GPR13_SATA_MPLL_CLK_EN
                        | IMX6Q_GPR13_SATA_TX_EDGE_RATE
                        , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
                        | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
index f9554318504f8a401c97b2221831b1cdbdcdb67f..4b231baceb0995557c2cae40e501f6d3449dc365 100644 (file)
@@ -329,6 +329,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
 static const struct of_device_id ahci_of_match[] = {
        { .compatible = "snps,spear-ahci", },
        { .compatible = "snps,exynos5440-ahci", },
+       { .compatible = "ibm,476gtr-ahci", },
        {},
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
index 81a94a3919dbb0992c079e84130a1c850d81e587..1393a5890ed5356e5ef36965ea74e49e226c0a29 100644 (file)
@@ -2149,9 +2149,16 @@ static int ata_dev_config_ncq(struct ata_device *dev,
                                    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
                                    err_mask);
                } else {
+                       u8 *cmds = dev->ncq_send_recv_cmds;
+
                        dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
-                       memcpy(dev->ncq_send_recv_cmds, ap->sector_buf,
-                               ATA_LOG_NCQ_SEND_RECV_SIZE);
+                       memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+
+                       if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
+                               ata_dev_dbg(dev, "disabling queued TRIM support\n");
+                               cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
+                                       ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
+                       }
                }
        }
 
@@ -4156,6 +4163,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
+       /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+       { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
@@ -4202,6 +4212,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* devices that don't properly handle queued TRIM commands */
+       { "Micron_M500*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M500SSD1",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+
        /* End Marker */
        { }
 };
@@ -6304,10 +6318,9 @@ static void ata_port_detach(struct ata_port *ap)
                for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
                        ata_tlink_delete(&ap->pmp_link[i]);
        }
-       ata_tport_delete(ap);
-
        /* remove the associated SCSI host */
        scsi_remove_host(ap->scsi_host);
+       ata_tport_delete(ap);
 }
 
 /**
@@ -6520,6 +6533,7 @@ static int __init ata_parse_force_one(char **cur,
                { "norst",      .lflags         = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
                { "rstonce",    .lflags         = ATA_LFLAG_RST_ONCE },
                { "atapi_dmadir", .horkage_on   = ATA_HORKAGE_ATAPI_DMADIR },
+               { "disable",    .horkage_on     = ATA_HORKAGE_DISABLE },
        };
        char *start = *cur, *p = *cur;
        char *id, *val, *endp;
index db6dfcfa3e2ee932190069290814f2a71bc8f3f6..377eb889f555dd2029c46a01254a3a204744ac81 100644 (file)
@@ -3625,6 +3625,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                shost->max_lun = 1;
                shost->max_channel = 1;
                shost->max_cmd_len = 16;
+               shost->no_write_same = 1;
 
                /* Schedule policy is determined by ->qc_defer()
                 * callback and it needs to see every deferred qc.
@@ -3871,6 +3872,27 @@ void ata_scsi_hotplug(struct work_struct *work)
                return;
        }
 
+       /*
+        * XXX - UGLY HACK
+        *
+        * The block layer suspend/resume path is fundamentally broken due
+        * to freezable kthreads and workqueue and may deadlock if a block
+        * device gets removed while resume is in progress.  I don't know
+        * what the solution is short of removing freezable kthreads and
+        * workqueues altogether.
+        *
+        * The following is an ugly hack to avoid kicking off device
+        * removal while freezer is active.  This is a joke but does avoid
+        * this particular deadlock scenario.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=62801
+        * http://marc.info/?l=linux-kernel&m=138695698516487
+        */
+#ifdef CONFIG_FREEZER
+       while (pm_freezing)
+               msleep(10);
+#endif
+
        DPRINTK("ENTER\n");
        mutex_lock(&ap->scsi_scan_mutex);
 
index 68f9e3293e9c62971486937d6a5048c58b1a056c..88949c6d55ddd43b32b07accdb892256028d5e25 100644 (file)
@@ -88,15 +88,13 @@ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
 static bool odd_can_poweroff(struct ata_device *ata_dev)
 {
        acpi_handle handle;
-       acpi_status status;
        struct acpi_device *acpi_dev;
 
        handle = ata_dev_acpi_handle(ata_dev);
        if (!handle)
                return false;
 
-       status = acpi_bus_get_device(handle, &acpi_dev);
-       if (ACPI_FAILURE(status))
+       if (acpi_bus_get_device(handle, &acpi_dev))
                return false;
 
        return acpi_device_can_poweroff(acpi_dev);
index e88690ebfd827b8a02558c4b611b474a4f8c4a1e..73492dd4a4bce8aade1f79a7dbdfd3926c7f6f6b 100644 (file)
@@ -319,6 +319,7 @@ static int cf_init(struct arasan_cf_dev *acdev)
        ret = clk_set_rate(acdev->clk, 166000000);
        if (ret) {
                dev_warn(acdev->host->dev, "clock set rate failed");
+               clk_disable_unprepare(acdev->clk);
                return ret;
        }
 
index 98745dd77e8ccfb75080d47fb099448d81d1eaa8..81f977510775460fa2bf8b0bd500c69027c02274 100644 (file)
@@ -40,7 +40,7 @@ static int regmap_mmio_gather_write(void *context,
 
        BUG_ON(reg_size != 4);
 
-       if (ctx->clk) {
+       if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
@@ -73,7 +73,7 @@ static int regmap_mmio_gather_write(void *context,
                offset += ctx->val_bytes;
        }
 
-       if (ctx->clk)
+       if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
 
        return 0;
@@ -96,7 +96,7 @@ static int regmap_mmio_read(void *context,
 
        BUG_ON(reg_size != 4);
 
-       if (ctx->clk) {
+       if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
@@ -129,7 +129,7 @@ static int regmap_mmio_read(void *context,
                offset += ctx->val_bytes;
        }
 
-       if (ctx->clk)
+       if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
 
        return 0;
@@ -139,7 +139,7 @@ static void regmap_mmio_free_context(void *context)
 {
        struct regmap_mmio_context *ctx = context;
 
-       if (ctx->clk) {
+       if (!IS_ERR(ctx->clk)) {
                clk_unprepare(ctx->clk);
                clk_put(ctx->clk);
        }
@@ -209,6 +209,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
 
        ctx->regs = regs;
        ctx->val_bytes = config->val_bits / 8;
+       ctx->clk = ERR_PTR(-ENODEV);
 
        if (clk_id == NULL)
                return ctx;
index 9c021d9cace0fcc74080ccec7b5a2b3933c65f2a..c2e00210094995fde1cc69998d03f98e01c75fb1 100644 (file)
@@ -1549,7 +1549,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
                                                val + (i * val_bytes),
                                                val_bytes);
                        if (ret != 0)
-                               return ret;
+                               goto out;
                }
        } else {
                ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
@@ -1743,7 +1743,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
 /**
  * regmap_read(): Read a value from a single register
  *
- * @map: Register map to write to
+ * @map: Register map to read from
  * @reg: Register to be read from
  * @val: Pointer to store read value
  *
@@ -1770,7 +1770,7 @@ EXPORT_SYMBOL_GPL(regmap_read);
 /**
  * regmap_raw_read(): Read raw data from the device
  *
- * @map: Register map to write to
+ * @map: Register map to read from
  * @reg: First register to be read from
  * @val: Pointer to store read value
  * @val_len: Size of data to read
@@ -1882,7 +1882,7 @@ EXPORT_SYMBOL_GPL(regmap_fields_read);
 /**
  * regmap_bulk_read(): Read multiple registers from the device
  *
- * @map: Register map to write to
+ * @map: Register map to read from
  * @reg: First register to be read from
  * @val: Pointer to store read value, in native register size for device
  * @val_count: Number of registers to read
index ea192ec029c45bf7354d8184b44e1eb460cdbf77..a2e69d26266d9b7faef4244aef695180d4c6eaef 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+
 #include <linux/moduleparam.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -65,7 +66,7 @@ enum {
        NULL_Q_MQ               = 2,
 };
 
-static int submit_queues = 1;
+static int submit_queues;
 module_param(submit_queues, int, S_IRUGO);
 MODULE_PARM_DESC(submit_queues, "Number of submission queues");
 
@@ -101,9 +102,9 @@ static int hw_queue_depth = 64;
 module_param(hw_queue_depth, int, S_IRUGO);
 MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: 64");
 
-static bool use_per_node_hctx = true;
+static bool use_per_node_hctx = false;
 module_param(use_per_node_hctx, bool, S_IRUGO);
-MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: true");
+MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: false");
 
 static void put_tag(struct nullb_queue *nq, unsigned int tag)
 {
@@ -346,8 +347,37 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq)
 
 static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_reg *reg, unsigned int hctx_index)
 {
-       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL,
-                               hctx_index);
+       int b_size = DIV_ROUND_UP(reg->nr_hw_queues, nr_online_nodes);
+       int tip = (reg->nr_hw_queues % nr_online_nodes);
+       int node = 0, i, n;
+
+       /*
+        * Split submit queues evenly wrt to the number of nodes. If uneven,
+        * fill the first buckets with one extra, until the rest is filled with
+        * no extra.
+        */
+       for (i = 0, n = 1; i < hctx_index; i++, n++) {
+               if (n % b_size == 0) {
+                       n = 0;
+                       node++;
+
+                       tip--;
+                       if (!tip)
+                               b_size = reg->nr_hw_queues / nr_online_nodes;
+               }
+       }
+
+       /*
+        * A node might not be online, therefore map the relative node id to the
+        * real node id.
+        */
+       for_each_online_node(n) {
+               if (!node)
+                       break;
+               node--;
+       }
+
+       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL, n);
 }
 
 static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
@@ -355,16 +385,24 @@ static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
        kfree(hctx);
 }
 
+static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
+{
+       BUG_ON(!nullb);
+       BUG_ON(!nq);
+
+       init_waitqueue_head(&nq->wait);
+       nq->queue_depth = nullb->queue_depth;
+}
+
 static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
                          unsigned int index)
 {
        struct nullb *nullb = data;
        struct nullb_queue *nq = &nullb->queues[index];
 
-       init_waitqueue_head(&nq->wait);
-       nq->queue_depth = nullb->queue_depth;
-       nullb->nr_queues++;
        hctx->driver_data = nq;
+       null_init_queue(nullb, nq);
+       nullb->nr_queues++;
 
        return 0;
 }
@@ -417,13 +455,13 @@ static int setup_commands(struct nullb_queue *nq)
 
        nq->cmds = kzalloc(nq->queue_depth * sizeof(*cmd), GFP_KERNEL);
        if (!nq->cmds)
-               return 1;
+               return -ENOMEM;
 
        tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG;
        nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL);
        if (!nq->tag_map) {
                kfree(nq->cmds);
-               return 1;
+               return -ENOMEM;
        }
 
        for (i = 0; i < nq->queue_depth; i++) {
@@ -454,33 +492,37 @@ static void cleanup_queues(struct nullb *nullb)
 
 static int setup_queues(struct nullb *nullb)
 {
-       struct nullb_queue *nq;
-       int i;
-
-       nullb->queues = kzalloc(submit_queues * sizeof(*nq), GFP_KERNEL);
+       nullb->queues = kzalloc(submit_queues * sizeof(struct nullb_queue),
+                                                               GFP_KERNEL);
        if (!nullb->queues)
-               return 1;
+               return -ENOMEM;
 
        nullb->nr_queues = 0;
        nullb->queue_depth = hw_queue_depth;
 
-       if (queue_mode == NULL_Q_MQ)
-               return 0;
+       return 0;
+}
+
+static int init_driver_queues(struct nullb *nullb)
+{
+       struct nullb_queue *nq;
+       int i, ret = 0;
 
        for (i = 0; i < submit_queues; i++) {
                nq = &nullb->queues[i];
-               init_waitqueue_head(&nq->wait);
-               nq->queue_depth = hw_queue_depth;
-               if (setup_commands(nq))
-                       break;
+
+               null_init_queue(nullb, nq);
+
+               ret = setup_commands(nq);
+               if (ret)
+                       goto err_queue;
                nullb->nr_queues++;
        }
 
-       if (i == submit_queues)
-               return 0;
-
+       return 0;
+err_queue:
        cleanup_queues(nullb);
-       return 1;
+       return ret;
 }
 
 static int null_add_dev(void)
@@ -495,34 +537,36 @@ static int null_add_dev(void)
 
        spin_lock_init(&nullb->lock);
 
+       if (queue_mode == NULL_Q_MQ && use_per_node_hctx)
+               submit_queues = nr_online_nodes;
+
        if (setup_queues(nullb))
                goto err;
 
        if (queue_mode == NULL_Q_MQ) {
                null_mq_reg.numa_node = home_node;
                null_mq_reg.queue_depth = hw_queue_depth;
+               null_mq_reg.nr_hw_queues = submit_queues;
 
                if (use_per_node_hctx) {
                        null_mq_reg.ops->alloc_hctx = null_alloc_hctx;
                        null_mq_reg.ops->free_hctx = null_free_hctx;
-
-                       null_mq_reg.nr_hw_queues = nr_online_nodes;
                } else {
                        null_mq_reg.ops->alloc_hctx = blk_mq_alloc_single_hw_queue;
                        null_mq_reg.ops->free_hctx = blk_mq_free_single_hw_queue;
-
-                       null_mq_reg.nr_hw_queues = submit_queues;
                }
 
                nullb->q = blk_mq_init_queue(&null_mq_reg, nullb);
        } else if (queue_mode == NULL_Q_BIO) {
                nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
                blk_queue_make_request(nullb->q, null_queue_bio);
+               init_driver_queues(nullb);
        } else {
                nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
                blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
                if (nullb->q)
                        blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
+               init_driver_queues(nullb);
        }
 
        if (!nullb->q)
@@ -579,7 +623,13 @@ static int __init null_init(void)
        }
 #endif
 
-       if (submit_queues > nr_cpu_ids)
+       if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
+               if (submit_queues < nr_online_nodes) {
+                       pr_warn("null_blk: submit_queues param is set to %u.",
+                                                       nr_online_nodes);
+                       submit_queues = nr_online_nodes;
+               }
+       } else if (submit_queues > nr_cpu_ids)
                submit_queues = nr_cpu_ids;
        else if (!submit_queues)
                submit_queues = 1;
index 9199c93be926ed97f33eaa95fc9ce4ec0549cea7..eb6e1e0e8db25f78f2d2407e0d54dafc2a2b9583 100644 (file)
@@ -5269,7 +5269,7 @@ const char *skd_skdev_state_to_str(enum skd_drvr_state state)
        }
 }
 
-const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
+static const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
 {
        switch (state) {
        case SKD_MSG_STATE_IDLE:
@@ -5281,7 +5281,7 @@ const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
        }
 }
 
-const char *skd_skreq_state_to_str(enum skd_req_state state)
+static const char *skd_skreq_state_to_str(enum skd_req_state state)
 {
        switch (state) {
        case SKD_REQ_STATE_IDLE:
index 432db1b59b003a837679cd187c4743f98ca9b152..c4a4c900628891c31fec541277cb7ffea9a3e68b 100644 (file)
@@ -489,7 +489,7 @@ static int blkif_queue_request(struct request *req)
 
                        if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
                            (i % SEGS_PER_INDIRECT_FRAME == 0)) {
-                               unsigned long pfn;
+                               unsigned long uninitialized_var(pfn);
 
                                if (segments)
                                        kunmap_atomic(segments);
@@ -2011,6 +2011,10 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
 
        bdev = bdget_disk(disk, 0);
 
+       if (!bdev) {
+               WARN(1, "Block device %s yanked out from us!\n", disk->disk_name);
+               goto out_mutex;
+       }
        if (bdev->bd_openers)
                goto out;
 
@@ -2041,6 +2045,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
 
 out:
        bdput(bdev);
+out_mutex:
        mutex_unlock(&blkfront_mutex);
 }
 
index c206de2951f20f086c099ab69e8a1a48286465be..2f2b08457c673547568187f04863a01947163385 100644 (file)
@@ -165,6 +165,19 @@ config HW_RANDOM_OMAP
 
          If unsure, say Y.
 
+config HW_RANDOM_OMAP3_ROM
+       tristate "OMAP3 ROM Random Number Generator support"
+       depends on HW_RANDOM && ARCH_OMAP3
+       default HW_RANDOM
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on OMAP34xx processors.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap3-rom-rng.
+
+         If unsure, say Y.
+
 config HW_RANDOM_OCTEON
        tristate "Octeon Random Number Generator support"
        depends on HW_RANDOM && CAVIUM_OCTEON_SOC
@@ -327,3 +340,15 @@ config HW_RANDOM_TPM
          module will be called tpm-rng.
 
          If unsure, say Y.
+
+config HW_RANDOM_MSM
+       tristate "Qualcomm MSM Random Number Generator support"
+       depends on HW_RANDOM && ARCH_MSM
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on Qualcomm MSM SoCs.
+
+         To compile this driver as a module, choose M here. the
+         module will be called msm-rng.
+
+         If unsure, say Y.
index d7d2435ff7fa8d38cd129d327c59ded717e3682a..3ae7755a52e706bd8356e8ae5bc660fe8a693767 100644 (file)
@@ -15,6 +15,7 @@ n2-rng-y := n2-drv.o n2-asm.o
 obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
 obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
+obj-$(CONFIG_HW_RANDOM_OMAP3_ROM) += omap3-rom-rng.o
 obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
 obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
 obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
@@ -28,3 +29,4 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
 obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
 obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
+obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o
diff --git a/drivers/char/hw_random/msm-rng.c b/drivers/char/hw_random/msm-rng.c
new file mode 100644 (file)
index 0000000..148521e
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+/* Device specific register offsets */
+#define PRNG_DATA_OUT          0x0000
+#define PRNG_STATUS            0x0004
+#define PRNG_LFSR_CFG          0x0100
+#define PRNG_CONFIG            0x0104
+
+/* Device specific register masks and config values */
+#define PRNG_LFSR_CFG_MASK     0x0000ffff
+#define PRNG_LFSR_CFG_CLOCKS   0x0000dddd
+#define PRNG_CONFIG_HW_ENABLE  BIT(1)
+#define PRNG_STATUS_DATA_AVAIL BIT(0)
+
+#define MAX_HW_FIFO_DEPTH      16
+#define MAX_HW_FIFO_SIZE       (MAX_HW_FIFO_DEPTH * 4)
+#define WORD_SZ                        4
+
+struct msm_rng {
+       void __iomem *base;
+       struct clk *clk;
+       struct hwrng hwrng;
+};
+
+#define to_msm_rng(p)  container_of(p, struct msm_rng, hwrng)
+
+static int msm_rng_enable(struct hwrng *hwrng, int enable)
+{
+       struct msm_rng *rng = to_msm_rng(hwrng);
+       u32 val;
+       int ret;
+
+       ret = clk_prepare_enable(rng->clk);
+       if (ret)
+               return ret;
+
+       if (enable) {
+               /* Enable PRNG only if it is not already enabled */
+               val = readl_relaxed(rng->base + PRNG_CONFIG);
+               if (val & PRNG_CONFIG_HW_ENABLE)
+                       goto already_enabled;
+
+               val = readl_relaxed(rng->base + PRNG_LFSR_CFG);
+               val &= ~PRNG_LFSR_CFG_MASK;
+               val |= PRNG_LFSR_CFG_CLOCKS;
+               writel(val, rng->base + PRNG_LFSR_CFG);
+
+               val = readl_relaxed(rng->base + PRNG_CONFIG);
+               val |= PRNG_CONFIG_HW_ENABLE;
+               writel(val, rng->base + PRNG_CONFIG);
+       } else {
+               val = readl_relaxed(rng->base + PRNG_CONFIG);
+               val &= ~PRNG_CONFIG_HW_ENABLE;
+               writel(val, rng->base + PRNG_CONFIG);
+       }
+
+already_enabled:
+       clk_disable_unprepare(rng->clk);
+       return 0;
+}
+
+static int msm_rng_read(struct hwrng *hwrng, void *data, size_t max, bool wait)
+{
+       struct msm_rng *rng = to_msm_rng(hwrng);
+       size_t currsize = 0;
+       u32 *retdata = data;
+       size_t maxsize;
+       int ret;
+       u32 val;
+
+       /* calculate max size bytes to transfer back to caller */
+       maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, max);
+
+       /* no room for word data */
+       if (maxsize < WORD_SZ)
+               return 0;
+
+       ret = clk_prepare_enable(rng->clk);
+       if (ret)
+               return ret;
+
+       /* read random data from hardware */
+       do {
+               val = readl_relaxed(rng->base + PRNG_STATUS);
+               if (!(val & PRNG_STATUS_DATA_AVAIL))
+                       break;
+
+               val = readl_relaxed(rng->base + PRNG_DATA_OUT);
+               if (!val)
+                       break;
+
+               *retdata++ = val;
+               currsize += WORD_SZ;
+
+               /* make sure we stay on 32bit boundary */
+               if ((maxsize - currsize) < WORD_SZ)
+                       break;
+       } while (currsize < maxsize);
+
+       clk_disable_unprepare(rng->clk);
+
+       return currsize;
+}
+
+static int msm_rng_init(struct hwrng *hwrng)
+{
+       return msm_rng_enable(hwrng, 1);
+}
+
+static void msm_rng_cleanup(struct hwrng *hwrng)
+{
+       msm_rng_enable(hwrng, 0);
+}
+
+static int msm_rng_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct msm_rng *rng;
+       int ret;
+
+       rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
+       if (!rng)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, rng);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rng->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(rng->base))
+               return PTR_ERR(rng->base);
+
+       rng->clk = devm_clk_get(&pdev->dev, "core");
+       if (IS_ERR(rng->clk))
+               return PTR_ERR(rng->clk);
+
+       rng->hwrng.name = KBUILD_MODNAME,
+       rng->hwrng.init = msm_rng_init,
+       rng->hwrng.cleanup = msm_rng_cleanup,
+       rng->hwrng.read = msm_rng_read,
+
+       ret = hwrng_register(&rng->hwrng);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register hwrng\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int msm_rng_remove(struct platform_device *pdev)
+{
+       struct msm_rng *rng = platform_get_drvdata(pdev);
+
+       hwrng_unregister(&rng->hwrng);
+       return 0;
+}
+
+static const struct of_device_id msm_rng_of_match[] = {
+       { .compatible = "qcom,prng", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, msm_rng_of_match);
+
+static struct platform_driver msm_rng_driver = {
+       .probe = msm_rng_probe,
+       .remove = msm_rng_remove,
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(msm_rng_of_match),
+       }
+};
+module_platform_driver(msm_rng_driver);
+
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
+MODULE_AUTHOR("The Linux Foundation");
+MODULE_DESCRIPTION("Qualcomm MSM random number generator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c
new file mode 100644 (file)
index 0000000..c853e9e
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * omap3-rom-rng.c - RNG driver for TI OMAP3 CPU family
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Juha Yrjola <juha.yrjola@solidboot.com>
+ *
+ * Copyright (C) 2013 Pali Rohár <pali.rohar@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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/hw_random.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#define RNG_RESET                      0x01
+#define RNG_GEN_PRNG_HW_INIT           0x02
+#define RNG_GEN_HW                     0x08
+
+/* param1: ptr, param2: count, param3: flag */
+static u32 (*omap3_rom_rng_call)(u32, u32, u32);
+
+static struct timer_list idle_timer;
+static int rng_idle;
+static struct clk *rng_clk;
+
+static void omap3_rom_rng_idle(unsigned long data)
+{
+       int r;
+
+       r = omap3_rom_rng_call(0, 0, RNG_RESET);
+       if (r != 0) {
+               pr_err("reset failed: %d\n", r);
+               return;
+       }
+       clk_disable_unprepare(rng_clk);
+       rng_idle = 1;
+}
+
+static int omap3_rom_rng_get_random(void *buf, unsigned int count)
+{
+       u32 r;
+       u32 ptr;
+
+       del_timer_sync(&idle_timer);
+       if (rng_idle) {
+               clk_prepare_enable(rng_clk);
+               r = omap3_rom_rng_call(0, 0, RNG_GEN_PRNG_HW_INIT);
+               if (r != 0) {
+                       clk_disable_unprepare(rng_clk);
+                       pr_err("HW init failed: %d\n", r);
+                       return -EIO;
+               }
+               rng_idle = 0;
+       }
+
+       ptr = virt_to_phys(buf);
+       r = omap3_rom_rng_call(ptr, count, RNG_GEN_HW);
+       mod_timer(&idle_timer, jiffies + msecs_to_jiffies(500));
+       if (r != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static int omap3_rom_rng_data_present(struct hwrng *rng, int wait)
+{
+       return 1;
+}
+
+static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       int r;
+
+       r = omap3_rom_rng_get_random(data, 4);
+       if (r < 0)
+               return r;
+       return 4;
+}
+
+static struct hwrng omap3_rom_rng_ops = {
+       .name           = "omap3-rom",
+       .data_present   = omap3_rom_rng_data_present,
+       .data_read      = omap3_rom_rng_data_read,
+};
+
+static int omap3_rom_rng_probe(struct platform_device *pdev)
+{
+       pr_info("initializing\n");
+
+       omap3_rom_rng_call = pdev->dev.platform_data;
+       if (!omap3_rom_rng_call) {
+               pr_err("omap3_rom_rng_call is NULL\n");
+               return -EINVAL;
+       }
+
+       setup_timer(&idle_timer, omap3_rom_rng_idle, 0);
+       rng_clk = clk_get(&pdev->dev, "ick");
+       if (IS_ERR(rng_clk)) {
+               pr_err("unable to get RNG clock\n");
+               return PTR_ERR(rng_clk);
+       }
+
+       /* Leave the RNG in reset state. */
+       clk_prepare_enable(rng_clk);
+       omap3_rom_rng_idle(0);
+
+       return hwrng_register(&omap3_rom_rng_ops);
+}
+
+static int omap3_rom_rng_remove(struct platform_device *pdev)
+{
+       hwrng_unregister(&omap3_rom_rng_ops);
+       clk_disable_unprepare(rng_clk);
+       clk_put(rng_clk);
+       return 0;
+}
+
+static struct platform_driver omap3_rom_rng_driver = {
+       .driver = {
+               .name           = "omap3-rom-rng",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = omap3_rom_rng_probe,
+       .remove         = omap3_rom_rng_remove,
+};
+
+module_platform_driver(omap3_rom_rng_driver);
+
+MODULE_ALIAS("platform:omap3-rom-rng");
+MODULE_AUTHOR("Juha Yrjola");
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
+MODULE_LICENSE("GPL");
index b761459a3436c25d31321f5bb46037f7faaf9292..ab7ffdec0ec3545a7ec6f940b32cff396d153183 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/hw_random.h>
 #include <asm/vio.h>
 
-#define MODULE_NAME "pseries-rng"
 
 static int pseries_rng_data_read(struct hwrng *rng, u32 *data)
 {
@@ -55,7 +54,7 @@ static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev)
 };
 
 static struct hwrng pseries_rng = {
-       .name           = MODULE_NAME,
+       .name           = KBUILD_MODNAME,
        .data_read      = pseries_rng_data_read,
 };
 
@@ -78,7 +77,7 @@ static struct vio_device_id pseries_rng_driver_ids[] = {
 MODULE_DEVICE_TABLE(vio, pseries_rng_driver_ids);
 
 static struct vio_driver pseries_rng_driver = {
-       .name = MODULE_NAME,
+       .name = KBUILD_MODNAME,
        .probe = pseries_rng_probe,
        .remove = pseries_rng_remove,
        .get_desired_dma = pseries_rng_get_desired_dma,
index e737772ad69a8103312e596cd0e24ce00d759e22..de5a6dcfb3e242ec4aa5b6742c73c7700e32d551 100644 (file)
@@ -221,7 +221,7 @@ static void __exit mod_exit(void)
 module_init(mod_init);
 module_exit(mod_exit);
 
-static struct x86_cpu_id via_rng_cpu_id[] = {
+static struct x86_cpu_id __maybe_unused via_rng_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_XSTORE),
        {}
 };
index 40cc0cf2ded639f6b4e3f28cfb1b093660c19ae1..e6939e13e3388e0b05132f72320d8eec0c757a57 100644 (file)
@@ -664,6 +664,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
                },
        },
+       {
+               .ident = "Dell XPS421",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+               },
+       },
         { }
 };
 
index 7be41e676a6470ab02b0bfd52867f54561a7960d..00a3abe103a5ac472dfb352a1bb0cec42cd29ddb 100644 (file)
@@ -60,7 +60,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
        int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap,
+       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
                                S2MPS11_REG_RTC_CTRL,
                                 s2mps11->mask, s2mps11->mask);
        if (!ret)
@@ -74,7 +74,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
        int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
+       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL,
                           s2mps11->mask, ~s2mps11->mask);
 
        if (!ret)
@@ -174,7 +174,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                s2mps11_clk->hw.init = &s2mps11_clks_init[i];
                s2mps11_clk->mask = 1 << i;
 
-               ret = regmap_read(s2mps11_clk->iodev->regmap,
+               ret = regmap_read(s2mps11_clk->iodev->regmap_pmic,
                                  S2MPS11_REG_RTC_CTRL, &val);
                if (ret < 0)
                        goto err_reg;
index 7d2c84265947a1b2e85ebf92c8c6e9cb8d9303f8..8e27aee6887eed36c2ebaf7c82bd705672ab5784 100644 (file)
@@ -331,8 +331,8 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
        ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
        ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
        ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
-       ALIAS(HCLK_DMA1, NULL, "dma1"),
-       ALIAS(HCLK_DMA0, NULL, "dma0"),
+       ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
+       ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
        ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
        ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
        ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
index bdb953e15d2a88d201c3997ca86e80f15a00e5cf..634c4d6dd45a489384d4c6b293e56f0fcc2ba331 100644 (file)
@@ -75,6 +75,7 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 config CLKSRC_EFM32
        bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32
        depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
+       select CLKSRC_MMIO
        default ARCH_EFM32
        help
          Support to use the timers of EFM32 SoCs as clock source and clock
@@ -87,6 +88,7 @@ config ARM_ARCH_TIMER
 config ARM_ARCH_TIMER_EVTSTREAM
        bool "Support for ARM architected timer event stream generation"
        default y if ARM_ARCH_TIMER
+       depends on ARM_ARCH_TIMER
        help
          This option enables support for event stream generation based on
          the ARM architected timer. It is used for waking up CPUs executing
index 35639cf4e5a208af89c9b692eae32227bcefc5d3..b9ddd9e3a2f599e2cc7424c1eac18d4280b2f850 100644 (file)
@@ -35,6 +35,5 @@ void __init clocksource_of_init(void)
 
                init_func = match->data;
                init_func(np);
-               of_node_put(np);
        }
 }
index 45ba8aecc7298428016dd6d5601482362cce0c4e..2a2ea2717f3ac94dfba2fdd6a986c4630556e7da 100644 (file)
@@ -108,12 +108,11 @@ static void __init add_clocksource(struct device_node *source_timer)
 
 static u64 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base);
 }
 
 static const struct of_device_id sptimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-rtc" },
-       { .compatible = "snps,dw-apb-timer-sp" },
        { /* Sentinel */ },
 };
 
@@ -151,4 +150,6 @@ static void __init dw_apb_timer_init(struct device_node *timer)
        num_called++;
 }
 CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
index 4aac9ee0d0c054a7ba953b17ac3272946af7b47d..3cf12834681e8335fa7f49dd032eb3cb57ad128a 100644 (file)
@@ -313,8 +313,20 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
                goto err1;
        }
 
-       return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
-                               cfg->clockevent_rating);
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err2;
+
+       ret = sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
+                              cfg->clockevent_rating);
+       if (ret < 0)
+               goto err3;
+
+       return 0;
+ err3:
+       clk_unprepare(p->clk);
+ err2:
+       clk_put(p->clk);
  err1:
        iounmap(p->mapbase);
  err0:
index 78b8dae49628cce42fb45ebdff2b32ece5045a52..63557cda0a7d599e352c402f2db23b348481e365 100644 (file)
@@ -472,12 +472,26 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
                ret = PTR_ERR(p->clk);
                goto err1;
        }
+
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err2;
+
        p->cs_enabled = false;
        p->enable_count = 0;
 
-       return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
-                              cfg->clockevent_rating,
-                              cfg->clocksource_rating);
+       ret = sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
+                             cfg->clockevent_rating,
+                             cfg->clocksource_rating);
+       if (ret < 0)
+               goto err3;
+
+       return 0;
+
+ err3:
+       clk_unprepare(p->clk);
+ err2:
+       clk_put(p->clk);
  err1:
        iounmap(p->mapbase);
  err0:
index 2fb4695a28d83e2e0f26c1e787b0c575612c650c..a4f6119aafd814efe2839f416bbe8fe99bc41554 100644 (file)
@@ -179,6 +179,9 @@ static void __init sun4i_timer_init(struct device_node *node)
        writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
               timer_base + TIMER_CTL_REG(0));
 
+       /* Make sure timer is stopped before playing with interrupts */
+       sun4i_clkevt_time_stop(0);
+
        ret = setup_irq(irq, &sun4i_timer_irq);
        if (ret)
                pr_warn("failed to setup irq %d\n", irq);
index d8e47e5027858faf9f99c0b3ad99883bd7bc9cc2..4e7f6802e840ba9379eb42d733801526d173e89e 100644 (file)
@@ -255,11 +255,6 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
 
        ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
 
-       /*
-        * Set scale and timer for sched_clock.
-        */
-       sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
-
        /*
         * Setup free-running clocksource timer (interrupts
         * disabled).
@@ -270,6 +265,11 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
        timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN |
                             TIMER0_DIV(TIMER_DIVIDER_SHIFT));
 
+       /*
+        * Set scale and timer for sched_clock.
+        */
+       sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
+
        clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
                              "armada_370_xp_clocksource",
                              timer_clk, 300, 32, clocksource_mmio_readl_down);
index 856ad80418ae5b92610e23e98922f0ff6505d34e..7c03dd84f66a35cabbde683eece8e23f73585743 100644 (file)
@@ -58,7 +58,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
        return 0;
 }
 
-static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
+static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
        unsigned int frequency, rate, min_freq;
        int retval, steps, i;
index 02d534da22dda0bb22277c4f80f7c1d27f24cd65..16d7b4ac94be21210779cd7c87d9440a78666162 100644 (file)
@@ -828,6 +828,12 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
        int ret = 0;
 
        memcpy(&new_policy, policy, sizeof(*policy));
+
+       /* Use the default policy if its valid. */
+       if (cpufreq_driver->setpolicy)
+               cpufreq_parse_governor(policy->governor->name,
+                                       &new_policy.policy, NULL);
+
        /* assure that the starting sequence is run in cpufreq_set_policy */
        policy->governor = NULL;
 
@@ -845,8 +851,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
 
 #ifdef CONFIG_HOTPLUG_CPU
 static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
-                                 unsigned int cpu, struct device *dev,
-                                 bool frozen)
+                                 unsigned int cpu, struct device *dev)
 {
        int ret = 0;
        unsigned long flags;
@@ -877,11 +882,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
                }
        }
 
-       /* Don't touch sysfs links during light-weight init */
-       if (!frozen)
-               ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
-
-       return ret;
+       return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
 }
 #endif
 
@@ -926,6 +927,27 @@ err_free_policy:
        return NULL;
 }
 
+static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
+{
+       struct kobject *kobj;
+       struct completion *cmp;
+
+       down_read(&policy->rwsem);
+       kobj = &policy->kobj;
+       cmp = &policy->kobj_unregister;
+       up_read(&policy->rwsem);
+       kobject_put(kobj);
+
+       /*
+        * We need to make sure that the underlying kobj is
+        * actually not referenced anymore by anybody before we
+        * proceed with unloading.
+        */
+       pr_debug("waiting for dropping of refcount\n");
+       wait_for_completion(cmp);
+       pr_debug("wait complete\n");
+}
+
 static void cpufreq_policy_free(struct cpufreq_policy *policy)
 {
        free_cpumask_var(policy->related_cpus);
@@ -986,7 +1008,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
                if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
                        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
+                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
                        up_read(&cpufreq_rwsem);
                        return ret;
                }
@@ -1096,7 +1118,10 @@ err_get_freq:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 err_set_policy_cpu:
+       if (frozen)
+               cpufreq_policy_put_kobj(policy);
        cpufreq_policy_free(policy);
+
 nomem_out:
        up_read(&cpufreq_rwsem);
 
@@ -1118,7 +1143,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 }
 
 static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
-                                          unsigned int old_cpu, bool frozen)
+                                          unsigned int old_cpu)
 {
        struct device *cpu_dev;
        int ret;
@@ -1126,10 +1151,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        /* first sibling now owns the new sysfs dir */
        cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
 
-       /* Don't touch sysfs files during light-weight tear-down */
-       if (frozen)
-               return cpu_dev->id;
-
        sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
        ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
        if (ret) {
@@ -1196,7 +1217,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                if (!frozen)
                        sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
-               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
+               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
                if (new_cpu >= 0) {
                        update_policy_cpu(policy, new_cpu);
 
@@ -1218,8 +1239,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
        int ret;
        unsigned long flags;
        struct cpufreq_policy *policy;
-       struct kobject *kobj;
-       struct completion *cmp;
 
        read_lock_irqsave(&cpufreq_driver_lock, flags);
        policy = per_cpu(cpufreq_cpu_data, cpu);
@@ -1249,22 +1268,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                        }
                }
 
-               if (!frozen) {
-                       down_read(&policy->rwsem);
-                       kobj = &policy->kobj;
-                       cmp = &policy->kobj_unregister;
-                       up_read(&policy->rwsem);
-                       kobject_put(kobj);
-
-                       /*
-                        * We need to make sure that the underlying kobj is
-                        * actually not referenced anymore by anybody before we
-                        * proceed with unloading.
-                        */
-                       pr_debug("waiting for dropping of refcount\n");
-                       wait_for_completion(cmp);
-                       pr_debug("wait complete\n");
-               }
+               if (!frozen)
+                       cpufreq_policy_put_kobj(policy);
 
                /*
                 * Perform the ->exit() even during light-weight tear-down,
index f2c75065ce198694428d631baef388ad8e9aa6c6..dfd1643b0b2ff86f229b8e8726fee437c3e1e618 100644 (file)
@@ -157,4 +157,3 @@ err_moutcore:
        pr_debug("%s: failed initialization\n", __func__);
        return -EINVAL;
 }
-EXPORT_SYMBOL(exynos4210_cpufreq_init);
index 8683304ce62cc4dba0c947e2be6049e1b94ffcaf..efad5e657f6f95d9729b33469b2a3f018eaa798c 100644 (file)
@@ -211,4 +211,3 @@ err_moutcore:
        pr_debug("%s: failed initialization\n", __func__);
        return -EINVAL;
 }
-EXPORT_SYMBOL(exynos4x12_cpufreq_init);
index 9fae466d7746a5fed781edb17f4838b6931ed8f0..8feda86fe42c5b5b86c5ac53b02c4d47216fd101 100644 (file)
@@ -236,4 +236,3 @@ err_moutcore:
        pr_err("%s: failed initialization\n", __func__);
        return -EINVAL;
 }
-EXPORT_SYMBOL(exynos5250_cpufreq_init);
index f42df7ec03c53a00838839861567de2e0d8060fa..b7309c37033d57b64d37ca3b93354f0b2848102d 100644 (file)
@@ -142,10 +142,8 @@ static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
 
        mutex_lock(&tegra_cpu_lock);
 
-       if (is_suspended) {
-               ret = -EBUSY;
+       if (is_suspended)
                goto out;
-       }
 
        freq = freq_table[index].frequency;
 
index 2a991e468f78190e1dfab933225d33cfef69d710..a55e68f2cfc8bfad02a85957c9d9ddc55823c6fe 100644 (file)
@@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-       if (dev->registered == 0)
+       if (!dev || dev->registered == 0)
                return;
 
        cpuidle_pause_and_lock();
index ca89f6b84b068c1ecc770eededee50bf8c1d55aa..e7555ff4cafdb4b0444a09f2de4b2b153f9e78e9 100644 (file)
@@ -4,16 +4,29 @@ config CRYPTO_DEV_FSL_CAAM
        help
          Enables the driver module for Freescale's Cryptographic Accelerator
          and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
-         This module adds a job ring operation interface, and configures h/w
+         This module creates job ring devices, and configures h/w
          to operate as a DPAA component automatically, depending
          on h/w feature availability.
 
          To compile this driver as a module, choose M here: the module
          will be called caam.
 
+config CRYPTO_DEV_FSL_CAAM_JR
+       tristate "Freescale CAAM Job Ring driver backend"
+       depends on CRYPTO_DEV_FSL_CAAM
+       default y
+       help
+         Enables the driver module for Job Rings which are part of
+         Freescale's Cryptographic Accelerator
+         and Assurance Module (CAAM). This module adds a job ring operation
+         interface.
+
+         To compile this driver as a module, choose M here: the module
+         will be called caam_jr.
+
 config CRYPTO_DEV_FSL_CAAM_RINGSIZE
        int "Job Ring size"
-       depends on CRYPTO_DEV_FSL_CAAM
+       depends on CRYPTO_DEV_FSL_CAAM_JR
        range 2 9
        default "9"
        help
@@ -31,7 +44,7 @@ config CRYPTO_DEV_FSL_CAAM_RINGSIZE
 
 config CRYPTO_DEV_FSL_CAAM_INTC
        bool "Job Ring interrupt coalescing"
-       depends on CRYPTO_DEV_FSL_CAAM
+       depends on CRYPTO_DEV_FSL_CAAM_JR
        default n
        help
          Enable the Job Ring's interrupt coalescing feature.
@@ -62,7 +75,7 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD
 
 config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
        tristate "Register algorithm implementations with the Crypto API"
-       depends on CRYPTO_DEV_FSL_CAAM
+       depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
        default y
        select CRYPTO_ALGAPI
        select CRYPTO_AUTHENC
@@ -76,7 +89,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
 
 config CRYPTO_DEV_FSL_CAAM_AHASH_API
        tristate "Register hash algorithm implementations with Crypto API"
-       depends on CRYPTO_DEV_FSL_CAAM
+       depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
        default y
        select CRYPTO_HASH
        help
@@ -88,7 +101,7 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
 
 config CRYPTO_DEV_FSL_CAAM_RNG_API
        tristate "Register caam device for hwrng API"
-       depends on CRYPTO_DEV_FSL_CAAM
+       depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
        default y
        select CRYPTO_RNG
        select HW_RANDOM
index d56bd0ec65d877ca9f2989ad77173214cc537868..550758a333e7c8e920a422da0cc20fc8807476d1 100644 (file)
@@ -6,8 +6,10 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y)
 endif
 
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 
-caam-objs := ctrl.o jr.o error.o key_gen.o
+caam-objs := ctrl.o
+caam_jr-objs := jr.o key_gen.o error.o
index 7c63b72ecd750f381fef66e8baccc7955351b1b3..4cf5dec826e1e283aa8b5991cd1a4b80a0dbdba6 100644 (file)
@@ -86,6 +86,7 @@
 #else
 #define debug(format, arg...)
 #endif
+static struct list_head alg_list;
 
 /* Set DK bit in class 1 operation if shared */
 static inline void append_dec_op1(u32 *desc, u32 type)
@@ -817,7 +818,7 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
                       ivsize, 1);
        print_hex_dump(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
-                      req->cryptlen, 1);
+                      req->cryptlen - ctx->authsize, 1);
 #endif
 
        if (err) {
@@ -971,12 +972,9 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
                                 (edesc->src_nents ? : 1);
                in_options = LDST_SGF;
        }
-       if (encrypt)
-               append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                                 req->cryptlen - authsize, in_options);
-       else
-               append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                                 req->cryptlen, in_options);
+
+       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+                         in_options);
 
        if (likely(req->src == req->dst)) {
                if (all_contig) {
@@ -997,7 +995,8 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
                }
        }
        if (encrypt)
-               append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+               append_seq_out_ptr(desc, dst_dma, req->cryptlen + authsize,
+                                  out_options);
        else
                append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
                                   out_options);
@@ -1047,8 +1046,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
                sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents;
                in_options = LDST_SGF;
        }
-       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                         req->cryptlen - authsize, in_options);
+       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+                         in_options);
 
        if (contig & GIV_DST_CONTIG) {
                dst_dma = edesc->iv_dma;
@@ -1065,7 +1064,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
                }
        }
 
-       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options);
+       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen + authsize,
+                          out_options);
 }
 
 /*
@@ -1129,7 +1129,8 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
  * allocate and map the aead extended descriptor
  */
 static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
-                                          int desc_bytes, bool *all_contig_ptr)
+                                          int desc_bytes, bool *all_contig_ptr,
+                                          bool encrypt)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
        struct caam_ctx *ctx = crypto_aead_ctx(aead);
@@ -1144,12 +1145,22 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
        bool assoc_chained = false, src_chained = false, dst_chained = false;
        int ivsize = crypto_aead_ivsize(aead);
        int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
+       unsigned int authsize = ctx->authsize;
 
        assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
-       src_nents = sg_count(req->src, req->cryptlen, &src_chained);
 
-       if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+       if (unlikely(req->dst != req->src)) {
+               src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+               dst_nents = sg_count(req->dst,
+                                    req->cryptlen +
+                                       (encrypt ? authsize : (-authsize)),
+                                    &dst_chained);
+       } else {
+               src_nents = sg_count(req->src,
+                                    req->cryptlen +
+                                       (encrypt ? authsize : 0),
+                                    &src_chained);
+       }
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
                                 DMA_TO_DEVICE, assoc_chained);
@@ -1233,11 +1244,9 @@ static int aead_encrypt(struct aead_request *req)
        u32 *desc;
        int ret = 0;
 
-       req->cryptlen += ctx->authsize;
-
        /* allocate extended descriptor */
        edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                CAAM_CMD_SZ, &all_contig);
+                                CAAM_CMD_SZ, &all_contig, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1274,7 +1283,7 @@ static int aead_decrypt(struct aead_request *req)
 
        /* allocate extended descriptor */
        edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                CAAM_CMD_SZ, &all_contig);
+                                CAAM_CMD_SZ, &all_contig, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1331,7 +1340,8 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
        src_nents = sg_count(req->src, req->cryptlen, &src_chained);
 
        if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+               dst_nents = sg_count(req->dst, req->cryptlen + ctx->authsize,
+                                    &dst_chained);
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
                                 DMA_TO_DEVICE, assoc_chained);
@@ -1425,8 +1435,6 @@ static int aead_givencrypt(struct aead_givcrypt_request *areq)
        u32 *desc;
        int ret = 0;
 
-       req->cryptlen += ctx->authsize;
-
        /* allocate extended descriptor */
        edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
                                     CAAM_CMD_SZ, &contig);
@@ -2057,7 +2065,6 @@ static struct caam_alg_template driver_algs[] = {
 
 struct caam_crypto_alg {
        struct list_head entry;
-       struct device *ctrldev;
        int class1_alg_type;
        int class2_alg_type;
        int alg_op;
@@ -2070,14 +2077,12 @@ static int caam_cra_init(struct crypto_tfm *tfm)
        struct caam_crypto_alg *caam_alg =
                 container_of(alg, struct caam_crypto_alg, crypto_alg);
        struct caam_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct caam_drv_private *priv = dev_get_drvdata(caam_alg->ctrldev);
-       int tgt_jr = atomic_inc_return(&priv->tfm_count);
 
-       /*
-        * distribute tfms across job rings to ensure in-order
-        * crypto request processing per tfm
-        */
-       ctx->jrdev = priv->jrdev[(tgt_jr / 2) % priv->total_jobrs];
+       ctx->jrdev = caam_jr_alloc();
+       if (IS_ERR(ctx->jrdev)) {
+               pr_err("Job Ring Device allocation for transform failed\n");
+               return PTR_ERR(ctx->jrdev);
+       }
 
        /* copy descriptor header template value */
        ctx->class1_alg_type = OP_TYPE_CLASS1_ALG | caam_alg->class1_alg_type;
@@ -2104,44 +2109,26 @@ static void caam_cra_exit(struct crypto_tfm *tfm)
                dma_unmap_single(ctx->jrdev, ctx->sh_desc_givenc_dma,
                                 desc_bytes(ctx->sh_desc_givenc),
                                 DMA_TO_DEVICE);
+
+       caam_jr_free(ctx->jrdev);
 }
 
 static void __exit caam_algapi_exit(void)
 {
 
-       struct device_node *dev_node;
-       struct platform_device *pdev;
-       struct device *ctrldev;
-       struct caam_drv_private *priv;
        struct caam_crypto_alg *t_alg, *n;
 
-       dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-       if (!dev_node) {
-               dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-               if (!dev_node)
-                       return;
-       }
-
-       pdev = of_find_device_by_node(dev_node);
-       if (!pdev)
-               return;
-
-       ctrldev = &pdev->dev;
-       of_node_put(dev_node);
-       priv = dev_get_drvdata(ctrldev);
-
-       if (!priv->alg_list.next)
+       if (!alg_list.next)
                return;
 
-       list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
+       list_for_each_entry_safe(t_alg, n, &alg_list, entry) {
                crypto_unregister_alg(&t_alg->crypto_alg);
                list_del(&t_alg->entry);
                kfree(t_alg);
        }
 }
 
-static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
-                                             struct caam_alg_template
+static struct caam_crypto_alg *caam_alg_alloc(struct caam_alg_template
                                              *template)
 {
        struct caam_crypto_alg *t_alg;
@@ -2149,7 +2136,7 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
 
        t_alg = kzalloc(sizeof(struct caam_crypto_alg), GFP_KERNEL);
        if (!t_alg) {
-               dev_err(ctrldev, "failed to allocate t_alg\n");
+               pr_err("failed to allocate t_alg\n");
                return ERR_PTR(-ENOMEM);
        }
 
@@ -2181,62 +2168,39 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
        t_alg->class1_alg_type = template->class1_alg_type;
        t_alg->class2_alg_type = template->class2_alg_type;
        t_alg->alg_op = template->alg_op;
-       t_alg->ctrldev = ctrldev;
 
        return t_alg;
 }
 
 static int __init caam_algapi_init(void)
 {
-       struct device_node *dev_node;
-       struct platform_device *pdev;
-       struct device *ctrldev;
-       struct caam_drv_private *priv;
        int i = 0, err = 0;
 
-       dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-       if (!dev_node) {
-               dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-               if (!dev_node)
-                       return -ENODEV;
-       }
-
-       pdev = of_find_device_by_node(dev_node);
-       if (!pdev)
-               return -ENODEV;
-
-       ctrldev = &pdev->dev;
-       priv = dev_get_drvdata(ctrldev);
-       of_node_put(dev_node);
-
-       INIT_LIST_HEAD(&priv->alg_list);
-
-       atomic_set(&priv->tfm_count, -1);
+       INIT_LIST_HEAD(&alg_list);
 
        /* register crypto algorithms the device supports */
        for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
                /* TODO: check if h/w supports alg */
                struct caam_crypto_alg *t_alg;
 
-               t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
+               t_alg = caam_alg_alloc(&driver_algs[i]);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
-                       dev_warn(ctrldev, "%s alg allocation failed\n",
-                                driver_algs[i].driver_name);
+                       pr_warn("%s alg allocation failed\n",
+                               driver_algs[i].driver_name);
                        continue;
                }
 
                err = crypto_register_alg(&t_alg->crypto_alg);
                if (err) {
-                       dev_warn(ctrldev, "%s alg registration failed\n",
+                       pr_warn("%s alg registration failed\n",
                                t_alg->crypto_alg.cra_driver_name);
                        kfree(t_alg);
                } else
-                       list_add_tail(&t_alg->entry, &priv->alg_list);
+                       list_add_tail(&t_alg->entry, &alg_list);
        }
-       if (!list_empty(&priv->alg_list))
-               dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
-                        (char *)of_get_property(dev_node, "compatible", NULL));
+       if (!list_empty(&alg_list))
+               pr_info("caam algorithms registered in /proc/crypto\n");
 
        return err;
 }
index e732bd962e98cc715db6463c7587dbb2511707e3..0378328f47a775b368b795cd3d7adc9b678fd31b 100644 (file)
@@ -94,6 +94,9 @@
 #define debug(format, arg...)
 #endif
 
+
+static struct list_head hash_list;
+
 /* ahash per-session context */
 struct caam_hash_ctx {
        struct device *jrdev;
@@ -1653,7 +1656,6 @@ static struct caam_hash_template driver_hash[] = {
 
 struct caam_hash_alg {
        struct list_head entry;
-       struct device *ctrldev;
        int alg_type;
        int alg_op;
        struct ahash_alg ahash_alg;
@@ -1670,7 +1672,6 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
        struct caam_hash_alg *caam_hash =
                 container_of(alg, struct caam_hash_alg, ahash_alg);
        struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct caam_drv_private *priv = dev_get_drvdata(caam_hash->ctrldev);
        /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
        static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
                                         HASH_MSG_LEN + SHA1_DIGEST_SIZE,
@@ -1678,15 +1679,17 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
                                         HASH_MSG_LEN + SHA256_DIGEST_SIZE,
                                         HASH_MSG_LEN + 64,
                                         HASH_MSG_LEN + SHA512_DIGEST_SIZE };
-       int tgt_jr = atomic_inc_return(&priv->tfm_count);
        int ret = 0;
 
        /*
-        * distribute tfms across job rings to ensure in-order
+        * Get a Job ring from Job Ring driver to ensure in-order
         * crypto request processing per tfm
         */
-       ctx->jrdev = priv->jrdev[tgt_jr % priv->total_jobrs];
-
+       ctx->jrdev = caam_jr_alloc();
+       if (IS_ERR(ctx->jrdev)) {
+               pr_err("Job Ring Device allocation for transform failed\n");
+               return PTR_ERR(ctx->jrdev);
+       }
        /* copy descriptor header template value */
        ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
        ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_hash->alg_op;
@@ -1729,35 +1732,18 @@ static void caam_hash_cra_exit(struct crypto_tfm *tfm)
            !dma_mapping_error(ctx->jrdev, ctx->sh_desc_finup_dma))
                dma_unmap_single(ctx->jrdev, ctx->sh_desc_finup_dma,
                                 desc_bytes(ctx->sh_desc_finup), DMA_TO_DEVICE);
+
+       caam_jr_free(ctx->jrdev);
 }
 
 static void __exit caam_algapi_hash_exit(void)
 {
-       struct device_node *dev_node;
-       struct platform_device *pdev;
-       struct device *ctrldev;
-       struct caam_drv_private *priv;
        struct caam_hash_alg *t_alg, *n;
 
-       dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-       if (!dev_node) {
-               dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-               if (!dev_node)
-                       return;
-       }
-
-       pdev = of_find_device_by_node(dev_node);
-       if (!pdev)
+       if (!hash_list.next)
                return;
 
-       ctrldev = &pdev->dev;
-       of_node_put(dev_node);
-       priv = dev_get_drvdata(ctrldev);
-
-       if (!priv->hash_list.next)
-               return;
-
-       list_for_each_entry_safe(t_alg, n, &priv->hash_list, entry) {
+       list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
                crypto_unregister_ahash(&t_alg->ahash_alg);
                list_del(&t_alg->entry);
                kfree(t_alg);
@@ -1765,7 +1751,7 @@ static void __exit caam_algapi_hash_exit(void)
 }
 
 static struct caam_hash_alg *
-caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
+caam_hash_alloc(struct caam_hash_template *template,
                bool keyed)
 {
        struct caam_hash_alg *t_alg;
@@ -1774,7 +1760,7 @@ caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
 
        t_alg = kzalloc(sizeof(struct caam_hash_alg), GFP_KERNEL);
        if (!t_alg) {
-               dev_err(ctrldev, "failed to allocate t_alg\n");
+               pr_err("failed to allocate t_alg\n");
                return ERR_PTR(-ENOMEM);
        }
 
@@ -1805,37 +1791,15 @@ caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
 
        t_alg->alg_type = template->alg_type;
        t_alg->alg_op = template->alg_op;
-       t_alg->ctrldev = ctrldev;
 
        return t_alg;
 }
 
 static int __init caam_algapi_hash_init(void)
 {
-       struct device_node *dev_node;
-       struct platform_device *pdev;
-       struct device *ctrldev;
-       struct caam_drv_private *priv;
        int i = 0, err = 0;
 
-       dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-       if (!dev_node) {
-               dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-               if (!dev_node)
-                       return -ENODEV;
-       }
-
-       pdev = of_find_device_by_node(dev_node);
-       if (!pdev)
-               return -ENODEV;
-
-       ctrldev = &pdev->dev;
-       priv = dev_get_drvdata(ctrldev);
-       of_node_put(dev_node);
-
-       INIT_LIST_HEAD(&priv->hash_list);
-
-       atomic_set(&priv->tfm_count, -1);
+       INIT_LIST_HEAD(&hash_list);
 
        /* register crypto algorithms the device supports */
        for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
@@ -1843,38 +1807,38 @@ static int __init caam_algapi_hash_init(void)
                struct caam_hash_alg *t_alg;
 
                /* register hmac version */
-               t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], true);
+               t_alg = caam_hash_alloc(&driver_hash[i], true);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
-                       dev_warn(ctrldev, "%s alg allocation failed\n",
-                                driver_hash[i].driver_name);
+                       pr_warn("%s alg allocation failed\n",
+                               driver_hash[i].driver_name);
                        continue;
                }
 
                err = crypto_register_ahash(&t_alg->ahash_alg);
                if (err) {
-                       dev_warn(ctrldev, "%s alg registration failed\n",
+                       pr_warn("%s alg registration failed\n",
                                t_alg->ahash_alg.halg.base.cra_driver_name);
                        kfree(t_alg);
                } else
-                       list_add_tail(&t_alg->entry, &priv->hash_list);
+                       list_add_tail(&t_alg->entry, &hash_list);
 
                /* register unkeyed version */
-               t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], false);
+               t_alg = caam_hash_alloc(&driver_hash[i], false);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
-                       dev_warn(ctrldev, "%s alg allocation failed\n",
-                                driver_hash[i].driver_name);
+                       pr_warn("%s alg allocation failed\n",
+                               driver_hash[i].driver_name);
                        continue;
                }
 
                err = crypto_register_ahash(&t_alg->ahash_alg);
                if (err) {
-                       dev_warn(ctrldev, "%s alg registration failed\n",
+                       pr_warn("%s alg registration failed\n",
                                t_alg->ahash_alg.halg.base.cra_driver_name);
                        kfree(t_alg);
                } else
-                       list_add_tail(&t_alg->entry, &priv->hash_list);
+                       list_add_tail(&t_alg->entry, &hash_list);
        }
 
        return err;
index d1939a9539c06a4204a26b65d3d743d46c2346d3..28486b19fc36b3e837d774ace08a3aa041b8d1e7 100644 (file)
@@ -273,34 +273,23 @@ static struct hwrng caam_rng = {
 
 static void __exit caam_rng_exit(void)
 {
+       caam_jr_free(rng_ctx.jrdev);
        hwrng_unregister(&caam_rng);
 }
 
 static int __init caam_rng_init(void)
 {
-       struct device_node *dev_node;
-       struct platform_device *pdev;
-       struct device *ctrldev;
-       struct caam_drv_private *priv;
-
-       dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-       if (!dev_node) {
-               dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
-               if (!dev_node)
-                       return -ENODEV;
-       }
-
-       pdev = of_find_device_by_node(dev_node);
-       if (!pdev)
-               return -ENODEV;
+       struct device *dev;
 
-       ctrldev = &pdev->dev;
-       priv = dev_get_drvdata(ctrldev);
-       of_node_put(dev_node);
+       dev = caam_jr_alloc();
+       if (IS_ERR(dev)) {
+               pr_err("Job Ring Device allocation for transform failed\n");
+               return PTR_ERR(dev);
+       }
 
-       caam_init_rng(&rng_ctx, priv->jrdev[0]);
+       caam_init_rng(&rng_ctx, dev);
 
-       dev_info(priv->jrdev[0], "registering rng-caam\n");
+       dev_info(dev, "registering rng-caam\n");
        return hwrng_register(&caam_rng);
 }
 
index bc6d820812b6a73e83c6596caa48ae7d475c315a..63fb1af2c43187fe398663869b5877fa16bf8834 100644 (file)
 #include "error.h"
 #include "ctrl.h"
 
-static int caam_remove(struct platform_device *pdev)
-{
-       struct device *ctrldev;
-       struct caam_drv_private *ctrlpriv;
-       struct caam_drv_private_jr *jrpriv;
-       struct caam_full __iomem *topregs;
-       int ring, ret = 0;
-
-       ctrldev = &pdev->dev;
-       ctrlpriv = dev_get_drvdata(ctrldev);
-       topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
-
-       /* shut down JobRs */
-       for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
-               ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]);
-               jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]);
-               irq_dispose_mapping(jrpriv->irq);
-       }
-
-       /* Shut down debug views */
-#ifdef CONFIG_DEBUG_FS
-       debugfs_remove_recursive(ctrlpriv->dfs_root);
-#endif
-
-       /* Unmap controller region */
-       iounmap(&topregs->ctrl);
-
-       kfree(ctrlpriv->jrdev);
-       kfree(ctrlpriv);
-
-       return ret;
-}
-
 /*
  * Descriptor to instantiate RNG State Handle 0 in normal mode and
  * load the JDKEK, TDKEK and TDSK registers
  */
-static void build_instantiation_desc(u32 *desc)
+static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
 {
-       u32 *jump_cmd;
+       u32 *jump_cmd, op_flags;
 
        init_job_desc(desc, 0);
 
+       op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+                       (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
+
        /* INIT RNG in non-test mode */
-       append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
-                        OP_ALG_AS_INIT);
+       append_operation(desc, op_flags);
+
+       if (!handle && do_sk) {
+               /*
+                * For SH0, Secure Keys must be generated as well
+                */
+
+               /* wait for done */
+               jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+               set_jump_tgt_here(desc, jump_cmd);
+
+               /*
+                * load 1 to clear written reg:
+                * resets the done interrrupt and returns the RNG to idle.
+                */
+               append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+               /* Initialize State Handle  */
+               append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+                                OP_ALG_AAI_RNG4_SK);
+       }
 
-       /* wait for done */
-       jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
-       set_jump_tgt_here(desc, jump_cmd);
+       append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
 
-       /*
-        * load 1 to clear written reg:
-        * resets the done interrupt and returns the RNG to idle.
-        */
-       append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
+static void build_deinstantiation_desc(u32 *desc, int handle)
+{
+       init_job_desc(desc, 0);
 
-       /* generate secure keys (non-test) */
+       /* Uninstantiate State Handle 0 */
        append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
-                        OP_ALG_RNG4_SK);
+                        (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
+
+       append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
 }
 
-static int instantiate_rng(struct device *ctrldev)
+/*
+ * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
+ *                       the software (no JR/QI used).
+ * @ctrldev - pointer to device
+ * @status - descriptor status, after being run
+ *
+ * Return: - 0 if no error occurred
+ *        - -ENODEV if the DECO couldn't be acquired
+ *        - -EAGAIN if an error occurred while executing the descriptor
+ */
+static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
+                                       u32 *status)
 {
        struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
        struct caam_full __iomem *topregs;
        unsigned int timeout = 100000;
-       u32 *desc;
-       int i, ret = 0;
-
-       desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
-       if (!desc) {
-               dev_err(ctrldev, "can't allocate RNG init descriptor memory\n");
-               return -ENOMEM;
-       }
-       build_instantiation_desc(desc);
+       u32 deco_dbg_reg, flags;
+       int i;
 
        /* Set the bit to request direct access to DECO0 */
        topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
@@ -103,36 +96,219 @@ static int instantiate_rng(struct device *ctrldev)
 
        if (!timeout) {
                dev_err(ctrldev, "failed to acquire DECO 0\n");
-               ret = -EIO;
-               goto out;
+               clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
+               return -ENODEV;
        }
 
        for (i = 0; i < desc_len(desc); i++)
-               topregs->deco.descbuf[i] = *(desc + i);
+               wr_reg32(&topregs->deco.descbuf[i], *(desc + i));
+
+       flags = DECO_JQCR_WHL;
+       /*
+        * If the descriptor length is longer than 4 words, then the
+        * FOUR bit in JRCTRL register must be set.
+        */
+       if (desc_len(desc) >= 4)
+               flags |= DECO_JQCR_FOUR;
 
-       wr_reg32(&topregs->deco.jr_ctl_hi, DECO_JQCR_WHL | DECO_JQCR_FOUR);
+       /* Instruct the DECO to execute it */
+       wr_reg32(&topregs->deco.jr_ctl_hi, flags);
 
        timeout = 10000000;
-       while ((rd_reg32(&topregs->deco.desc_dbg) & DECO_DBG_VALID) &&
-                                                                --timeout)
+       do {
+               deco_dbg_reg = rd_reg32(&topregs->deco.desc_dbg);
+               /*
+                * If an error occured in the descriptor, then
+                * the DECO status field will be set to 0x0D
+                */
+               if ((deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) ==
+                   DESC_DBG_DECO_STAT_HOST_ERR)
+                       break;
                cpu_relax();
+       } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout);
 
-       if (!timeout) {
-               dev_err(ctrldev, "failed to instantiate RNG\n");
-               ret = -EIO;
-       }
+       *status = rd_reg32(&topregs->deco.op_status_hi) &
+                 DECO_OP_STATUS_HI_ERR_MASK;
 
+       /* Mark the DECO as free */
        clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
-out:
+
+       if (!timeout)
+               return -EAGAIN;
+
+       return 0;
+}
+
+/*
+ * instantiate_rng - builds and executes a descriptor on DECO0,
+ *                  which initializes the RNG block.
+ * @ctrldev - pointer to device
+ * @state_handle_mask - bitmask containing the instantiation status
+ *                     for the RNG4 state handles which exist in
+ *                     the RNG4 block: 1 if it's been instantiated
+ *                     by an external entry, 0 otherwise.
+ * @gen_sk  - generate data to be loaded into the JDKEK, TDKEK and TDSK;
+ *           Caution: this can be done only once; if the keys need to be
+ *           regenerated, a POR is required
+ *
+ * Return: - 0 if no error occurred
+ *        - -ENOMEM if there isn't enough memory to allocate the descriptor
+ *        - -ENODEV if DECO0 couldn't be acquired
+ *        - -EAGAIN if an error occurred when executing the descriptor
+ *           f.i. there was a RNG hardware error due to not "good enough"
+ *           entropy being aquired.
+ */
+static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
+                          int gen_sk)
+{
+       struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+       struct caam_full __iomem *topregs;
+       struct rng4tst __iomem *r4tst;
+       u32 *desc, status, rdsta_val;
+       int ret = 0, sh_idx;
+
+       topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+       r4tst = &topregs->ctrl.r4tst[0];
+
+       desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+               /*
+                * If the corresponding bit is set, this state handle
+                * was initialized by somebody else, so it's left alone.
+                */
+               if ((1 << sh_idx) & state_handle_mask)
+                       continue;
+
+               /* Create the descriptor for instantiating RNG State Handle */
+               build_instantiation_desc(desc, sh_idx, gen_sk);
+
+               /* Try to run it through DECO0 */
+               ret = run_descriptor_deco0(ctrldev, desc, &status);
+
+               /*
+                * If ret is not 0, or descriptor status is not 0, then
+                * something went wrong. No need to try the next state
+                * handle (if available), bail out here.
+                * Also, if for some reason, the State Handle didn't get
+                * instantiated although the descriptor has finished
+                * without any error (HW optimizations for later
+                * CAAM eras), then try again.
+                */
+               rdsta_val =
+                       rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IFMASK;
+               if (status || !(rdsta_val & (1 << sh_idx)))
+                       ret = -EAGAIN;
+               if (ret)
+                       break;
+
+               dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
+               /* Clear the contents before recreating the descriptor */
+               memset(desc, 0x00, CAAM_CMD_SZ * 7);
+       }
+
        kfree(desc);
+
        return ret;
 }
 
 /*
- * By default, the TRNG runs for 200 clocks per sample;
- * 1600 clocks per sample generates better entropy.
+ * deinstantiate_rng - builds and executes a descriptor on DECO0,
+ *                    which deinitializes the RNG block.
+ * @ctrldev - pointer to device
+ * @state_handle_mask - bitmask containing the instantiation status
+ *                     for the RNG4 state handles which exist in
+ *                     the RNG4 block: 1 if it's been instantiated
+ *
+ * Return: - 0 if no error occurred
+ *        - -ENOMEM if there isn't enough memory to allocate the descriptor
+ *        - -ENODEV if DECO0 couldn't be acquired
+ *        - -EAGAIN if an error occurred when executing the descriptor
  */
-static void kick_trng(struct platform_device *pdev)
+static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
+{
+       u32 *desc, status;
+       int sh_idx, ret = 0;
+
+       desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+               /*
+                * If the corresponding bit is set, then it means the state
+                * handle was initialized by us, and thus it needs to be
+                * deintialized as well
+                */
+               if ((1 << sh_idx) & state_handle_mask) {
+                       /*
+                        * Create the descriptor for deinstantating this state
+                        * handle
+                        */
+                       build_deinstantiation_desc(desc, sh_idx);
+
+                       /* Try to run it through DECO0 */
+                       ret = run_descriptor_deco0(ctrldev, desc, &status);
+
+                       if (ret || status) {
+                               dev_err(ctrldev,
+                                       "Failed to deinstantiate RNG4 SH%d\n",
+                                       sh_idx);
+                               break;
+                       }
+                       dev_info(ctrldev, "Deinstantiated RNG4 SH%d\n", sh_idx);
+               }
+       }
+
+       kfree(desc);
+
+       return ret;
+}
+
+static int caam_remove(struct platform_device *pdev)
+{
+       struct device *ctrldev;
+       struct caam_drv_private *ctrlpriv;
+       struct caam_full __iomem *topregs;
+       int ring, ret = 0;
+
+       ctrldev = &pdev->dev;
+       ctrlpriv = dev_get_drvdata(ctrldev);
+       topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+
+       /* Remove platform devices for JobRs */
+       for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
+               if (ctrlpriv->jrpdev[ring])
+                       of_device_unregister(ctrlpriv->jrpdev[ring]);
+       }
+
+       /* De-initialize RNG state handles initialized by this driver. */
+       if (ctrlpriv->rng4_sh_init)
+               deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
+
+       /* Shut down debug views */
+#ifdef CONFIG_DEBUG_FS
+       debugfs_remove_recursive(ctrlpriv->dfs_root);
+#endif
+
+       /* Unmap controller region */
+       iounmap(&topregs->ctrl);
+
+       kfree(ctrlpriv->jrpdev);
+       kfree(ctrlpriv);
+
+       return ret;
+}
+
+/*
+ * kick_trng - sets the various parameters for enabling the initialization
+ *            of the RNG4 block in CAAM
+ * @pdev - pointer to the platform device
+ * @ent_delay - Defines the length (in system clocks) of each entropy sample.
+ */
+static void kick_trng(struct platform_device *pdev, int ent_delay)
 {
        struct device *ctrldev = &pdev->dev;
        struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
@@ -145,14 +321,31 @@ static void kick_trng(struct platform_device *pdev)
 
        /* put RNG4 into program mode */
        setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
-       /* 1600 clocks per sample */
+
+       /*
+        * Performance-wise, it does not make sense to
+        * set the delay to a value that is lower
+        * than the last one that worked (i.e. the state handles
+        * were instantiated properly. Thus, instead of wasting
+        * time trying to set the values controlling the sample
+        * frequency, the function simply returns.
+        */
+       val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
+             >> RTSDCTL_ENT_DLY_SHIFT;
+       if (ent_delay <= val) {
+               /* put RNG4 into run mode */
+               clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
+               return;
+       }
+
        val = rd_reg32(&r4tst->rtsdctl);
-       val = (val & ~RTSDCTL_ENT_DLY_MASK) | (1600 << RTSDCTL_ENT_DLY_SHIFT);
+       val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+             (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
        wr_reg32(&r4tst->rtsdctl, val);
-       /* min. freq. count */
-       wr_reg32(&r4tst->rtfrqmin, 400);
-       /* max. freq. count */
-       wr_reg32(&r4tst->rtfrqmax, 6400);
+       /* min. freq. count, equal to 1/4 of the entropy sample length */
+       wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
+       /* max. freq. count, equal to 8 times the entropy sample length */
+       wr_reg32(&r4tst->rtfrqmax, ent_delay << 3);
        /* put RNG4 into run mode */
        clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
 }
@@ -193,7 +386,7 @@ EXPORT_SYMBOL(caam_get_era);
 /* Probe routine for CAAM top (controller) level */
 static int caam_probe(struct platform_device *pdev)
 {
-       int ret, ring, rspec;
+       int ret, ring, rspec, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
        u64 caam_id;
        struct device *dev;
        struct device_node *nprop, *np;
@@ -258,8 +451,9 @@ static int caam_probe(struct platform_device *pdev)
                        rspec++;
        }
 
-       ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL);
-       if (ctrlpriv->jrdev == NULL) {
+       ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec,
+                                                               GFP_KERNEL);
+       if (ctrlpriv->jrpdev == NULL) {
                iounmap(&topregs->ctrl);
                return -ENOMEM;
        }
@@ -267,13 +461,24 @@ static int caam_probe(struct platform_device *pdev)
        ring = 0;
        ctrlpriv->total_jobrs = 0;
        for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") {
-               caam_jr_probe(pdev, np, ring);
+               ctrlpriv->jrpdev[ring] =
+                               of_platform_device_create(np, NULL, dev);
+               if (!ctrlpriv->jrpdev[ring]) {
+                       pr_warn("JR%d Platform device creation error\n", ring);
+                       continue;
+               }
                ctrlpriv->total_jobrs++;
                ring++;
        }
        if (!ring) {
                for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") {
-                       caam_jr_probe(pdev, np, ring);
+                       ctrlpriv->jrpdev[ring] =
+                               of_platform_device_create(np, NULL, dev);
+                       if (!ctrlpriv->jrpdev[ring]) {
+                               pr_warn("JR%d Platform device creation error\n",
+                                       ring);
+                               continue;
+                       }
                        ctrlpriv->total_jobrs++;
                        ring++;
                }
@@ -299,16 +504,55 @@ static int caam_probe(struct platform_device *pdev)
 
        /*
         * If SEC has RNG version >= 4 and RNG state handle has not been
-        * already instantiated ,do RNG instantiation
+        * already instantiateddo RNG instantiation
         */
-       if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4 &&
-           !(rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IF0)) {
-               kick_trng(pdev);
-               ret = instantiate_rng(dev);
+       if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4) {
+               ctrlpriv->rng4_sh_init =
+                       rd_reg32(&topregs->ctrl.r4tst[0].rdsta);
+               /*
+                * If the secure keys (TDKEK, JDKEK, TDSK), were already
+                * generated, signal this to the function that is instantiating
+                * the state handles. An error would occur if RNG4 attempts
+                * to regenerate these keys before the next POR.
+                */
+               gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
+               ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
+               do {
+                       int inst_handles =
+                               rd_reg32(&topregs->ctrl.r4tst[0].rdsta) &
+                                                               RDSTA_IFMASK;
+                       /*
+                        * If either SH were instantiated by somebody else
+                        * (e.g. u-boot) then it is assumed that the entropy
+                        * parameters are properly set and thus the function
+                        * setting these (kick_trng(...)) is skipped.
+                        * Also, if a handle was instantiated, do not change
+                        * the TRNG parameters.
+                        */
+                       if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+                               kick_trng(pdev, ent_delay);
+                               ent_delay += 400;
+                       }
+                       /*
+                        * if instantiate_rng(...) fails, the loop will rerun
+                        * and the kick_trng(...) function will modfiy the
+                        * upper and lower limits of the entropy sampling
+                        * interval, leading to a sucessful initialization of
+                        * the RNG.
+                        */
+                       ret = instantiate_rng(dev, inst_handles,
+                                             gen_sk);
+               } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
                if (ret) {
+                       dev_err(dev, "failed to instantiate RNG");
                        caam_remove(pdev);
                        return ret;
                }
+               /*
+                * Set handles init'ed by this module as the complement of the
+                * already initialized ones
+                */
+               ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
 
                /* Enable RDB bit so that RNG works faster */
                setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE);
index 53b296f78b0d2a588fe1cc3bb4bde067c05a0eda..7e4500f18df6f06de602a3d44ff6d88c4ca70ec5 100644 (file)
@@ -1155,8 +1155,15 @@ struct sec4_sg_entry {
 
 /* randomizer AAI set */
 #define OP_ALG_AAI_RNG         (0x00 << OP_ALG_AAI_SHIFT)
-#define OP_ALG_AAI_RNG_NOZERO  (0x10 << OP_ALG_AAI_SHIFT)
-#define OP_ALG_AAI_RNG_ODD     (0x20 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_NZB     (0x10 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_OBP     (0x20 << OP_ALG_AAI_SHIFT)
+
+/* RNG4 AAI set */
+#define OP_ALG_AAI_RNG4_SH_0   (0x00 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SH_1   (0x01 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_PS     (0x40 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_AI     (0x80 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SK     (0x100 << OP_ALG_AAI_SHIFT)
 
 /* hmac/smac AAI set */
 #define OP_ALG_AAI_HASH                (0x00 << OP_ALG_AAI_SHIFT)
@@ -1178,12 +1185,6 @@ struct sec4_sg_entry {
 #define OP_ALG_AAI_GSM         (0x10 << OP_ALG_AAI_SHIFT)
 #define OP_ALG_AAI_EDGE                (0x20 << OP_ALG_AAI_SHIFT)
 
-/* RNG4 set */
-#define OP_ALG_RNG4_SHIFT      4
-#define OP_ALG_RNG4_MASK       (0x1f3 << OP_ALG_RNG4_SHIFT)
-
-#define OP_ALG_RNG4_SK         (0x100 << OP_ALG_RNG4_SHIFT)
-
 #define OP_ALG_AS_SHIFT                2
 #define OP_ALG_AS_MASK         (0x3 << OP_ALG_AS_SHIFT)
 #define OP_ALG_AS_UPDATE       (0 << OP_ALG_AS_SHIFT)
index 34c4b9f7fbfae414a1578e37da245fd9119ac8fd..6d85fcc5bd0a48977467eaa058609ff882fff26e 100644 (file)
@@ -37,13 +37,16 @@ struct caam_jrentry_info {
 
 /* Private sub-storage for a single JobR */
 struct caam_drv_private_jr {
-       struct device *parentdev;       /* points back to controller dev */
-       struct platform_device *jr_pdev;/* points to platform device for JR */
+       struct list_head        list_node;      /* Job Ring device list */
+       struct device           *dev;
        int ridx;
        struct caam_job_ring __iomem *rregs;    /* JobR's register space */
        struct tasklet_struct irqtask;
        int irq;                        /* One per queue */
 
+       /* Number of scatterlist crypt transforms active on the JobR */
+       atomic_t tfm_count ____cacheline_aligned;
+
        /* Job ring info */
        int ringsize;   /* Size of rings (assume input = output) */
        struct caam_jrentry_info *entinfo;      /* Alloc'ed 1 per ring entry */
@@ -63,7 +66,7 @@ struct caam_drv_private_jr {
 struct caam_drv_private {
 
        struct device *dev;
-       struct device **jrdev; /* Alloc'ed array per sub-device */
+       struct platform_device **jrpdev; /* Alloc'ed array per sub-device */
        struct platform_device *pdev;
 
        /* Physical-presence section */
@@ -80,12 +83,11 @@ struct caam_drv_private {
        u8 qi_present;          /* Nonzero if QI present in device */
        int secvio_irq;         /* Security violation interrupt number */
 
-       /* which jr allocated to scatterlist crypto */
-       atomic_t tfm_count ____cacheline_aligned;
-       /* list of registered crypto algorithms (mk generic context handle?) */
-       struct list_head alg_list;
-       /* list of registered hash algorithms (mk generic context handle?) */
-       struct list_head hash_list;
+#define        RNG4_MAX_HANDLES 2
+       /* RNG4 block */
+       u32 rng4_sh_init;       /* This bitmap shows which of the State
+                                  Handles of the RNG4 block are initialized
+                                  by this driver */
 
        /*
         * debugfs entries for developer view into driver/device
index bdb786d5a5e5b0216b968a833592d8aef7c96d8d..1d80bd3636c5b1f2cf4dc078d4934e64befc7f68 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #include "compat.h"
 #include "regs.h"
 #include "desc.h"
 #include "intern.h"
 
+struct jr_driver_data {
+       /* List of Physical JobR's with the Driver */
+       struct list_head        jr_list;
+       spinlock_t              jr_alloc_lock;  /* jr_list lock */
+} ____cacheline_aligned;
+
+static struct jr_driver_data driver_data;
+
+static int caam_reset_hw_jr(struct device *dev)
+{
+       struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+       unsigned int timeout = 100000;
+
+       /*
+        * mask interrupts since we are going to poll
+        * for reset completion status
+        */
+       setbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+
+       /* initiate flush (required prior to reset) */
+       wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
+       while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) ==
+               JRINT_ERR_HALT_INPROGRESS) && --timeout)
+               cpu_relax();
+
+       if ((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) !=
+           JRINT_ERR_HALT_COMPLETE || timeout == 0) {
+               dev_err(dev, "failed to flush job ring %d\n", jrp->ridx);
+               return -EIO;
+       }
+
+       /* initiate reset */
+       timeout = 100000;
+       wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
+       while ((rd_reg32(&jrp->rregs->jrcommand) & JRCR_RESET) && --timeout)
+               cpu_relax();
+
+       if (timeout == 0) {
+               dev_err(dev, "failed to reset job ring %d\n", jrp->ridx);
+               return -EIO;
+       }
+
+       /* unmask interrupts */
+       clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+
+       return 0;
+}
+
+/*
+ * Shutdown JobR independent of platform property code
+ */
+int caam_jr_shutdown(struct device *dev)
+{
+       struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+       dma_addr_t inpbusaddr, outbusaddr;
+       int ret;
+
+       ret = caam_reset_hw_jr(dev);
+
+       tasklet_kill(&jrp->irqtask);
+
+       /* Release interrupt */
+       free_irq(jrp->irq, dev);
+
+       /* Free rings */
+       inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
+       outbusaddr = rd_reg64(&jrp->rregs->outring_base);
+       dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH,
+                         jrp->inpring, inpbusaddr);
+       dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH,
+                         jrp->outring, outbusaddr);
+       kfree(jrp->entinfo);
+
+       return ret;
+}
+
+static int caam_jr_remove(struct platform_device *pdev)
+{
+       int ret;
+       struct device *jrdev;
+       struct caam_drv_private_jr *jrpriv;
+
+       jrdev = &pdev->dev;
+       jrpriv = dev_get_drvdata(jrdev);
+
+       /*
+        * Return EBUSY if job ring already allocated.
+        */
+       if (atomic_read(&jrpriv->tfm_count)) {
+               dev_err(jrdev, "Device is busy\n");
+               return -EBUSY;
+       }
+
+       /* Remove the node from Physical JobR list maintained by driver */
+       spin_lock(&driver_data.jr_alloc_lock);
+       list_del(&jrpriv->list_node);
+       spin_unlock(&driver_data.jr_alloc_lock);
+
+       /* Release ring */
+       ret = caam_jr_shutdown(jrdev);
+       if (ret)
+               dev_err(jrdev, "Failed to shut down job ring\n");
+       irq_dispose_mapping(jrpriv->irq);
+
+       return ret;
+}
+
 /* Main per-ring interrupt handler */
 static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)
 {
@@ -127,6 +235,59 @@ static void caam_jr_dequeue(unsigned long devarg)
        clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
 }
 
+/**
+ * caam_jr_alloc() - Alloc a job ring for someone to use as needed.
+ *
+ * returns :  pointer to the newly allocated physical
+ *           JobR dev can be written to if successful.
+ **/
+struct device *caam_jr_alloc(void)
+{
+       struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL;
+       struct device *dev = NULL;
+       int min_tfm_cnt = INT_MAX;
+       int tfm_cnt;
+
+       spin_lock(&driver_data.jr_alloc_lock);
+
+       if (list_empty(&driver_data.jr_list)) {
+               spin_unlock(&driver_data.jr_alloc_lock);
+               return ERR_PTR(-ENODEV);
+       }
+
+       list_for_each_entry(jrpriv, &driver_data.jr_list, list_node) {
+               tfm_cnt = atomic_read(&jrpriv->tfm_count);
+               if (tfm_cnt < min_tfm_cnt) {
+                       min_tfm_cnt = tfm_cnt;
+                       min_jrpriv = jrpriv;
+               }
+               if (!min_tfm_cnt)
+                       break;
+       }
+
+       if (min_jrpriv) {
+               atomic_inc(&min_jrpriv->tfm_count);
+               dev = min_jrpriv->dev;
+       }
+       spin_unlock(&driver_data.jr_alloc_lock);
+
+       return dev;
+}
+EXPORT_SYMBOL(caam_jr_alloc);
+
+/**
+ * caam_jr_free() - Free the Job Ring
+ * @rdev     - points to the dev that identifies the Job ring to
+ *             be released.
+ **/
+void caam_jr_free(struct device *rdev)
+{
+       struct caam_drv_private_jr *jrpriv = dev_get_drvdata(rdev);
+
+       atomic_dec(&jrpriv->tfm_count);
+}
+EXPORT_SYMBOL(caam_jr_free);
+
 /**
  * caam_jr_enqueue() - Enqueue a job descriptor head. Returns 0 if OK,
  * -EBUSY if the queue is full, -EIO if it cannot map the caller's
@@ -207,46 +368,6 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
 }
 EXPORT_SYMBOL(caam_jr_enqueue);
 
-static int caam_reset_hw_jr(struct device *dev)
-{
-       struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
-       unsigned int timeout = 100000;
-
-       /*
-        * mask interrupts since we are going to poll
-        * for reset completion status
-        */
-       setbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
-
-       /* initiate flush (required prior to reset) */
-       wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
-       while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) ==
-               JRINT_ERR_HALT_INPROGRESS) && --timeout)
-               cpu_relax();
-
-       if ((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) !=
-           JRINT_ERR_HALT_COMPLETE || timeout == 0) {
-               dev_err(dev, "failed to flush job ring %d\n", jrp->ridx);
-               return -EIO;
-       }
-
-       /* initiate reset */
-       timeout = 100000;
-       wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
-       while ((rd_reg32(&jrp->rregs->jrcommand) & JRCR_RESET) && --timeout)
-               cpu_relax();
-
-       if (timeout == 0) {
-               dev_err(dev, "failed to reset job ring %d\n", jrp->ridx);
-               return -EIO;
-       }
-
-       /* unmask interrupts */
-       clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
-
-       return 0;
-}
-
 /*
  * Init JobR independent of platform property detection
  */
@@ -262,7 +383,7 @@ static int caam_jr_init(struct device *dev)
 
        /* Connect job ring interrupt handler. */
        error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED,
-                           "caam-jobr", dev);
+                           dev_name(dev), dev);
        if (error) {
                dev_err(dev, "can't connect JobR %d interrupt (%d)\n",
                        jrp->ridx, jrp->irq);
@@ -318,86 +439,43 @@ static int caam_jr_init(struct device *dev)
        return 0;
 }
 
-/*
- * Shutdown JobR independent of platform property code
- */
-int caam_jr_shutdown(struct device *dev)
-{
-       struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
-       dma_addr_t inpbusaddr, outbusaddr;
-       int ret;
-
-       ret = caam_reset_hw_jr(dev);
-
-       tasklet_kill(&jrp->irqtask);
-
-       /* Release interrupt */
-       free_irq(jrp->irq, dev);
-
-       /* Free rings */
-       inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
-       outbusaddr = rd_reg64(&jrp->rregs->outring_base);
-       dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH,
-                         jrp->inpring, inpbusaddr);
-       dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH,
-                         jrp->outring, outbusaddr);
-       kfree(jrp->entinfo);
-       of_device_unregister(jrp->jr_pdev);
-
-       return ret;
-}
 
 /*
- * Probe routine for each detected JobR subsystem. It assumes that
- * property detection was picked up externally.
+ * Probe routine for each detected JobR subsystem.
  */
-int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
-                 int ring)
+static int caam_jr_probe(struct platform_device *pdev)
 {
-       struct device *ctrldev, *jrdev;
-       struct platform_device *jr_pdev;
-       struct caam_drv_private *ctrlpriv;
+       struct device *jrdev;
+       struct device_node *nprop;
+       struct caam_job_ring __iomem *ctrl;
        struct caam_drv_private_jr *jrpriv;
-       u32 *jroffset;
+       static int total_jobrs;
        int error;
 
-       ctrldev = &pdev->dev;
-       ctrlpriv = dev_get_drvdata(ctrldev);
-
+       jrdev = &pdev->dev;
        jrpriv = kmalloc(sizeof(struct caam_drv_private_jr),
                         GFP_KERNEL);
-       if (jrpriv == NULL) {
-               dev_err(ctrldev, "can't alloc private mem for job ring %d\n",
-                       ring);
+       if (!jrpriv)
                return -ENOMEM;
-       }
-       jrpriv->parentdev = ctrldev; /* point back to parent */
-       jrpriv->ridx = ring; /* save ring identity relative to detection */
 
-       /*
-        * Derive a pointer to the detected JobRs regs
-        * Driver has already iomapped the entire space, we just
-        * need to add in the offset to this JobR. Don't know if I
-        * like this long-term, but it'll run
-        */
-       jroffset = (u32 *)of_get_property(np, "reg", NULL);
-       jrpriv->rregs = (struct caam_job_ring __iomem *)((void *)ctrlpriv->ctrl
-                                                        + *jroffset);
+       dev_set_drvdata(jrdev, jrpriv);
 
-       /* Build a local dev for each detected queue */
-       jr_pdev = of_platform_device_create(np, NULL, ctrldev);
-       if (jr_pdev == NULL) {
-               kfree(jrpriv);
-               return -EINVAL;
+       /* save ring identity relative to detection */
+       jrpriv->ridx = total_jobrs++;
+
+       nprop = pdev->dev.of_node;
+       /* Get configuration properties from device tree */
+       /* First, get register page */
+       ctrl = of_iomap(nprop, 0);
+       if (!ctrl) {
+               dev_err(jrdev, "of_iomap() failed\n");
+               return -ENOMEM;
        }
 
-       jrpriv->jr_pdev = jr_pdev;
-       jrdev = &jr_pdev->dev;
-       dev_set_drvdata(jrdev, jrpriv);
-       ctrlpriv->jrdev[ring] = jrdev;
+       jrpriv->rregs = (struct caam_job_ring __force *)ctrl;
 
        if (sizeof(dma_addr_t) == sizeof(u64))
-               if (of_device_is_compatible(np, "fsl,sec-v5.0-job-ring"))
+               if (of_device_is_compatible(nprop, "fsl,sec-v5.0-job-ring"))
                        dma_set_mask(jrdev, DMA_BIT_MASK(40));
                else
                        dma_set_mask(jrdev, DMA_BIT_MASK(36));
@@ -405,15 +483,61 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
                dma_set_mask(jrdev, DMA_BIT_MASK(32));
 
        /* Identify the interrupt */
-       jrpriv->irq = irq_of_parse_and_map(np, 0);
+       jrpriv->irq = irq_of_parse_and_map(nprop, 0);
 
        /* Now do the platform independent part */
        error = caam_jr_init(jrdev); /* now turn on hardware */
        if (error) {
-               of_device_unregister(jr_pdev);
                kfree(jrpriv);
                return error;
        }
 
-       return error;
+       jrpriv->dev = jrdev;
+       spin_lock(&driver_data.jr_alloc_lock);
+       list_add_tail(&jrpriv->list_node, &driver_data.jr_list);
+       spin_unlock(&driver_data.jr_alloc_lock);
+
+       atomic_set(&jrpriv->tfm_count, 0);
+
+       return 0;
+}
+
+static struct of_device_id caam_jr_match[] = {
+       {
+               .compatible = "fsl,sec-v4.0-job-ring",
+       },
+       {
+               .compatible = "fsl,sec4.0-job-ring",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, caam_jr_match);
+
+static struct platform_driver caam_jr_driver = {
+       .driver = {
+               .name = "caam_jr",
+               .owner = THIS_MODULE,
+               .of_match_table = caam_jr_match,
+       },
+       .probe       = caam_jr_probe,
+       .remove      = caam_jr_remove,
+};
+
+static int __init jr_driver_init(void)
+{
+       spin_lock_init(&driver_data.jr_alloc_lock);
+       INIT_LIST_HEAD(&driver_data.jr_list);
+       return platform_driver_register(&caam_jr_driver);
+}
+
+static void __exit jr_driver_exit(void)
+{
+       platform_driver_unregister(&caam_jr_driver);
 }
+
+module_init(jr_driver_init);
+module_exit(jr_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM JR request backend");
+MODULE_AUTHOR("Freescale Semiconductor - NMG/STC");
index 9d8741a59037f82ea162ef2a0b894bca49b5b040..97113a6d6c58f500cd7aeb64a4d506ebfc0ca688 100644 (file)
@@ -8,12 +8,11 @@
 #define JR_H
 
 /* Prototypes for backend-level services exposed to APIs */
+struct device *caam_jr_alloc(void);
+void caam_jr_free(struct device *rdev);
 int caam_jr_enqueue(struct device *dev, u32 *desc,
                    void (*cbk)(struct device *dev, u32 *desc, u32 status,
                                void *areq),
                    void *areq);
 
-extern int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
-                        int ring);
-extern int caam_jr_shutdown(struct device *dev);
 #endif /* JR_H */
index 4455396918de84320380fcca2eca01d694971114..d50174f45b21c8e0c145d7077ec86f86cb66ff37 100644 (file)
@@ -245,7 +245,7 @@ struct rngtst {
 
 /* RNG4 TRNG test registers */
 struct rng4tst {
-#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+#define RTMCTL_PRGM    0x00010000      /* 1 -> program mode, 0 -> run mode */
        u32 rtmctl;             /* misc. control register */
        u32 rtscmisc;           /* statistical check misc. register */
        u32 rtpkrrng;           /* poker range register */
@@ -255,6 +255,8 @@ struct rng4tst {
        };
 #define RTSDCTL_ENT_DLY_SHIFT 16
 #define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
+#define RTSDCTL_ENT_DLY_MIN 1200
+#define RTSDCTL_ENT_DLY_MAX 12800
        u32 rtsdctl;            /* seed control register */
        union {
                u32 rtsblim;    /* PRGM=1: sparse bit limit register */
@@ -266,7 +268,11 @@ struct rng4tst {
                u32 rtfrqcnt;   /* PRGM=0: freq. count register */
        };
        u32 rsvd1[40];
+#define RDSTA_SKVT 0x80000000
+#define RDSTA_SKVN 0x40000000
 #define RDSTA_IF0 0x00000001
+#define RDSTA_IF1 0x00000002
+#define RDSTA_IFMASK (RDSTA_IF1 | RDSTA_IF0)
        u32 rdsta;
        u32 rsvd2[15];
 };
@@ -692,6 +698,7 @@ struct caam_deco {
        u32 jr_ctl_hi;  /* CxJRR - JobR Control Register      @800 */
        u32 jr_ctl_lo;
        u64 jr_descaddr;        /* CxDADR - JobR Descriptor Address */
+#define DECO_OP_STATUS_HI_ERR_MASK 0xF00000FF
        u32 op_status_hi;       /* DxOPSTA - DECO Operation Status */
        u32 op_status_lo;
        u32 rsvd24[2];
@@ -706,12 +713,13 @@ struct caam_deco {
        u32 rsvd29[48];
        u32 descbuf[64];        /* DxDESB - Descriptor buffer */
        u32 rscvd30[193];
+#define DESC_DBG_DECO_STAT_HOST_ERR    0x00D00000
+#define DESC_DBG_DECO_STAT_VALID       0x80000000
+#define DESC_DBG_DECO_STAT_MASK                0x00F00000
        u32 desc_dbg;           /* DxDDR - DECO Debug Register */
        u32 rsvd31[126];
 };
 
-/* DECO DBG Register Valid Bit*/
-#define DECO_DBG_VALID         0x80000000
 #define DECO_JQCR_WHL          0x20000000
 #define DECO_JQCR_FOUR         0x10000000
 
index e0037c8ee24386e941e5eed6189e9c2cd9747a3a..b12ff85f4241ece439e43310b115d16a08c5e2eb 100644 (file)
@@ -117,6 +117,21 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
        return nents;
 }
 
+/* Map SG page in kernel virtual address space and copy */
+static inline void sg_map_copy(u8 *dest, struct scatterlist *sg,
+                              int len, int offset)
+{
+       u8 *mapped_addr;
+
+       /*
+        * Page here can be user-space pinned using get_user_pages
+        * Same must be kmapped before use and kunmapped subsequently
+        */
+       mapped_addr = kmap_atomic(sg_page(sg));
+       memcpy(dest, mapped_addr + offset, len);
+       kunmap_atomic(mapped_addr);
+}
+
 /* Copy from len bytes of sg to dest, starting from beginning */
 static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
 {
@@ -124,15 +139,15 @@ static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
        int cpy_index = 0, next_cpy_index = current_sg->length;
 
        while (next_cpy_index < len) {
-               memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
-                      current_sg->length);
+               sg_map_copy(dest + cpy_index, current_sg, current_sg->length,
+                           current_sg->offset);
                current_sg = scatterwalk_sg_next(current_sg);
                cpy_index = next_cpy_index;
                next_cpy_index += current_sg->length;
        }
        if (cpy_index < len)
-               memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
-                      len - cpy_index);
+               sg_map_copy(dest + cpy_index, current_sg, len-cpy_index,
+                           current_sg->offset);
 }
 
 /* Copy sg data, from to_skip to end, to dest */
@@ -140,7 +155,7 @@ static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
                                      int to_skip, unsigned int end)
 {
        struct scatterlist *current_sg = sg;
-       int sg_index, cpy_index;
+       int sg_index, cpy_index, offset;
 
        sg_index = current_sg->length;
        while (sg_index <= to_skip) {
@@ -148,9 +163,10 @@ static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
                sg_index += current_sg->length;
        }
        cpy_index = sg_index - to_skip;
-       memcpy(dest, (u8 *) sg_virt(current_sg) +
-              current_sg->length - cpy_index, cpy_index);
-       current_sg = scatterwalk_sg_next(current_sg);
-       if (end - sg_index)
+       offset = current_sg->offset + current_sg->length - cpy_index;
+       sg_map_copy(dest, current_sg, cpy_index, offset);
+       if (end - sg_index) {
+               current_sg = scatterwalk_sg_next(current_sg);
                sg_copy(dest + cpy_index, current_sg, end - sg_index);
+       }
 }
index a8a7dd4b0d25c6741d47e40b53b9d3cfd7f101ad..247ab8048f5bea3f09e5537f103626fe84e3bce5 100644 (file)
@@ -733,12 +733,9 @@ static int dcp_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, dev);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
-               dev_err(&pdev->dev, "failed to get IORESOURCE_MEM\n");
-               return -ENXIO;
-       }
-       dev->dcp_regs_base = devm_ioremap(&pdev->dev, r->start,
-                                         resource_size(r));
+       dev->dcp_regs_base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(dev->dcp_regs_base))
+               return PTR_ERR(dev->dcp_regs_base);
 
        dcp_set(dev, DCP_CTRL_SFRST, DCP_REG_CTRL);
        udelay(10);
@@ -762,7 +759,8 @@ static int dcp_probe(struct platform_device *pdev)
                return -EIO;
        }
        dev->dcp_vmi_irq = r->start;
-       ret = request_irq(dev->dcp_vmi_irq, dcp_vmi_irq, 0, "dcp", dev);
+       ret = devm_request_irq(&pdev->dev, dev->dcp_vmi_irq, dcp_vmi_irq, 0,
+                              "dcp", dev);
        if (ret != 0) {
                dev_err(&pdev->dev, "can't request_irq (0)\n");
                return -EIO;
@@ -771,15 +769,14 @@ static int dcp_probe(struct platform_device *pdev)
        r = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
        if (!r) {
                dev_err(&pdev->dev, "can't get IRQ resource (1)\n");
-               ret = -EIO;
-               goto err_free_irq0;
+               return -EIO;
        }
        dev->dcp_irq = r->start;
-       ret = request_irq(dev->dcp_irq, dcp_irq, 0, "dcp", dev);
+       ret = devm_request_irq(&pdev->dev, dev->dcp_irq, dcp_irq, 0, "dcp",
+                              dev);
        if (ret != 0) {
                dev_err(&pdev->dev, "can't request_irq (1)\n");
-               ret = -EIO;
-               goto err_free_irq0;
+               return -EIO;
        }
 
        dev->hw_pkg[0] = dma_alloc_coherent(&pdev->dev,
@@ -788,8 +785,7 @@ static int dcp_probe(struct platform_device *pdev)
                        GFP_KERNEL);
        if (!dev->hw_pkg[0]) {
                dev_err(&pdev->dev, "Could not allocate hw descriptors\n");
-               ret = -ENOMEM;
-               goto err_free_irq1;
+               return -ENOMEM;
        }
 
        for (i = 1; i < DCP_MAX_PKG; i++) {
@@ -848,16 +844,14 @@ err_unregister:
        for (j = 0; j < i; j++)
                crypto_unregister_alg(&algs[j]);
 err_free_key_iv:
+       tasklet_kill(&dev->done_task);
+       tasklet_kill(&dev->queue_task);
        dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
                        dev->payload_base_dma);
 err_free_hw_packet:
        dma_free_coherent(&pdev->dev, DCP_MAX_PKG *
                sizeof(struct dcp_hw_packet), dev->hw_pkg[0],
                dev->hw_phys_pkg);
-err_free_irq1:
-       free_irq(dev->dcp_irq, dev);
-err_free_irq0:
-       free_irq(dev->dcp_vmi_irq, dev);
 
        return ret;
 }
@@ -868,23 +862,20 @@ static int dcp_remove(struct platform_device *pdev)
        int j;
        dev = platform_get_drvdata(pdev);
 
-       dma_free_coherent(&pdev->dev,
-                       DCP_MAX_PKG * sizeof(struct dcp_hw_packet),
-                       dev->hw_pkg[0], dev->hw_phys_pkg);
-
-       dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
-                       dev->payload_base_dma);
+       misc_deregister(&dev->dcp_bootstream_misc);
 
-       free_irq(dev->dcp_irq, dev);
-       free_irq(dev->dcp_vmi_irq, dev);
+       for (j = 0; j < ARRAY_SIZE(algs); j++)
+               crypto_unregister_alg(&algs[j]);
 
        tasklet_kill(&dev->done_task);
        tasklet_kill(&dev->queue_task);
 
-       for (j = 0; j < ARRAY_SIZE(algs); j++)
-               crypto_unregister_alg(&algs[j]);
+       dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
+                       dev->payload_base_dma);
 
-       misc_deregister(&dev->dcp_bootstream_misc);
+       dma_free_coherent(&pdev->dev,
+                       DCP_MAX_PKG * sizeof(struct dcp_hw_packet),
+                       dev->hw_pkg[0], dev->hw_phys_pkg);
 
        return 0;
 }
index 214357e12dc0b5469bb3c9daae5904ef3a618845..9dd6e01eac33050b8304c5f8758440e7286606f2 100644 (file)
@@ -1149,32 +1149,24 @@ static int aead_setkey(struct crypto_aead *tfm, const u8 *key,
                        unsigned int keylen)
 {
        struct ixp_ctx *ctx = crypto_aead_ctx(tfm);
-       struct rtattr *rta = (struct rtattr *)key;
-       struct crypto_authenc_key_param *param;
+       struct crypto_authenc_keys keys;
 
-       if (!RTA_OK(rta, keylen))
-               goto badkey;
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+       if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
                goto badkey;
 
-       param = RTA_DATA(rta);
-       ctx->enckey_len = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
+       if (keys.authkeylen > sizeof(ctx->authkey))
+               goto badkey;
 
-       if (keylen < ctx->enckey_len)
+       if (keys.enckeylen > sizeof(ctx->enckey))
                goto badkey;
 
-       ctx->authkey_len = keylen - ctx->enckey_len;
-       memcpy(ctx->enckey, key + ctx->authkey_len, ctx->enckey_len);
-       memcpy(ctx->authkey, key, ctx->authkey_len);
+       memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
+       memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
+       ctx->authkey_len = keys.authkeylen;
+       ctx->enckey_len = keys.enckeylen;
 
        return aead_setup(tfm, crypto_aead_authsize(tfm));
 badkey:
-       ctx->enckey_len = 0;
        crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
        return -EINVAL;
 }
index 3374a3ebe4c75f49ecacbec24740ead4e05011b8..8d1e6f8e9e9cf613519b14fa5e5126135d37e986 100644 (file)
@@ -907,7 +907,7 @@ static int mv_cra_hash_hmac_sha1_init(struct crypto_tfm *tfm)
        return mv_cra_hash_init(tfm, "sha1", COP_HMAC_SHA1, SHA1_BLOCK_SIZE);
 }
 
-irqreturn_t crypto_int(int irq, void *priv)
+static irqreturn_t crypto_int(int irq, void *priv)
 {
        u32 val;
 
@@ -928,7 +928,7 @@ irqreturn_t crypto_int(int irq, void *priv)
        return IRQ_HANDLED;
 }
 
-struct crypto_alg mv_aes_alg_ecb = {
+static struct crypto_alg mv_aes_alg_ecb = {
        .cra_name               = "ecb(aes)",
        .cra_driver_name        = "mv-ecb-aes",
        .cra_priority   = 300,
@@ -951,7 +951,7 @@ struct crypto_alg mv_aes_alg_ecb = {
        },
 };
 
-struct crypto_alg mv_aes_alg_cbc = {
+static struct crypto_alg mv_aes_alg_cbc = {
        .cra_name               = "cbc(aes)",
        .cra_driver_name        = "mv-cbc-aes",
        .cra_priority   = 300,
@@ -975,7 +975,7 @@ struct crypto_alg mv_aes_alg_cbc = {
        },
 };
 
-struct ahash_alg mv_sha1_alg = {
+static struct ahash_alg mv_sha1_alg = {
        .init = mv_hash_init,
        .update = mv_hash_update,
        .final = mv_hash_final,
@@ -999,7 +999,7 @@ struct ahash_alg mv_sha1_alg = {
                 }
 };
 
-struct ahash_alg mv_hmac_sha1_alg = {
+static struct ahash_alg mv_hmac_sha1_alg = {
        .init = mv_hash_init,
        .update = mv_hash_update,
        .final = mv_hash_final,
@@ -1084,7 +1084,7 @@ static int mv_probe(struct platform_device *pdev)
                goto err_unmap_sram;
        }
 
-       ret = request_irq(irq, crypto_int, IRQF_DISABLED, dev_name(&pdev->dev),
+       ret = request_irq(irq, crypto_int, 0, dev_name(&pdev->dev),
                        cp);
        if (ret)
                goto err_thread;
@@ -1187,7 +1187,7 @@ static struct platform_driver marvell_crypto = {
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "mv_crypto",
-               .of_match_table = of_match_ptr(mv_cesa_of_match_table),
+               .of_match_table = mv_cesa_of_match_table,
        },
 };
 MODULE_ALIAS("platform:mv_crypto");
index ce791c2f81f79e4ffda5d7d44e6a31a8a46bcb34..a9ccbf14096e3c03a9c193042baddc6d5b0e4925 100644 (file)
@@ -275,7 +275,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
        if (dd->flags & FLAGS_CBC)
                val |= AES_REG_CTRL_CBC;
        if (dd->flags & FLAGS_CTR) {
-               val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_32;
+               val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128;
                mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
        }
        if (dd->flags & FLAGS_ENCRYPT)
@@ -554,7 +554,7 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
        return err;
 }
 
-int omap_aes_check_aligned(struct scatterlist *sg)
+static int omap_aes_check_aligned(struct scatterlist *sg)
 {
        while (sg) {
                if (!IS_ALIGNED(sg->offset, 4))
@@ -566,7 +566,7 @@ int omap_aes_check_aligned(struct scatterlist *sg)
        return 0;
 }
 
-int omap_aes_copy_sgs(struct omap_aes_dev *dd)
+static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
 {
        void *buf_in, *buf_out;
        int pages;
index e28104b4aab08ce20a9c1bbf26aefdb45778379a..e45aaaf0db3069d5c99cef88664dfdc62a87d434 100644 (file)
@@ -2033,3 +2033,4 @@ module_platform_driver(omap_sham_driver);
 MODULE_DESCRIPTION("OMAP SHA1/MD5 hw acceleration support.");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Dmitry Kasatkin");
+MODULE_ALIAS("platform:omap-sham");
index 888f7f4a6d3fa29a36c26a1ee1119428164d9df9..a6175ba6d2389f96ea118470123fd3e7818fb279 100644 (file)
@@ -495,45 +495,29 @@ static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
 {
        struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
        struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
-       unsigned int authkeylen, enckeylen;
+       struct crypto_authenc_keys keys;
        int err = -EINVAL;
 
-       if (!RTA_OK(rta, keylen))
+       if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
                goto badkey;
 
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+       if (keys.enckeylen > AES_MAX_KEY_SIZE)
                goto badkey;
 
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
-               goto badkey;
-
-       param = RTA_DATA(rta);
-       enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
-
-       if (keylen < enckeylen)
-               goto badkey;
-
-       authkeylen = keylen - enckeylen;
-
-       if (enckeylen > AES_MAX_KEY_SIZE)
+       if (keys.authkeylen > sizeof(ctx->hash_ctx))
                goto badkey;
 
        if ((alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
            SPA_CTRL_CIPH_ALG_AES)
-               err = spacc_aead_aes_setkey(tfm, key + authkeylen, enckeylen);
+               err = spacc_aead_aes_setkey(tfm, keys.enckey, keys.enckeylen);
        else
-               err = spacc_aead_des_setkey(tfm, key + authkeylen, enckeylen);
+               err = spacc_aead_des_setkey(tfm, keys.enckey, keys.enckeylen);
 
        if (err)
                goto badkey;
 
-       memcpy(ctx->hash_ctx, keyauthkeylen);
-       ctx->hash_key_len = authkeylen;
+       memcpy(ctx->hash_ctx, keys.authkey, keys.authkeylen);
+       ctx->hash_key_len = keys.authkeylen;
 
        return 0;
 
index d7bb8bac36e973944334409760dc56c37eb02be1..785a9ded7bdf3bda2840bc36daa88fe7f1532a9b 100644 (file)
@@ -1058,7 +1058,7 @@ static struct platform_driver sahara_driver = {
        .driver         = {
                .name   = SAHARA_NAME,
                .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(sahara_dt_ids),
+               .of_match_table = sahara_dt_ids,
        },
        .id_table = sahara_platform_ids,
 };
index 6cd0e603858321dd678b45ad74dda8f6746fba97..b44f4ddc565c3bb7cd32b84c08a0b286543681e5 100644 (file)
@@ -673,39 +673,20 @@ static int aead_setkey(struct crypto_aead *authenc,
                       const u8 *key, unsigned int keylen)
 {
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
-       unsigned int authkeylen;
-       unsigned int enckeylen;
-
-       if (!RTA_OK(rta, keylen))
-               goto badkey;
+       struct crypto_authenc_keys keys;
 
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+       if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
                goto badkey;
 
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+       if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
                goto badkey;
 
-       param = RTA_DATA(rta);
-       enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
+       memcpy(ctx->key, keys.authkey, keys.authkeylen);
+       memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
 
-       if (keylen < enckeylen)
-               goto badkey;
-
-       authkeylen = keylen - enckeylen;
-
-       if (keylen > TALITOS_MAX_KEY_SIZE)
-               goto badkey;
-
-       memcpy(&ctx->key, key, keylen);
-
-       ctx->keylen = keylen;
-       ctx->enckeylen = enckeylen;
-       ctx->authkeylen = authkeylen;
+       ctx->keylen = keys.authkeylen + keys.enckeylen;
+       ctx->enckeylen = keys.enckeylen;
+       ctx->authkeylen = keys.authkeylen;
 
        return 0;
 
@@ -809,7 +790,7 @@ static void ipsec_esp_unmap(struct device *dev,
 
        if (edesc->assoc_chained)
                talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
-       else
+       else if (areq->assoclen)
                /* assoc_nents counts also for IV in non-contiguous cases */
                dma_unmap_sg(dev, areq->assoc,
                             edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
@@ -992,7 +973,11 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
                dma_sync_single_for_device(dev, edesc->dma_link_tbl,
                                           edesc->dma_len, DMA_BIDIRECTIONAL);
        } else {
-               to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->assoc));
+               if (areq->assoclen)
+                       to_talitos_ptr(&desc->ptr[1],
+                                      sg_dma_address(areq->assoc));
+               else
+                       to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
                desc->ptr[1].j_extent = 0;
        }
 
@@ -1127,7 +1112,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                 unsigned int authsize,
                                                 unsigned int ivsize,
                                                 int icv_stashing,
-                                                u32 cryptoflags)
+                                                u32 cryptoflags,
+                                                bool encrypt)
 {
        struct talitos_edesc *edesc;
        int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
@@ -1141,10 +1127,10 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       if (iv)
+       if (ivsize)
                iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
 
-       if (assoc) {
+       if (assoclen) {
                /*
                 * Currently it is assumed that iv is provided whenever assoc
                 * is.
@@ -1160,19 +1146,17 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                        assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
        }
 
-       src_nents = sg_count(src, cryptlen + authsize, &src_chained);
-       src_nents = (src_nents == 1) ? 0 : src_nents;
-
-       if (!dst) {
-               dst_nents = 0;
-       } else {
-               if (dst == src) {
-                       dst_nents = src_nents;
-               } else {
-                       dst_nents = sg_count(dst, cryptlen + authsize,
-                                            &dst_chained);
-                       dst_nents = (dst_nents == 1) ? 0 : dst_nents;
-               }
+       if (!dst || dst == src) {
+               src_nents = sg_count(src, cryptlen + authsize, &src_chained);
+               src_nents = (src_nents == 1) ? 0 : src_nents;
+               dst_nents = dst ? src_nents : 0;
+       } else { /* dst && dst != src*/
+               src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
+                                    &src_chained);
+               src_nents = (src_nents == 1) ? 0 : src_nents;
+               dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
+                                    &dst_chained);
+               dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
 
        /*
@@ -1192,9 +1176,16 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
        if (!edesc) {
-               talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+               if (assoc_chained)
+                       talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+               else if (assoclen)
+                       dma_unmap_sg(dev, assoc,
+                                    assoc_nents ? assoc_nents - 1 : 1,
+                                    DMA_TO_DEVICE);
+
                if (iv_dma)
                        dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+
                dev_err(dev, "could not allocate edescriptor\n");
                return ERR_PTR(-ENOMEM);
        }
@@ -1216,7 +1207,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
-                                             int icv_stashing)
+                                             int icv_stashing, bool encrypt)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
@@ -1225,7 +1216,7 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
        return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
                                   iv, areq->assoclen, areq->cryptlen,
                                   ctx->authsize, ivsize, icv_stashing,
-                                  areq->base.flags);
+                                  areq->base.flags, encrypt);
 }
 
 static int aead_encrypt(struct aead_request *req)
@@ -1235,7 +1226,7 @@ static int aead_encrypt(struct aead_request *req)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(req, req->iv, 0);
+       edesc = aead_edesc_alloc(req, req->iv, 0, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1258,7 +1249,7 @@ static int aead_decrypt(struct aead_request *req)
        req->cryptlen -= authsize;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(req, req->iv, 1);
+       edesc = aead_edesc_alloc(req, req->iv, 1, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1304,7 +1295,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(areq, req->giv, 0);
+       edesc = aead_edesc_alloc(areq, req->giv, 0, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1460,7 +1451,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 }
 
 static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
-                                                   areq)
+                                                   areq, bool encrypt)
 {
        struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
        struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
@@ -1468,7 +1459,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
 
        return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
                                   areq->info, 0, areq->nbytes, 0, ivsize, 0,
-                                  areq->base.flags);
+                                  areq->base.flags, encrypt);
 }
 
 static int ablkcipher_encrypt(struct ablkcipher_request *areq)
@@ -1478,7 +1469,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(areq);
+       edesc = ablkcipher_edesc_alloc(areq, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1495,7 +1486,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(areq);
+       edesc = ablkcipher_edesc_alloc(areq, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1647,7 +1638,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
        struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 
        return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
-                                  nbytes, 0, 0, 0, areq->base.flags);
+                                  nbytes, 0, 0, 0, areq->base.flags, false);
 }
 
 static int ahash_init(struct ahash_request *areq)
index fa05e3c329bdd44a522a922a1d12e87a54393309..060eecc5dbc31b24bf0c05301b37192da7e36dff 100644 (file)
@@ -27,6 +27,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -199,8 +201,6 @@ static void aes_workqueue_handler(struct work_struct *work);
 static DECLARE_WORK(aes_work, aes_workqueue_handler);
 static struct workqueue_struct *aes_wq;
 
-extern unsigned long long tegra_chip_uid(void);
-
 static inline u32 aes_readl(struct tegra_aes_dev *dd, u32 offset)
 {
        return readl(dd->io_base + offset);
@@ -713,13 +713,12 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
        struct tegra_aes_dev *dd = aes_dev;
        struct tegra_aes_ctx *ctx = &rng_ctx;
        struct tegra_aes_slot *key_slot;
-       struct timespec ts;
        int ret = 0;
-       u64 nsec, tmp[2];
+       u8 tmp[16]; /* 16 bytes = 128 bits of entropy */
        u8 *dt;
 
        if (!ctx || !dd) {
-               dev_err(dd->dev, "ctx=0x%x, dd=0x%x\n",
+               pr_err("ctx=0x%x, dd=0x%x\n",
                        (unsigned int)ctx, (unsigned int)dd);
                return -EINVAL;
        }
@@ -778,14 +777,8 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
        if (dd->ivlen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) {
                dt = dd->iv + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128;
        } else {
-               getnstimeofday(&ts);
-               nsec = timespec_to_ns(&ts);
-               do_div(nsec, 1000);
-               nsec ^= dd->ctr << 56;
-               dd->ctr++;
-               tmp[0] = nsec;
-               tmp[1] = tegra_chip_uid();
-               dt = (u8 *)tmp;
+               get_random_bytes(tmp, sizeof(tmp));
+               dt = tmp;
        }
        memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ);
 
@@ -804,7 +797,7 @@ static int tegra_aes_cra_init(struct crypto_tfm *tfm)
        return 0;
 }
 
-void tegra_aes_cra_exit(struct crypto_tfm *tfm)
+static void tegra_aes_cra_exit(struct crypto_tfm *tfm)
 {
        struct tegra_aes_ctx *ctx =
                crypto_ablkcipher_ctx((struct crypto_ablkcipher *)tfm);
@@ -924,7 +917,7 @@ static int tegra_aes_probe(struct platform_device *pdev)
        }
 
        /* Initialize the vde clock */
-       dd->aes_clk = clk_get(dev, "vde");
+       dd->aes_clk = devm_clk_get(dev, "vde");
        if (IS_ERR(dd->aes_clk)) {
                dev_err(dev, "iclock intialization failed.\n");
                err = -ENODEV;
@@ -1033,8 +1026,6 @@ out:
        if (dd->buf_out)
                dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
                        dd->buf_out, dd->dma_buf_out);
-       if (!IS_ERR(dd->aes_clk))
-               clk_put(dd->aes_clk);
        if (aes_wq)
                destroy_workqueue(aes_wq);
        spin_lock(&list_lock);
@@ -1068,7 +1059,6 @@ static int tegra_aes_remove(struct platform_device *pdev)
                          dd->buf_in, dd->dma_buf_in);
        dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
                          dd->buf_out, dd->dma_buf_out);
-       clk_put(dd->aes_clk);
        aes_dev = NULL;
 
        return 0;
index 446687cc2334ed2f60a0b6f0170382fe733aae01..c823daaf90430bb501ff9bc168e88adbcecf87ef 100644 (file)
@@ -62,6 +62,7 @@ config INTEL_IOATDMA
        tristate "Intel I/OAT DMA support"
        depends on PCI && X86
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select DCA
        help
          Enable support for the Intel(R) I/OAT DMA engine present
@@ -112,6 +113,7 @@ config MV_XOR
        bool "Marvell XOR engine support"
        depends on PLAT_ORION
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        ---help---
          Enable support for the Marvell XOR engine.
@@ -187,6 +189,7 @@ config AMCC_PPC440SPE_ADMA
        tristate "AMCC PPC440SPe ADMA support"
        depends on 440SPe || 440SP
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        help
@@ -352,6 +355,7 @@ config NET_DMA
        bool "Network: TCP receive copy offload"
        depends on DMA_ENGINE && NET
        default (INTEL_IOATDMA || FSL_DMA)
+       depends on BROKEN
        help
          This enables the use of DMA engines in the network stack to
          offload receive copy-to-user operations, freeing CPU cycles.
@@ -377,4 +381,7 @@ config DMATEST
          Simple DMA test client. Say N unless you're debugging a
          DMA Device driver.
 
+config DMA_ENGINE_RAID
+       bool
+
 endif
index 16a2aa28f85672689f66c37039a8e72230e71b02..ec4ee5c1fe9dc2115e029d0c472bd32f48cb281c 100644 (file)
@@ -1169,7 +1169,7 @@ static void pl08x_desc_free(struct virt_dma_desc *vd)
        struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
        struct pl08x_dma_chan *plchan = to_pl08x_chan(vd->tx.chan);
 
-       dma_descriptor_unmap(txd);
+       dma_descriptor_unmap(&vd->tx);
        if (!txd->done)
                pl08x_release_mux(plchan);
 
index f31d647acdfaac3730371e1366ff964e245435ac..2787aba60c6bdee8ed0489cb932338d6a81528ac 100644 (file)
@@ -347,10 +347,6 @@ static struct device *chan2dev(struct dma_chan *chan)
 {
        return &chan->dev->device;
 }
-static struct device *chan2parent(struct dma_chan *chan)
-{
-       return chan->dev->device.parent;
-}
 
 #if defined(VERBOSE_DEBUG)
 static void vdbg_dump_regs(struct at_dma_chan *atchan)
index ea806bdc12ef92418c528be0b950758de59c3ee7..92caad629d996cec8415b5d96dfc10605b127195 100644 (file)
@@ -540,6 +540,8 @@ EXPORT_SYMBOL_GPL(dma_get_slave_channel);
  * @mask: capabilities that the channel must satisfy
  * @fn: optional callback to disposition available channels
  * @fn_param: opaque parameter to pass to dma_filter_fn
+ *
+ * Returns pointer to appropriate DMA channel on success or NULL.
  */
 struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
                                       dma_filter_fn fn, void *fn_param)
@@ -591,18 +593,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
  * dma_request_slave_channel - try to allocate an exclusive slave channel
  * @dev:       pointer to client device structure
  * @name:      slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
  */
-struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
+struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
+                                                 const char *name)
 {
+       struct dma_chan *chan;
+
        /* If device-tree is present get slave info from here */
        if (dev->of_node)
                return of_dma_request_slave_channel(dev->of_node, name);
 
        /* If device was enumerated by ACPI get slave info from here */
-       if (ACPI_HANDLE(dev))
-               return acpi_dma_request_slave_chan_by_name(dev, name);
+       if (ACPI_HANDLE(dev)) {
+               chan = acpi_dma_request_slave_chan_by_name(dev, name);
+               if (chan)
+                       return chan;
+       }
 
-       return NULL;
+       return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
+
+/**
+ * dma_request_slave_channel - try to allocate an exclusive slave channel
+ * @dev:       pointer to client device structure
+ * @name:      slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or NULL.
+ */
+struct dma_chan *dma_request_slave_channel(struct device *dev,
+                                          const char *name)
+{
+       struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
+       if (IS_ERR(ch))
+               return NULL;
+       return ch;
 }
 EXPORT_SYMBOL_GPL(dma_request_slave_channel);
 
@@ -912,7 +939,7 @@ struct dmaengine_unmap_pool {
 #define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) }
 static struct dmaengine_unmap_pool unmap_pool[] = {
        __UNMAP_POOL(2),
-       #if IS_ENABLED(CONFIG_ASYNC_TX_DMA)
+       #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID)
        __UNMAP_POOL(16),
        __UNMAP_POOL(128),
        __UNMAP_POOL(256),
@@ -1054,7 +1081,7 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
        dma_cookie_t cookie;
        unsigned long flags;
 
-       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOIO);
+       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOWAIT);
        if (!unmap)
                return -ENOMEM;
 
index 20f9a3aaf9266ea6daa71a18f08d258afa8a1a1e..9dfcaf5c12888d3de80483329ffccc7fbbacd02a 100644 (file)
@@ -539,9 +539,9 @@ static int dmatest_func(void *data)
 
                um->len = params->buf_size;
                for (i = 0; i < src_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->srcs[i];
+                       void *buf = thread->srcs[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
                                                   um->len, DMA_TO_DEVICE);
@@ -559,9 +559,9 @@ static int dmatest_func(void *data)
                /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
                dsts = &um->addr[src_cnt];
                for (i = 0; i < dst_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->dsts[i];
+                       void *buf = thread->dsts[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
                                               DMA_BIDIRECTIONAL);
index 7086a16a55f2ed488573e475e615600c80be767e..f157c6f76b32b8c98dce28eed6253db033acc258 100644 (file)
@@ -86,11 +86,6 @@ static void set_desc_cnt(struct fsldma_chan *chan,
        hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
-static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
-{
-       return DMA_TO_CPU(chan, desc->hw.count, 32);
-}
-
 static void set_desc_src(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
@@ -101,16 +96,6 @@ static void set_desc_src(struct fsldma_chan *chan,
        hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
-static dma_addr_t get_desc_src(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_dst(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
@@ -121,16 +106,6 @@ static void set_desc_dst(struct fsldma_chan *chan,
        hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
-static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_next(struct fsldma_chan *chan,
                          struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
@@ -408,7 +383,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
        struct fsl_desc_sw *child;
        unsigned long flags;
-       dma_cookie_t cookie;
+       dma_cookie_t cookie = -EINVAL;
 
        spin_lock_irqsave(&chan->desc_lock, flags);
 
@@ -854,10 +829,6 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
                                      struct fsl_desc_sw *desc)
 {
        struct dma_async_tx_descriptor *txd = &desc->async_tx;
-       struct device *dev = chan->common.device->dev;
-       dma_addr_t src = get_desc_src(chan, desc);
-       dma_addr_t dst = get_desc_dst(chan, desc);
-       u32 len = get_desc_cnt(chan, desc);
 
        /* Run the link descriptor callback function */
        if (txd->callback) {
index dcb1e05149a7664c6e65a214d783080d540aaafd..8869500ab92b84a4b93f4111f8936e6722d4911c 100644 (file)
@@ -1017,6 +1017,7 @@ static int mmp_pdma_probe(struct platform_device *op)
                }
        }
 
+       platform_set_drvdata(op, pdev);
        dev_info(pdev->device.dev, "initialized %d channels\n", dma_channels);
        return 0;
 }
index 7807f0ef4e209c25ad90db9d32f7bc13955391cf..53fb0c8365b0b27f29a893a3072103c9fb2360e9 100644 (file)
@@ -54,12 +54,6 @@ static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
        hw_desc->desc_command = (1 << 31);
 }
 
-static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
-{
-       struct mv_xor_desc *hw_desc = desc->hw_desc;
-       return hw_desc->phy_dest_addr;
-}
-
 static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
                                   u32 byte_count)
 {
@@ -787,7 +781,6 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
 /*
  * Perform a transaction to verify the HW works.
  */
-#define MV_XOR_TEST_SIZE 2000
 
 static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 {
@@ -797,20 +790,21 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        int err = 0;
 
-       src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!src)
                return -ENOMEM;
 
-       dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!dest) {
                kfree(src);
                return -ENOMEM;
        }
 
        /* Fill in src buffer */
-       for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+       for (i = 0; i < PAGE_SIZE; i++)
                ((u8 *) src)[i] = (u8)i;
 
        dma_chan = &mv_chan->dmachan;
@@ -819,14 +813,26 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
-       dest_dma = dma_map_single(dma_chan->device->dev, dest,
-                                 MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, 2, GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
+       src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
+                                PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->to_cnt = 1;
+       unmap->addr[0] = src_dma;
 
-       src_dma = dma_map_single(dma_chan->device->dev, src,
-                                MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+       dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
+                                 PAGE_SIZE, DMA_FROM_DEVICE);
+       unmap->from_cnt = 1;
+       unmap->addr[1] = dest_dma;
+
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
-                                   MV_XOR_TEST_SIZE, 0);
+                                   PAGE_SIZE, 0);
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
        async_tx_ack(tx);
@@ -841,8 +847,8 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
        dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
-                               MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
-       if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+                               PAGE_SIZE, DMA_FROM_DEVICE);
+       if (memcmp(src, dest, PAGE_SIZE)) {
                dev_err(dma_chan->device->dev,
                        "Self-test copy failed compare, disabling\n");
                err = -ENODEV;
@@ -850,6 +856,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
        kfree(src);
@@ -867,13 +874,15 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
        dma_addr_t dest_dma;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        u8 cmp_byte = 0;
        u32 cmp_word;
        int err = 0;
+       int src_count = MV_XOR_NUM_SRC_TEST;
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
                if (!xor_srcs[src_idx]) {
                        while (src_idx--)
@@ -890,13 +899,13 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
        /* Fill in src buffers */
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                u8 *ptr = page_address(xor_srcs[src_idx]);
                for (i = 0; i < PAGE_SIZE; i++)
                        ptr[i] = (1 << src_idx);
        }
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+       for (src_idx = 0; src_idx < src_count; src_idx++)
                cmp_byte ^= (u8) (1 << src_idx);
 
        cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
@@ -910,16 +919,29 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, src_count + 1,
+                                        GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
        /* test xor */
-       dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
-                               DMA_FROM_DEVICE);
+       for (i = 0; i < src_count; i++) {
+               unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+                                             0, PAGE_SIZE, DMA_TO_DEVICE);
+               dma_srcs[i] = unmap->addr[i];
+               unmap->to_cnt++;
+       }
 
-       for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
-                                          0, PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+                                     DMA_FROM_DEVICE);
+       dest_dma = unmap->addr[src_count];
+       unmap->from_cnt = 1;
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
-                                MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+                                src_count, PAGE_SIZE, 0);
 
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
@@ -948,9 +970,10 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
-       src_idx = MV_XOR_NUM_SRC_TEST;
+       src_idx = src_count;
        while (src_idx--)
                __free_page(xor_srcs[src_idx]);
        __free_page(dest);
@@ -1176,6 +1199,7 @@ static int mv_xor_probe(struct platform_device *pdev)
                int i = 0;
 
                for_each_child_of_node(pdev->dev.of_node, np) {
+                       struct mv_xor_chan *chan;
                        dma_cap_mask_t cap_mask;
                        int irq;
 
@@ -1193,21 +1217,21 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
-                               xordev->channels[i] = NULL;
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                irq_dispose_mapping(irq);
                                goto err_channel_add;
                        }
 
+                       xordev->channels[i] = chan;
                        i++;
                }
        } else if (pdata && pdata->channels) {
                for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
                        struct mv_xor_channel_data *cd;
+                       struct mv_xor_chan *chan;
                        int irq;
 
                        cd = &pdata->channels[i];
@@ -1222,13 +1246,14 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cd->cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cd->cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                goto err_channel_add;
                        }
+
+                       xordev->channels[i] = chan;
                }
        }
 
index 0b88dd3d05f4880f41561f455f79c5eb9ca0a885..e8fe9dc455f4d8989e6d75618fecdd7ce351647f 100644 (file)
@@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
  * @np:                device node to get DMA request from
  * @name:      name of desired channel
  *
- * Returns pointer to appropriate dma channel on success or NULL on error.
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
  */
 struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                                              const char *name)
@@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
        struct of_dma           *ofdma;
        struct dma_chan         *chan;
        int                     count, i;
+       int                     ret_no_channel = -ENODEV;
 
        if (!np || !name) {
                pr_err("%s: not enough information provided\n", __func__);
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        count = of_property_count_strings(np, "dma-names");
        if (count < 0) {
                pr_err("%s: dma-names property of node '%s' missing or empty\n",
                        __func__, np->full_name);
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        for (i = 0; i < count; i++) {
@@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                mutex_lock(&of_dma_lock);
                ofdma = of_dma_find_controller(&dma_spec);
 
-               if (ofdma)
+               if (ofdma) {
                        chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
-               else
+               } else {
+                       ret_no_channel = -EPROBE_DEFER;
                        chan = NULL;
+               }
 
                mutex_unlock(&of_dma_lock);
 
@@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                        return chan;
        }
 
-       return NULL;
+       return ERR_PTR(ret_no_channel);
 }
 
 /**
index cdf0483b8f2dfb8f746b786fd6bf84b0d5f6657b..c90edecee4633c3b7d9b76777534ab424a66ac7a 100644 (file)
@@ -2492,12 +2492,9 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static inline void _init_desc(struct dma_pl330_desc *desc)
 {
-       desc->pchan = NULL;
        desc->req.x = &desc->px;
        desc->req.token = desc;
        desc->rqcfg.swap = SWAP_NO;
-       desc->rqcfg.privileged = 0;
-       desc->rqcfg.insnaccess = 0;
        desc->rqcfg.scctl = SCCTRL0;
        desc->rqcfg.dcctl = DCCTRL0;
        desc->req.cfg = &desc->rqcfg;
@@ -2517,7 +2514,7 @@ static int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
        if (!pdmac)
                return 0;
 
-       desc = kmalloc(count * sizeof(*desc), flg);
+       desc = kcalloc(count, sizeof(*desc), flg);
        if (!desc)
                return 0;
 
@@ -2887,6 +2884,7 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan,
        caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
        caps->cmd_pause = false;
        caps->cmd_terminate = true;
+       caps->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
 
        return 0;
 }
index 8da48c6b2a38ccd76f3e127d53e4be5ab7be425c..8bba298535b0984e241793403af6920399d7366d 100644 (file)
@@ -532,29 +532,6 @@ static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc,
        hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
 }
 
-/**
- * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation
- */
-static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc,
-                                       int value, unsigned long flags)
-{
-       struct dma_cdb *hw_desc = desc->hw_desc;
-
-       memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
-       desc->hw_next = NULL;
-       desc->src_cnt = 1;
-       desc->dst_cnt = 1;
-
-       if (flags & DMA_PREP_INTERRUPT)
-               set_bit(PPC440SPE_DESC_INT, &desc->flags);
-       else
-               clear_bit(PPC440SPE_DESC_INT, &desc->flags);
-
-       hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value);
-       hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value);
-       hw_desc->opc = DMA_CDB_OPC_DFILL128;
-}
-
 /**
  * ppc440spe_desc_set_src_addr - set source address into the descriptor
  */
@@ -1504,8 +1481,6 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
                struct ppc440spe_adma_chan *chan,
                dma_cookie_t cookie)
 {
-       int i;
-
        BUG_ON(desc->async_tx.cookie < 0);
        if (desc->async_tx.cookie > 0) {
                cookie = desc->async_tx.cookie;
@@ -3898,7 +3873,7 @@ static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev)
                        ppc440spe_adma_prep_dma_interrupt;
        }
        pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: "
-         "( %s%s%s%s%s%s%s)\n",
+         "( %s%s%s%s%s%s)\n",
          dev_name(adev->dev),
          dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "",
          dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "",
index 4cb12797863678be86af66017ec2cffb54f5dd16..4eddedb6eb7dd3deb68550c1b8065e8b9d882278 100644 (file)
@@ -628,42 +628,13 @@ retry:
        s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
 }
 
-static void s3c24xx_dma_unmap_buffers(struct s3c24xx_txd *txd)
-{
-       struct device *dev = txd->vd.tx.chan->device->dev;
-       struct s3c24xx_sg *dsg;
-
-       if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
-               if (txd->vd.tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_single(dev, dsg->src_addr, dsg->len,
-                                               DMA_TO_DEVICE);
-               else {
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_page(dev, dsg->src_addr, dsg->len,
-                                               DMA_TO_DEVICE);
-               }
-       }
-
-       if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
-               if (txd->vd.tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_single(dev, dsg->dst_addr, dsg->len,
-                                               DMA_FROM_DEVICE);
-               else
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_page(dev, dsg->dst_addr, dsg->len,
-                                               DMA_FROM_DEVICE);
-       }
-}
-
 static void s3c24xx_dma_desc_free(struct virt_dma_desc *vd)
 {
        struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
        struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(vd->tx.chan);
 
        if (!s3cchan->slave)
-               s3c24xx_dma_unmap_buffers(txd);
+               dma_descriptor_unmap(&vd->tx);
 
        s3c24xx_dma_free_txd(txd);
 }
@@ -795,7 +766,7 @@ static enum dma_status s3c24xx_dma_tx_status(struct dma_chan *chan,
 
        spin_lock_irqsave(&s3cchan->vc.lock, flags);
        ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret == DMA_SUCCESS) {
+       if (ret == DMA_COMPLETE) {
                spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
                return ret;
        }
index ebad84591a6e22bd1f28866c3f0b1946eba3dff0..3083d901a414f000a54e0337e02973a4586399bf 100644 (file)
@@ -60,6 +60,7 @@
 #define HPB_DMAE_DSTPR_DMSTP   BIT(0)
 
 /* DMA status register (DSTSR) bits */
+#define HPB_DMAE_DSTSR_DQSTS   BIT(2)
 #define HPB_DMAE_DSTSR_DMSTS   BIT(0)
 
 /* DMA common registers */
@@ -286,6 +287,9 @@ static void hpb_dmae_halt(struct shdma_chan *schan)
 
        ch_reg_write(chan, HPB_DMAE_DCMDR_DQEND, HPB_DMAE_DCMDR);
        ch_reg_write(chan, HPB_DMAE_DSTPR_DMSTP, HPB_DMAE_DSTPR);
+
+       chan->plane_idx = 0;
+       chan->first_desc = true;
 }
 
 static const struct hpb_dmae_slave_config *
@@ -385,7 +389,10 @@ static bool hpb_dmae_channel_busy(struct shdma_chan *schan)
        struct hpb_dmae_chan *chan = to_chan(schan);
        u32 dstsr = ch_reg_read(chan, HPB_DMAE_DSTSR);
 
-       return (dstsr & HPB_DMAE_DSTSR_DMSTS) == HPB_DMAE_DSTSR_DMSTS;
+       if (chan->xfer_mode == XFER_DOUBLE)
+               return dstsr & HPB_DMAE_DSTSR_DQSTS;
+       else
+               return dstsr & HPB_DMAE_DSTSR_DMSTS;
 }
 
 static int
@@ -510,6 +517,8 @@ static int hpb_dmae_chan_probe(struct hpb_dmae_device *hpbdev, int id)
        }
 
        schan = &new_hpb_chan->shdma_chan;
+       schan->max_xfer_len = HPB_DMA_TCR_MAX;
+
        shdma_chan_probe(sdev, schan, id);
 
        if (pdev->id >= 0)
index bae6c29f5502ab951f7926bdf621977703bc96b1..17686caf64d5c4beedd0d189dd4487a57acb1254 100644 (file)
@@ -406,7 +406,6 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
        dma_async_tx_callback callback;
        void *param;
        struct dma_async_tx_descriptor *txd = &desc->txd;
-       struct txx9dmac_slave *ds = dc->chan.private;
 
        dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
                 txd->cookie, desc);
index 8472405c558612e949e5be4caa6a6ac7c889c335..d7f1b57bd3be07a36036e459e4682455eeb220c3 100644 (file)
@@ -945,7 +945,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        u32                     tad_offset;
        u32                     rir_way;
        u32                     mb, kb;
-       u64                     ch_addr, offset, limit, prv = 0;
+       u64                     ch_addr, offset, limit = 0, prv = 0;
 
 
        /*
index 3c55ec856e39c714e7b474f081c01180b9aa9e2d..a287cece0593c327c53e8961b70a0dde8b1af2ce 100644 (file)
@@ -1082,7 +1082,7 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
 static int arizona_extcon_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
-       struct arizona_pdata *pdata;
+       struct arizona_pdata *pdata = &arizona->pdata;
        struct arizona_extcon_info *info;
        unsigned int val;
        int jack_irq_fall, jack_irq_rise;
@@ -1091,8 +1091,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
        if (!arizona->dapm || !arizona->dapm->card)
                return -EPROBE_DEFER;
 
-       pdata = dev_get_platdata(arizona->dev);
-
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (!info) {
                dev_err(&pdev->dev, "Failed to allocate memory\n");
index 15443d3b6be18049ddddbb7ec035eb05ce7dc409..76322330cbd7a10b427ff5d011b83abbd0abb0e8 100644 (file)
@@ -792,6 +792,8 @@ void extcon_dev_unregister(struct extcon_dev *edev)
                return;
        }
 
+       device_unregister(&edev->dev);
+
        if (edev->mutually_exclusive && edev->max_supported) {
                for (index = 0; edev->mutually_exclusive[index];
                                index++)
@@ -812,7 +814,6 @@ void extcon_dev_unregister(struct extcon_dev *edev)
        if (switch_class)
                class_compat_remove_link(switch_class, &edev->dev, NULL);
 #endif
-       device_unregister(&edev->dev);
        put_device(&edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
index 299fad6b5867287f0869648e4a99eaa9b581d872..5373dc5b60114f31af5cf66cdbb923bdc6b0f973 100644 (file)
@@ -14,3 +14,4 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
 obj-$(CONFIG_EFI)              += efi/
+obj-$(CONFIG_UEFI_CPER)                += efi/
index 3150aa4874e8f67e4360635934acdcb11bac6fef..6aecbc86ec9482f322e55735de02c9daa1e4775a 100644 (file)
@@ -36,7 +36,7 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE
          backend for pstore by default. This setting can be overridden
          using the efivars module's pstore_disable parameter.
 
-config UEFI_CPER
-       def_bool n
-
 endmenu
+
+config UEFI_CPER
+       bool
index 9ba156d3c7755e6854595b9983fc23db20fa2111..6c2a41ec21baf63989e9d676b569a21132c006c8 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for linux kernel
 #
-obj-y                                  += efi.o vars.o
+obj-$(CONFIG_EFI)                      += efi.o vars.o
 obj-$(CONFIG_EFI_VARS)                 += efivars.o
 obj-$(CONFIG_EFI_VARS_PSTORE)          += efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)                        += cper.o
index 5002d50e37817314d1fe3e449ad991ade1969f6b..4b9dc836dcf956e86c3800398946d40b0d1cf6dc 100644 (file)
@@ -18,14 +18,12 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
-       efivar_entry_iter_begin();
        psi->data = NULL;
        return 0;
 }
 
 static int efi_pstore_close(struct pstore_info *psi)
 {
-       efivar_entry_iter_end();
        psi->data = NULL;
        return 0;
 }
@@ -39,6 +37,12 @@ struct pstore_read_data {
        char **buf;
 };
 
+static inline u64 generic_id(unsigned long timestamp,
+                            unsigned int part, int count)
+{
+       return (timestamp * 100 + part) * 1000 + count;
+}
+
 static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 {
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
@@ -57,7 +61,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 
        if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
                   cb_data->type, &part, &cnt, &time, &data_type) == 5) {
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, cnt);
                *cb_data->count = cnt;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -67,7 +71,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
                        *cb_data->compressed = false;
        } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
                   cb_data->type, &part, &cnt, &time) == 4) {
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, cnt);
                *cb_data->count = cnt;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -79,7 +83,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
                 * which doesn't support holding
                 * multiple logs, remains.
                 */
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, 0);
                *cb_data->count = 0;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -91,19 +95,125 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
        __efivar_entry_get(entry, &entry->var.Attributes,
                           &entry->var.DataSize, entry->var.Data);
        size = entry->var.DataSize;
+       memcpy(*cb_data->buf, entry->var.Data,
+              (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
 
-       *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL);
-       if (*cb_data->buf == NULL)
-               return -ENOMEM;
        return size;
 }
 
+/**
+ * efi_pstore_scan_sysfs_enter
+ * @entry: scanning entry
+ * @next: next entry
+ * @head: list head
+ */
+static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos,
+                                       struct efivar_entry *next,
+                                       struct list_head *head)
+{
+       pos->scanning = true;
+       if (&next->list != head)
+               next->scanning = true;
+}
+
+/**
+ * __efi_pstore_scan_sysfs_exit
+ * @entry: deleting entry
+ * @turn_off_scanning: Check if a scanning flag should be turned off
+ */
+static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
+                                               bool turn_off_scanning)
+{
+       if (entry->deleting) {
+               list_del(&entry->list);
+               efivar_entry_iter_end();
+               efivar_unregister(entry);
+               efivar_entry_iter_begin();
+       } else if (turn_off_scanning)
+               entry->scanning = false;
+}
+
+/**
+ * efi_pstore_scan_sysfs_exit
+ * @pos: scanning entry
+ * @next: next entry
+ * @head: list head
+ * @stop: a flag checking if scanning will stop
+ */
+static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
+                                      struct efivar_entry *next,
+                                      struct list_head *head, bool stop)
+{
+       __efi_pstore_scan_sysfs_exit(pos, true);
+       if (stop)
+               __efi_pstore_scan_sysfs_exit(next, &next->list != head);
+}
+
+/**
+ * efi_pstore_sysfs_entry_iter
+ *
+ * @data: function-specific data to pass to callback
+ * @pos: entry to begin iterating from
+ *
+ * You MUST call efivar_enter_iter_begin() before this function, and
+ * efivar_entry_iter_end() afterwards.
+ *
+ * It is possible to begin iteration from an arbitrary entry within
+ * the list by passing @pos. @pos is updated on return to point to
+ * the next entry of the last one passed to efi_pstore_read_func().
+ * To begin iterating from the beginning of the list @pos must be %NULL.
+ */
+static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
+{
+       struct efivar_entry *entry, *n;
+       struct list_head *head = &efivar_sysfs_list;
+       int size = 0;
+
+       if (!*pos) {
+               list_for_each_entry_safe(entry, n, head, list) {
+                       efi_pstore_scan_sysfs_enter(entry, n, head);
+
+                       size = efi_pstore_read_func(entry, data);
+                       efi_pstore_scan_sysfs_exit(entry, n, head, size < 0);
+                       if (size)
+                               break;
+               }
+               *pos = n;
+               return size;
+       }
+
+       list_for_each_entry_safe_from((*pos), n, head, list) {
+               efi_pstore_scan_sysfs_enter((*pos), n, head);
+
+               size = efi_pstore_read_func((*pos), data);
+               efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
+               if (size)
+                       break;
+       }
+       *pos = n;
+       return size;
+}
+
+/**
+ * efi_pstore_read
+ *
+ * This function returns a size of NVRAM entry logged via efi_pstore_write().
+ * The meaning and behavior of efi_pstore/pstore are as below.
+ *
+ * size > 0: Got data of an entry logged via efi_pstore_write() successfully,
+ *           and pstore filesystem will continue reading subsequent entries.
+ * size == 0: Entry was not logged via efi_pstore_write(),
+ *            and efi_pstore driver will continue reading subsequent entries.
+ * size < 0: Failed to get data of entry logging via efi_pstore_write(),
+ *           and pstore will stop reading entry.
+ */
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
                               int *count, struct timespec *timespec,
                               char **buf, bool *compressed,
                               struct pstore_info *psi)
 {
        struct pstore_read_data data;
+       ssize_t size;
 
        data.id = id;
        data.type = type;
@@ -112,8 +222,17 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
        data.compressed = compressed;
        data.buf = buf;
 
-       return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data,
-                                  (struct efivar_entry **)&psi->data);
+       *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
+       if (!*data.buf)
+               return -ENOMEM;
+
+       efivar_entry_iter_begin();
+       size = efi_pstore_sysfs_entry_iter(&data,
+                                          (struct efivar_entry **)&psi->data);
+       efivar_entry_iter_end();
+       if (size <= 0)
+               kfree(*data.buf);
+       return size;
 }
 
 static int efi_pstore_write(enum pstore_type_id type,
@@ -184,9 +303,17 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
                        return 0;
        }
 
+       if (entry->scanning) {
+               /*
+                * Skip deletion because this entry will be deleted
+                * after scanning is completed.
+                */
+               entry->deleting = true;
+       } else
+               list_del(&entry->list);
+
        /* found */
        __efivar_entry_delete(entry);
-       list_del(&entry->list);
 
        return 1;
 }
@@ -199,14 +326,16 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
        char name[DUMP_NAME_LEN];
        efi_char16_t efi_name[DUMP_NAME_LEN];
        int found, i;
+       unsigned int part;
 
-       sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
-               time.tv_sec);
+       do_div(id, 1000);
+       part = do_div(id, 100);
+       sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec);
 
        for (i = 0; i < DUMP_NAME_LEN; i++)
                efi_name[i] = name[i];
 
-       edata.id = id;
+       edata.id = part;
        edata.type = type;
        edata.count = count;
        edata.time = time;
@@ -214,10 +343,12 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 
        efivar_entry_iter_begin();
        found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry);
-       efivar_entry_iter_end();
 
-       if (found)
+       if (found && !entry->scanning) {
+               efivar_entry_iter_end();
                efivar_unregister(entry);
+       } else
+               efivar_entry_iter_end();
 
        return 0;
 }
@@ -225,6 +356,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info efi_pstore_info = {
        .owner          = THIS_MODULE,
        .name           = "efi",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = efi_pstore_open,
        .close          = efi_pstore_close,
        .read           = efi_pstore_read,
index 933eb027d527d53aa8fb275b84c5d9b6e2ce3602..3dc24823919749ebb110f62b9ca5696cdaf67511 100644 (file)
@@ -383,12 +383,16 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
        else if (__efivar_entry_delete(entry))
                err = -EIO;
 
-       efivar_entry_iter_end();
-
-       if (err)
+       if (err) {
+               efivar_entry_iter_end();
                return err;
+       }
 
-       efivar_unregister(entry);
+       if (!entry->scanning) {
+               efivar_entry_iter_end();
+               efivar_unregister(entry);
+       } else
+               efivar_entry_iter_end();
 
        /* It's dead Jim.... */
        return count;
index 391c67b182d9b282681890cd04b98c0183023abc..b22659cccca42ebf85e3b54e52249b581b786409 100644 (file)
@@ -683,8 +683,16 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
        if (!found)
                return NULL;
 
-       if (remove)
-               list_del(&entry->list);
+       if (remove) {
+               if (entry->scanning) {
+                       /*
+                        * The entry will be deleted
+                        * after scanning is completed.
+                        */
+                       entry->deleting = true;
+               } else
+                       list_del(&entry->list);
+       }
 
        return entry;
 }
index 72c927dc3be1b104c53e04bec683aa37c9c92343..54c18c220a60575d0ebc63f952937d816132f89c 100644 (file)
@@ -158,7 +158,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
        spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
        /* return the specified bit status */
-       return !!(val & bit);
+       return !!(val & BIT(bit));
 }
 
 static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
index 8847adf392b7ecf823f9f603314c76001367203f..84be70157ad6b6e9809bd007c422e223c359d429 100644 (file)
@@ -327,7 +327,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
         * NOTE:  we assume for now that only irqs in the first gpio_chip
         * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
         */
-       if (offset < d->irq_base)
+       if (offset < d->gpio_unbanked)
                return d->gpio_irq + offset;
        else
                return -ENODEV;
@@ -419,6 +419,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 
                /* pass "bank 0" GPIO IRQs to AINTC */
                chips[0].chip.to_irq = gpio_to_irq_unbanked;
+               chips[0].gpio_irq = bank_irq;
+               chips[0].gpio_unbanked = pdata->gpio_unbanked;
                binten = BIT(0);
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
index 914e859e3eda38724642a8bdf60ea8bb7d4adcd6..d7d6d72eba33e89306168a16f16f487e445bb183 100644 (file)
@@ -70,10 +70,14 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
        u32 val;
        struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+       u32 out_mask, out_shadow;
 
-       val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+       out_mask = in_be32(mm->regs + GPIO_DIR);
 
-       return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+       val = in_be32(mm->regs + GPIO_DAT) & ~out_mask;
+       out_shadow = mpc8xxx_gc->data & out_mask;
+
+       return (val | out_shadow) & mpc8xxx_gpio2mask(gpio);
 }
 
 static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
index f7a0cc4da9502d12ef0aa602dfa249665e5a5c4a..2baf0ddf7e0230f2b334fc9e25dfca3bbe0205c9 100644 (file)
@@ -102,7 +102,7 @@ struct msm_gpio_dev {
        DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO);
        DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
        struct irq_domain *domain;
-       unsigned int summary_irq;
+       int summary_irq;
        void __iomem *msm_tlmm_base;
 };
 
@@ -252,7 +252,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
-       clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+       clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
        __clear_bit(gpio, msm_gpio.enabled_irqs);
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
@@ -264,7 +264,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        __set_bit(gpio, msm_gpio.enabled_irqs);
-       set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+       set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
        writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
index 3c3321f94053ab68f0ab0e691afc1ddf2b83f0e9..db3129043e635c2bc9c7f6a7c3ffd111de5dc6f4 100644 (file)
@@ -79,7 +79,7 @@ struct mvebu_gpio_chip {
        spinlock_t         lock;
        void __iomem      *membase;
        void __iomem      *percpu_membase;
-       unsigned int       irqbase;
+       int                irqbase;
        struct irq_domain *domain;
        int                soc_variant;
 };
index f22f7f3e2e531592ffb313c253c50e75b73b3337..b4d42112d02d5c3388849eac299245f30f193ac8 100644 (file)
@@ -286,11 +286,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
        if (!chip->base)
                return -ENOMEM;
 
-       chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
-                                            irq_base, &pl061_domain_ops, chip);
-       if (!chip->domain)
-               return -ENODEV;
-
        spin_lock_init(&chip->lock);
 
        chip->gc.request = pl061_gpio_request;
@@ -320,6 +315,11 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
        irq_set_chained_handler(irq, pl061_irq_handler);
        irq_set_handler_data(irq, chip);
 
+       chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
+                                            irq_base, &pl061_domain_ops, chip);
+       if (!chip->domain)
+               return -ENODEV;
+
        for (i = 0; i < PL061_GPIO_NR; i++) {
                if (pdata) {
                        if (pdata->directions & (1 << i))
index d3f15ae93bd3bef20a5aa306fa02e1a7fe12b838..8b7e719a68c3662f454c76b3e82b9569abeb22f8 100644 (file)
@@ -169,7 +169,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
        u32 pending;
        unsigned int offset, irqs_handled = 0;
 
-       while ((pending = gpio_rcar_read(p, INTDT))) {
+       while ((pending = gpio_rcar_read(p, INTDT) &
+                         gpio_rcar_read(p, INTMSK))) {
                offset = __ffs(pending);
                gpio_rcar_write(p, INTCLR, BIT(offset));
                generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
@@ -381,7 +382,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
        if (!p->irq_domain) {
                ret = -ENXIO;
                dev_err(&pdev->dev, "cannot initialize irq domain\n");
-               goto err1;
+               goto err0;
        }
 
        if (devm_request_irq(&pdev->dev, irq->start,
index 0502b9a041a50a199b40f4d3bf956bcd81dc7fdf..da071ddbad9985670843087ee3652844958b3827 100644 (file)
@@ -132,6 +132,7 @@ static int tb10x_gpio_direction_out(struct gpio_chip *chip,
        int mask = BIT(offset);
        int val = TB10X_GPIO_DIR_OUT << offset;
 
+       tb10x_gpio_set(chip, offset, value);
        tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val);
 
        return 0;
index 0c7e891c8651042a8f32e5e6ecf7344cabf6493e..f9996899c1f29cd26e7267cbeb349378c6e26bb4 100644 (file)
@@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
        if (offset < TWL4030_GPIO_MAX)
                ret = twl4030_set_gpio_direction(offset, 1);
        else
-               ret = -EINVAL;
+               ret = -EINVAL;  /* LED outputs can't be set as input */
 
        if (!ret)
                priv->direction &= ~BIT(offset);
@@ -354,17 +354,27 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
 static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
+       int ret = 0;
 
        mutex_lock(&priv->mutex);
-       if (offset < TWL4030_GPIO_MAX)
-               twl4030_set_gpio_dataout(offset, value);
+       if (offset < TWL4030_GPIO_MAX) {
+               ret = twl4030_set_gpio_direction(offset, 0);
+               if (ret) {
+                       mutex_unlock(&priv->mutex);
+                       return ret;
+               }
+       }
+
+       /*
+        *  LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output
+        */
 
        priv->direction |= BIT(offset);
        mutex_unlock(&priv->mutex);
 
        twl_set(chip, offset, value);
 
-       return 0;
+       return ret;
 }
 
 static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -435,7 +445,8 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
 
 static int gpio_twl4030_remove(struct platform_device *pdev);
 
-static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
+static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev,
+                               struct twl4030_gpio_platform_data *pdata)
 {
        struct twl4030_gpio_platform_data *omap_twl_info;
 
@@ -443,6 +454,9 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
        if (!omap_twl_info)
                return NULL;
 
+       if (pdata)
+               *omap_twl_info = *pdata;
+
        omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
                        "ti,use-leds");
 
@@ -500,7 +514,7 @@ no_irqs:
        mutex_init(&priv->mutex);
 
        if (node)
-               pdata = of_gpio_twl4030(&pdev->dev);
+               pdata = of_gpio_twl4030(&pdev->dev, pdata);
 
        if (pdata == NULL) {
                dev_err(&pdev->dev, "Platform data is missing\n");
index 1a605f2a0f55f8fac1675dd18f37dae366215edc..06fb5cf99dede237bd29f109bbd195bfa2230f5b 100644 (file)
@@ -105,3 +105,4 @@ module_platform_driver(ucb1400_gpio_driver);
 
 MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ucb1400_gpio");
index 4e10b10d3ddde47332f525285e1c549bd9a2c22f..85f772c0b26a619ec9c563f77f35c22fb8975e7f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/idr.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
+#include <linux/gpio/driver.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/gpio.h>
@@ -1308,6 +1309,18 @@ struct gpio_chip *gpiochip_find(void *data,
 }
 EXPORT_SYMBOL_GPL(gpiochip_find);
 
+static int gpiochip_match_name(struct gpio_chip *chip, void *data)
+{
+       const char *name = data;
+
+       return !strcmp(chip->label, name);
+}
+
+static struct gpio_chip *find_chip_by_name(const char *name)
+{
+       return gpiochip_find((void *)name, gpiochip_match_name);
+}
+
 #ifdef CONFIG_PINCTRL
 
 /**
@@ -1341,8 +1354,10 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip,
        ret = pinctrl_get_group_pins(pctldev, pin_group,
                                        &pin_range->range.pins,
                                        &pin_range->range.npins);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(pin_range);
                return ret;
+       }
 
        pinctrl_add_gpio_range(pctldev, &pin_range->range);
 
@@ -2260,26 +2275,10 @@ void gpiod_add_table(struct gpiod_lookup *table, size_t size)
        mutex_unlock(&gpio_lookup_lock);
 }
 
-/*
- * Caller must have a acquired gpio_lookup_lock
- */
-static struct gpio_chip *find_chip_by_name(const char *name)
-{
-       struct gpio_chip *chip = NULL;
-
-       list_for_each_entry(chip, &gpio_lookup_list, list) {
-               if (chip->label == NULL)
-                       continue;
-               if (!strcmp(chip->label, name))
-                       break;
-       }
-
-       return chip;
-}
-
 #ifdef CONFIG_OF
 static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
-                                     unsigned int idx, unsigned long *flags)
+                                     unsigned int idx,
+                                     enum gpio_lookup_flags *flags)
 {
        char prop_name[32]; /* 32 is max size of property name */
        enum of_gpio_flags of_flags;
@@ -2297,20 +2296,22 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
                return desc;
 
        if (of_flags & OF_GPIO_ACTIVE_LOW)
-               *flags |= GPIOF_ACTIVE_LOW;
+               *flags |= GPIO_ACTIVE_LOW;
 
        return desc;
 }
 #else
 static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
-                                     unsigned int idx, unsigned long *flags)
+                                     unsigned int idx,
+                                     enum gpio_lookup_flags *flags)
 {
        return ERR_PTR(-ENODEV);
 }
 #endif
 
 static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
-                                       unsigned int idx, unsigned long *flags)
+                                       unsigned int idx,
+                                       enum gpio_lookup_flags *flags)
 {
        struct acpi_gpio_info info;
        struct gpio_desc *desc;
@@ -2320,13 +2321,14 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
                return desc;
 
        if (info.gpioint && info.active_low)
-               *flags |= GPIOF_ACTIVE_LOW;
+               *flags |= GPIO_ACTIVE_LOW;
 
        return desc;
 }
 
 static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
-                                   unsigned int idx, unsigned long *flags)
+                                   unsigned int idx,
+                                   enum gpio_lookup_flags *flags)
 {
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct gpio_desc *desc = ERR_PTR(-ENODEV);
@@ -2366,7 +2368,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
                                continue;
                        }
 
-                       if (chip->ngpio >= p->chip_hwnum) {
+                       if (chip->ngpio <= p->chip_hwnum) {
                                dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
                                         chip->label, chip->ngpio);
                                continue;
@@ -2416,9 +2418,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx)
 {
-       struct gpio_desc *desc;
+       struct gpio_desc *desc = NULL;
        int status;
-       unsigned long flags = 0;
+       enum gpio_lookup_flags flags = 0;
 
        dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
 
@@ -2429,13 +2431,23 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
        } else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
                dev_dbg(dev, "using ACPI for GPIO lookup\n");
                desc = acpi_find_gpio(dev, con_id, idx, &flags);
-       } else {
+       }
+
+       /*
+        * Either we are not using DT or ACPI, or their lookup did not return
+        * a result. In that case, use platform lookup as a fallback.
+        */
+       if (!desc || IS_ERR(desc)) {
+               struct gpio_desc *pdesc;
                dev_dbg(dev, "using lookup tables for GPIO lookup");
-               desc = gpiod_find(dev, con_id, idx, &flags);
+               pdesc = gpiod_find(dev, con_id, idx, &flags);
+               /* If used as fallback, do not replace the previous error */
+               if (!IS_ERR(pdesc) || !desc)
+                       desc = pdesc;
        }
 
        if (IS_ERR(desc)) {
-               dev_warn(dev, "lookup for GPIO %s failed\n", con_id);
+               dev_dbg(dev, "lookup for GPIO %s failed\n", con_id);
                return desc;
        }
 
@@ -2444,8 +2456,12 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
        if (status < 0)
                return ERR_PTR(status);
 
-       if (flags & GPIOF_ACTIVE_LOW)
+       if (flags & GPIO_ACTIVE_LOW)
                set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+       if (flags & GPIO_OPEN_DRAIN)
+               set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+       if (flags & GPIO_OPEN_SOURCE)
+               set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 
        return desc;
 }
index eef09ec9a5ff03691f259031d6b0dc5337e4fb02..a72cae03b99b781d7becf0987c91317c3777a65c 100644 (file)
@@ -103,6 +103,7 @@ void armada_drm_queue_unref_work(struct drm_device *,
 extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs;
 
 int armada_fbdev_init(struct drm_device *);
+void armada_fbdev_lastclose(struct drm_device *);
 void armada_fbdev_fini(struct drm_device *);
 
 int armada_overlay_plane_create(struct drm_device *, unsigned long);
index 4f2b28354915c68fcbc730af9ef8b50142ef26bb..62d0ff3efddf9bb5a08e1b209b5a40c6b8148e47 100644 (file)
@@ -321,6 +321,11 @@ static struct drm_ioctl_desc armada_ioctls[] = {
                DRM_UNLOCKED),
 };
 
+static void armada_drm_lastclose(struct drm_device *dev)
+{
+       armada_fbdev_lastclose(dev);
+}
+
 static const struct file_operations armada_drm_fops = {
        .owner                  = THIS_MODULE,
        .llseek                 = no_llseek,
@@ -337,7 +342,7 @@ static struct drm_driver armada_drm_driver = {
        .open                   = NULL,
        .preclose               = NULL,
        .postclose              = NULL,
-       .lastclose              = NULL,
+       .lastclose              = armada_drm_lastclose,
        .unload                 = armada_drm_unload,
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = armada_drm_enable_vblank,
index dd5ea77dac960c916fd5d8169c625a572a897e05..948cb14c561ec501e10bae0f89adb043dc0b2808 100644 (file)
@@ -105,9 +105,9 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
        drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
        drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
 
-       DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n",
-               dfb->fb.width, dfb->fb.height,
-               dfb->fb.bits_per_pixel, obj->phys_addr);
+       DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n",
+               dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel,
+               (unsigned long long)obj->phys_addr);
 
        return 0;
 
@@ -177,6 +177,16 @@ int armada_fbdev_init(struct drm_device *dev)
        return ret;
 }
 
+void armada_fbdev_lastclose(struct drm_device *dev)
+{
+       struct armada_private *priv = dev->dev_private;
+
+       drm_modeset_lock_all(dev);
+       if (priv->fbdev)
+               drm_fb_helper_restore_fbdev_mode(priv->fbdev);
+       drm_modeset_unlock_all(dev);
+}
+
 void armada_fbdev_fini(struct drm_device *dev)
 {
        struct armada_private *priv = dev->dev_private;
@@ -192,11 +202,11 @@ void armada_fbdev_fini(struct drm_device *dev)
                        framebuffer_release(info);
                }
 
+               drm_fb_helper_fini(fbh);
+
                if (fbh->fb)
                        fbh->fb->funcs->destroy(fbh->fb);
 
-               drm_fb_helper_fini(fbh);
-
                priv->fbdev = NULL;
        }
 }
index 9f2356bae7fdafb5318b172d47535b6b32408e07..887816f43476937fcfbceed5207025b63eccb132 100644 (file)
@@ -172,8 +172,9 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
                obj->dev_addr = obj->linear->start;
        }
 
-       DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n",
-                        obj, obj->phys_addr, obj->dev_addr);
+       DRM_DEBUG_DRIVER("obj %p phys %#llx dev %#llx\n", obj,
+                        (unsigned long long)obj->phys_addr,
+                        (unsigned long long)obj->dev_addr);
 
        return 0;
 }
@@ -557,7 +558,6 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
                         * refcount on the gem object itself.
                         */
                        drm_gem_object_reference(obj);
-                       dma_buf_put(buf);
                        return obj;
                }
        }
@@ -573,6 +573,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
        }
 
        dobj->obj.import_attach = attach;
+       get_dma_buf(buf);
 
        /*
         * Don't call dma_buf_map_attachment() here - it maps the
index fb7cf0e796f668328e7a923dbcada92ba8c2f1c7..8835dcddfac3ab7c3ee1a4ba72360443e730aa74 100644 (file)
@@ -68,6 +68,8 @@
 #define EDID_QUIRK_DETAILED_SYNC_PP            (1 << 6)
 /* Force reduced-blanking timings for detailed modes */
 #define EDID_QUIRK_FORCE_REDUCED_BLANKING      (1 << 7)
+/* Force 8bpc */
+#define EDID_QUIRK_FORCE_8BPC                  (1 << 8)
 
 struct detailed_mode_closure {
        struct drm_connector *connector;
@@ -128,6 +130,9 @@ static struct edid_quirk {
 
        /* Medion MD 30217 PG */
        { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
+
+       /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
+       { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
 };
 
 /*
@@ -2674,7 +2679,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
        int modes = 0;
        u8 cea_mode;
 
-       if (video_db == NULL || video_index > video_len)
+       if (video_db == NULL || video_index >= video_len)
                return 0;
 
        /* CEA modes are numbered 1..127 */
@@ -2701,7 +2706,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
        if (structure & (1 << 8)) {
                newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
                if (newmode) {
-                       newmode->flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
+                       newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
                        drm_mode_probed_add(connector, newmode);
                        modes++;
                }
@@ -3435,6 +3440,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 
        drm_add_display_info(edid, &connector->display_info);
 
+       if (quirks & EDID_QUIRK_FORCE_8BPC)
+               connector->display_info.bpc = 8;
+
        return num_modes;
 }
 EXPORT_SYMBOL(drm_add_edid_modes);
index f53d5246979c386ed632b21c08decb3ab1296f9e..66dd3a001cf1b5ee43ec75f190b03146e7bbe46d 100644 (file)
@@ -566,11 +566,11 @@ err_unload:
        if (dev->driver->unload)
                dev->driver->unload(dev);
 err_primary_node:
-       drm_put_minor(dev->primary);
+       drm_unplug_minor(dev->primary);
 err_render_node:
-       drm_put_minor(dev->render);
+       drm_unplug_minor(dev->render);
 err_control_node:
-       drm_put_minor(dev->control);
+       drm_unplug_minor(dev->control);
 err_agp:
        if (dev->driver->bus->agp_destroy)
                dev->driver->bus->agp_destroy(dev);
index bd2bca395792a600deda6c6f2a1a28314ea89374..c22c3097c3e857ba823cd9c339333983842c4ecf 100644 (file)
@@ -516,7 +516,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
                 minor_str = "card%d";
 
        minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
-       if (!minor->dev) {
+       if (!minor->kdev) {
                r = -ENOMEM;
                goto error;
        }
index b676006a95a0118951f8e12d04f8a6fff0c49fb0..22b8f5eced80f3407b0fa9fc365c1d9e349d7e54 100644 (file)
@@ -172,29 +172,38 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 
 static void exynos_drm_preclose(struct drm_device *dev,
                                        struct drm_file *file)
+{
+       exynos_drm_subdrv_close(dev, file);
+}
+
+static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct exynos_drm_private *private = dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
+       struct drm_pending_vblank_event *v, *vt;
+       struct drm_pending_event *e, *et;
        unsigned long flags;
 
-       /* release events of current file */
+       if (!file->driver_priv)
+               return;
+
+       /* Release all events not unhandled by page flip handler. */
        spin_lock_irqsave(&dev->event_lock, flags);
-       list_for_each_entry_safe(e, t, &private->pageflip_event_list,
+       list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
                        base.link) {
-               if (e->base.file_priv == file) {
-                       list_del(&e->base.link);
-                       e->base.destroy(&e->base);
+               if (v->base.file_priv == file) {
+                       list_del(&v->base.link);
+                       drm_vblank_put(dev, v->pipe);
+                       v->base.destroy(&v->base);
                }
        }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       exynos_drm_subdrv_close(dev, file);
-}
+       /* Release all events handled by page flip handler but not freed. */
+       list_for_each_entry_safe(e, et, &file->event_list, link) {
+               list_del(&e->link);
+               e->destroy(e);
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
-{
-       if (!file->driver_priv)
-               return;
 
        kfree(file->driver_priv);
        file->driver_priv = NULL;
index 23da72b5eae98b0bae1e400ea28d74ed5ee7e472..a61878bf5dcd091cf31ed64a8374d230b580dc1e 100644 (file)
@@ -31,7 +31,7 @@
 #include "exynos_drm_iommu.h"
 
 /*
- * FIMD is stand for Fully Interactive Mobile Display and
+ * FIMD stands for Fully Interactive Mobile Display and
  * as a display controller, it transfers contents drawn on memory
  * to a LCD Panel through Display Interfaces such as RGB or
  * CPU Interface.
index 0cab2d045135b66d0462c88d390e43eff3df7b20..5c648425c1e053616801b3e1e545791a5fe111c0 100644 (file)
@@ -83,6 +83,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
 
+       /*
+        * The dri breadcrumb update races against the drm master disappearing.
+        * Instead of trying to fix this (this is by far not the only ums issue)
+        * just don't do the update in kms mode.
+        */
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
        if (dev->primary->master) {
                master_priv = dev->primary->master->driver_priv;
                if (master_priv->sarea_priv)
@@ -1490,16 +1498,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        mutex_init(&dev_priv->dpio_lock);
-       mutex_init(&dev_priv->rps.hw_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
 
-       mutex_init(&dev_priv->pc8.lock);
-       dev_priv->pc8.requirements_met = false;
-       dev_priv->pc8.gpu_idle = false;
-       dev_priv->pc8.irqs_disabled = false;
-       dev_priv->pc8.enabled = false;
-       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
-       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
+       intel_pm_setup(dev);
 
        intel_display_crc_init(dev);
 
@@ -1603,7 +1604,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        intel_irq_init(dev);
-       intel_pm_init(dev);
        intel_uncore_sanitize(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
@@ -1848,8 +1848,10 @@ void i915_driver_lastclose(struct drm_device * dev)
 
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
+       mutex_lock(&dev->struct_mutex);
        i915_gem_context_close(dev, file_priv);
        i915_gem_release(dev, file_priv);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
index 989be12cdd6e962e625b8376734f101ace947d1c..5b7b7e06cb3a09caec1cd7d5ab90401389df7a40 100644 (file)
@@ -534,8 +534,10 @@ static int i915_drm_freeze(struct drm_device *dev)
                 * Disable CRTCs directly since we want to preserve sw state
                 * for _thaw.
                 */
+               mutex_lock(&dev->mode_config.mutex);
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                        dev_priv->display.crtc_disable(crtc);
+               mutex_unlock(&dev->mode_config.mutex);
 
                intel_modeset_suspend_hw(dev);
        }
@@ -649,6 +651,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
                intel_modeset_init_hw(dev);
 
                drm_modeset_lock_all(dev);
+               drm_mode_config_reset(dev);
                intel_modeset_setup_hw_state(dev, true);
                drm_modeset_unlock_all(dev);
 
index ccdbecca070d2340919d5499f80824ddb84db4ac..90fcccba17b00da4a91ea2556b53a81e877356f0 100644 (file)
@@ -1755,8 +1755,13 @@ struct drm_i915_file_private {
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev)  (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0C00)
-#define IS_ULT(dev)            (IS_HASWELL(dev) && \
+#define IS_BDW_ULT(dev)                (IS_BROADWELL(dev) && \
+                                (((dev)->pdev->device & 0xf) == 0x2  || \
+                                ((dev)->pdev->device & 0xf) == 0x6 || \
+                                ((dev)->pdev->device & 0xf) == 0xe))
+#define IS_HSW_ULT(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0A00)
+#define IS_ULT(dev)            (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
 #define IS_HSW_GT3(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0x00F0) == 0x0020)
 #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
@@ -1901,9 +1906,7 @@ void i915_queue_hangcheck(struct drm_device *dev);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 
 extern void intel_uncore_sanitize(struct drm_device *dev);
 extern void intel_uncore_early_sanitize(struct drm_device *dev);
index 12bbd5eac70db7a22a291dfc5c2e01624803c816..76d3d1ab73c6965063eba62527594dce82dc41d4 100644 (file)
@@ -2343,15 +2343,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
        kfree(request);
 }
 
-static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
-                                     struct intel_ring_buffer *ring)
+static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
+                                      struct intel_ring_buffer *ring)
 {
-       u32 completed_seqno;
-       u32 acthd;
+       u32 completed_seqno = ring->get_seqno(ring, false);
+       u32 acthd = intel_ring_get_active_head(ring);
+       struct drm_i915_gem_request *request;
+
+       list_for_each_entry(request, &ring->request_list, list) {
+               if (i915_seqno_passed(completed_seqno, request->seqno))
+                       continue;
 
-       acthd = intel_ring_get_active_head(ring);
-       completed_seqno = ring->get_seqno(ring, false);
+               i915_set_reset_status(ring, request, acthd);
+       }
+}
 
+static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
+                                       struct intel_ring_buffer *ring)
+{
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
 
@@ -2359,9 +2368,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
                                           struct drm_i915_gem_request,
                                           list);
 
-               if (request->seqno > completed_seqno)
-                       i915_set_reset_status(ring, request, acthd);
-
                i915_gem_free_request(request);
        }
 
@@ -2403,8 +2409,16 @@ void i915_gem_reset(struct drm_device *dev)
        struct intel_ring_buffer *ring;
        int i;
 
+       /*
+        * Before we free the objects from the requests, we need to inspect
+        * them for finding the guilty party. As the requests only borrow
+        * their reference to the objects, the inspection must be done first.
+        */
+       for_each_ring(ring, dev_priv, i)
+               i915_gem_reset_ring_status(dev_priv, ring);
+
        for_each_ring(ring, dev_priv, i)
-               i915_gem_reset_ring_lists(dev_priv, ring);
+               i915_gem_reset_ring_cleanup(dev_priv, ring);
 
        i915_gem_cleanup_ringbuffer(dev);
 
@@ -4442,10 +4456,9 @@ i915_gem_init_hw(struct drm_device *dev)
        if (dev_priv->ellc_size)
                I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
 
-       if (IS_HSW_GT3(dev))
-               I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_ENABLED);
-       else
-               I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_DISABLED);
+       if (IS_HASWELL(dev))
+               I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ?
+                          LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
 
        if (HAS_PCH_NOP(dev)) {
                u32 temp = I915_READ(GEN7_MSG_CTL);
index 72a3df32292f79d88d1ba17dc8d620a24ad435ca..b0f42b9ca037ed472e1a0dd4cd663df6ffd70f06 100644 (file)
@@ -347,10 +347,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
 
-       mutex_lock(&dev->struct_mutex);
        idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
        idr_destroy(&file_priv->context_idr);
-       mutex_unlock(&dev->struct_mutex);
 }
 
 static struct i915_hw_context *
@@ -423,11 +421,21 @@ static int do_switch(struct i915_hw_context *to)
        if (ret)
                return ret;
 
-       /* Clear this page out of any CPU caches for coherent swap-in/out. Note
+       /*
+        * Pin can switch back to the default context if we end up calling into
+        * evict_everything - as a last ditch gtt defrag effort that also
+        * switches to the default context. Hence we need to reload from here.
+        */
+       from = ring->last_context;
+
+       /*
+        * Clear this page out of any CPU caches for coherent swap-in/out. Note
         * that thanks to write = false in this call and us not setting any gpu
         * write domains when putting a context object onto the active list
         * (when switching away from it), this won't block.
-        * XXX: We need a real interface to do this instead of trickery. */
+        *
+        * XXX: We need a real interface to do this instead of trickery.
+        */
        ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
        if (ret) {
                i915_gem_object_unpin(to->obj);
index 7d5752fda5f18b7850beeed588a6f1b3a85cd79a..9bb533e0d76234cdc14ec6d9da31a310114080a5 100644 (file)
@@ -125,13 +125,15 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 
        ret = i915_gem_object_get_pages(obj);
        if (ret)
-               goto error;
+               goto err;
+
+       i915_gem_object_pin_pages(obj);
 
        ret = -ENOMEM;
 
        pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
        if (pages == NULL)
-               goto error;
+               goto err_unpin;
 
        i = 0;
        for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
@@ -141,15 +143,16 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
        drm_free_large(pages);
 
        if (!obj->dma_buf_vmapping)
-               goto error;
+               goto err_unpin;
 
        obj->vmapping_count = 1;
-       i915_gem_object_pin_pages(obj);
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
        return obj->dma_buf_vmapping;
 
-error:
+err_unpin:
+       i915_gem_object_unpin_pages(obj);
+err:
        mutex_unlock(&dev->struct_mutex);
        return ERR_PTR(ret);
 }
index b7376533633d2cd74eeae8442a49588cf1af1cdc..8f3adc7d0dc823bd5e7848f013bda20d1d133cbc 100644 (file)
@@ -88,6 +88,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
        } else
                drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level);
 
+search_again:
        /* First see if there is a large enough contiguous idle region... */
        list_for_each_entry(vma, &vm->inactive_list, mm_list) {
                if (mark_free(vma, &unwind_list))
@@ -115,10 +116,17 @@ none:
                list_del_init(&vma->exec_list);
        }
 
-       /* We expect the caller to unpin, evict all and try again, or give up.
-        * So calling i915_gem_evict_vm() is unnecessary.
+       /* Can we unpin some objects such as idle hw contents,
+        * or pending flips?
         */
-       return -ENOSPC;
+       ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev);
+       if (ret)
+               return ret;
+
+       /* Only idle the GPU and repeat the search once */
+       i915_gem_retire_requests(dev);
+       nonblocking = true;
+       goto search_again;
 
 found:
        /* drm_mm doesn't allow any other other operations while
index 885d595e0e02255e30fbff181247b70df1af5363..a3ba9a8cd68794bbfd163c9236c91c7be9d15965 100644 (file)
@@ -33,6 +33,9 @@
 #include "intel_drv.h"
 #include <linux/dma_remapping.h>
 
+#define  __EXEC_OBJECT_HAS_PIN (1<<31)
+#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
+
 struct eb_vmas {
        struct list_head vmas;
        int and;
@@ -90,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 {
        struct drm_i915_gem_object *obj;
        struct list_head objects;
-       int i, ret = 0;
+       int i, ret;
 
        INIT_LIST_HEAD(&objects);
        spin_lock(&file->table_lock);
@@ -103,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Invalid object handle %d at index %d\n",
                                   exec[i].handle, i);
                        ret = -ENOENT;
-                       goto out;
+                       goto err;
                }
 
                if (!list_empty(&obj->obj_exec_link)) {
@@ -111,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
                                   obj, exec[i].handle, i);
                        ret = -EINVAL;
-                       goto out;
+                       goto err;
                }
 
                drm_gem_object_reference(&obj->base);
@@ -120,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb,
        spin_unlock(&file->table_lock);
 
        i = 0;
-       list_for_each_entry(obj, &objects, obj_exec_link) {
+       while (!list_empty(&objects)) {
                struct i915_vma *vma;
 
+               obj = list_first_entry(&objects,
+                                      struct drm_i915_gem_object,
+                                      obj_exec_link);
+
                /*
                 * NOTE: We can leak any vmas created here when something fails
                 * later on. But that's no issue since vma_unbind can deal with
@@ -135,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb,
                if (IS_ERR(vma)) {
                        DRM_DEBUG("Failed to lookup VMA\n");
                        ret = PTR_ERR(vma);
-                       goto out;
+                       goto err;
                }
 
+               /* Transfer ownership from the objects list to the vmas list. */
                list_add_tail(&vma->exec_list, &eb->vmas);
+               list_del_init(&obj->obj_exec_link);
 
                vma->exec_entry = &exec[i];
                if (eb->and < 0) {
@@ -152,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb,
                ++i;
        }
 
+       return 0;
 
-out:
+
+err:
        while (!list_empty(&objects)) {
                obj = list_first_entry(&objects,
                                       struct drm_i915_gem_object,
                                       obj_exec_link);
                list_del_init(&obj->obj_exec_link);
-               if (ret)
-                       drm_gem_object_unreference(&obj->base);
+               drm_gem_object_unreference(&obj->base);
        }
+       /*
+        * Objects already transfered to the vmas list will be unreferenced by
+        * eb_destroy.
+        */
+
        return ret;
 }
 
@@ -187,7 +202,28 @@ static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle)
        }
 }
 
-static void eb_destroy(struct eb_vmas *eb) {
+static void
+i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
+{
+       struct drm_i915_gem_exec_object2 *entry;
+       struct drm_i915_gem_object *obj = vma->obj;
+
+       if (!drm_mm_node_allocated(&vma->node))
+               return;
+
+       entry = vma->exec_entry;
+
+       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
+               i915_gem_object_unpin_fence(obj);
+
+       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
+               i915_gem_object_unpin(obj);
+
+       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
+}
+
+static void eb_destroy(struct eb_vmas *eb)
+{
        while (!list_empty(&eb->vmas)) {
                struct i915_vma *vma;
 
@@ -195,6 +231,7 @@ static void eb_destroy(struct eb_vmas *eb) {
                                       struct i915_vma,
                                       exec_list);
                list_del_init(&vma->exec_list);
+               i915_gem_execbuffer_unreserve_vma(vma);
                drm_gem_object_unreference(&vma->obj->base);
        }
        kfree(eb);
@@ -478,9 +515,6 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb,
        return ret;
 }
 
-#define  __EXEC_OBJECT_HAS_PIN (1<<31)
-#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
-
 static int
 need_reloc_mappable(struct i915_vma *vma)
 {
@@ -552,26 +586,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
        return 0;
 }
 
-static void
-i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
-{
-       struct drm_i915_gem_exec_object2 *entry;
-       struct drm_i915_gem_object *obj = vma->obj;
-
-       if (!drm_mm_node_allocated(&vma->node))
-               return;
-
-       entry = vma->exec_entry;
-
-       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
-               i915_gem_object_unpin_fence(obj);
-
-       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
-               i915_gem_object_unpin(obj);
-
-       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
-}
-
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                            struct list_head *vmas,
@@ -670,13 +684,14 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                                goto err;
                }
 
-err:           /* Decrement pin count for bound objects */
-               list_for_each_entry(vma, vmas, exec_list)
-                       i915_gem_execbuffer_unreserve_vma(vma);
-
+err:
                if (ret != -ENOSPC || retry++)
                        return ret;
 
+               /* Decrement pin count for bound objects */
+               list_for_each_entry(vma, vmas, exec_list)
+                       i915_gem_execbuffer_unreserve_vma(vma);
+
                ret = i915_gem_evict_vm(vm, true);
                if (ret)
                        return ret;
@@ -708,6 +723,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
        while (!list_empty(&eb->vmas)) {
                vma = list_first_entry(&eb->vmas, struct i915_vma, exec_list);
                list_del_init(&vma->exec_list);
+               i915_gem_execbuffer_unreserve_vma(vma);
                drm_gem_object_unreference(&vma->obj->base);
        }
 
index 3620a1b0a73cbcea019cbd5503250410e51f2807..c79dd2b1f70ecc2af6d0fb67a3c3289672eba7f9 100644 (file)
@@ -57,7 +57,9 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
 #define HSW_WB_LLC_AGE3                        HSW_CACHEABILITY_CONTROL(0x2)
 #define HSW_WB_LLC_AGE0                        HSW_CACHEABILITY_CONTROL(0x3)
 #define HSW_WB_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0xb)
+#define HSW_WB_ELLC_LLC_AGE3           HSW_CACHEABILITY_CONTROL(0x8)
 #define HSW_WT_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0x6)
+#define HSW_WT_ELLC_LLC_AGE3           HSW_CACHEABILITY_CONTROL(0x7)
 
 #define GEN8_PTES_PER_PAGE             (PAGE_SIZE / sizeof(gen8_gtt_pte_t))
 #define GEN8_PDES_PER_PAGE             (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
@@ -185,10 +187,10 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
        case I915_CACHE_NONE:
                break;
        case I915_CACHE_WT:
-               pte |= HSW_WT_ELLC_LLC_AGE0;
+               pte |= HSW_WT_ELLC_LLC_AGE3;
                break;
        default:
-               pte |= HSW_WB_ELLC_LLC_AGE0;
+               pte |= HSW_WB_ELLC_LLC_AGE3;
                break;
        }
 
@@ -335,8 +337,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                kfree(ppgtt->gen8_pt_dma_addr[i]);
        }
 
-       __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT);
-       __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT);
+       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
 }
 
 /**
@@ -1239,6 +1241,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
        bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
        if (bdw_gmch_ctl)
                bdw_gmch_ctl = 1 << bdw_gmch_ctl;
+       if (bdw_gmch_ctl > 4) {
+               WARN_ON(!i915_preliminary_hw_support);
+               return 4<<20;
+       }
+
        return bdw_gmch_ctl << 20;
 }
 
index f9eafb6ed523a2d0f8fbd2ff981705c644733790..ee2742122a02561f910b6d9d5383418794234eff 100644 (file)
  */
 #define MI_LOAD_REGISTER_IMM(x)        MI_INSTR(0x22, 2*x-1)
 #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1)
+#define  MI_SRM_LRM_GLOBAL_GTT         (1<<22)
 #define MI_FLUSH_DW            MI_INSTR(0x26, 1) /* for GEN6 */
 #define   MI_FLUSH_DW_STORE_INDEX      (1<<21)
 #define   MI_INVALIDATE_TLB            (1<<18)
index 330077bcd0bddb22ecf056766dd88cd7ed70bfaf..526c8ded16b03bc334846609a47e2d0bfc07c58c 100644 (file)
@@ -173,7 +173,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
                ddi_translations = ddi_translations_dp;
                break;
        case PORT_D:
-               if (intel_dpd_is_edp(dev))
+               if (intel_dp_is_edp(dev, PORT_D))
                        ddi_translations = ddi_translations_edp;
                else
                        ddi_translations = ddi_translations_dp;
@@ -1158,9 +1158,10 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
        if (wait)
                intel_wait_ddi_buf_idle(dev_priv, port);
 
-       if (type == INTEL_OUTPUT_EDP) {
+       if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
                ironlake_edp_panel_vdd_on(intel_dp);
+               intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
                ironlake_edp_panel_off(intel_dp);
        }
 
index 7ec8b488bb1d30b6b950a23eecc833b574ab4db0..54e82a80cf507fe90366ad1e0fb33f082073ca83 100644 (file)
@@ -5815,7 +5815,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)
                uint16_t postoff = 0;
 
                if (intel_crtc->config.limited_color_range)
-                       postoff = (16 * (1 << 13) / 255) & 0x1fff;
+                       postoff = (16 * (1 << 12) / 255) & 0x1fff;
 
                I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
                I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
@@ -6303,7 +6303,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        uint32_t val;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-               WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+               WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
 
        WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -6402,7 +6402,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
        /* Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine! */
-       dev_priv->uncore.funcs.force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6436,7 +6436,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
 
-       dev_priv->uncore.funcs.force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
@@ -8354,7 +8354,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
                intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
                                        DERRMR_PIPEB_PRI_FLIP_DONE |
                                        DERRMR_PIPEC_PRI_FLIP_DONE));
-               intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1));
+               intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
+                               MI_SRM_LRM_GLOBAL_GTT);
                intel_ring_emit(ring, DERRMR);
                intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
        }
@@ -9134,7 +9135,7 @@ intel_pipe_config_compare(struct drm_device *dev,
        if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
                PIPE_CONF_CHECK_I(pipe_bpp);
 
-       if (!IS_HASWELL(dev)) {
+       if (!HAS_DDI(dev)) {
                PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
                PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
        }
@@ -10049,7 +10050,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_ddi_init(dev, PORT_D);
        } else if (HAS_PCH_SPLIT(dev)) {
                int found;
-               dpd_is_edp = intel_dpd_is_edp(dev);
+               dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
 
                if (has_edp_a(dev))
                        intel_dp_init(dev, DP_A, PORT_A);
@@ -10086,8 +10087,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
                                        PORT_C);
                        if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
-                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C,
-                                             PORT_C);
+                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
                }
 
                intel_dsi_init(dev);
@@ -11036,8 +11036,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        intel_modeset_check_state(dev);
-
-       drm_mode_config_reset(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
@@ -11046,7 +11044,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
        intel_setup_overlay(dev);
 
+       drm_modeset_lock_all(dev);
+       drm_mode_config_reset(dev);
        intel_modeset_setup_hw_state(dev, false);
+       drm_modeset_unlock_all(dev);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11125,14 +11126,15 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
 int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
        u16 gmch_ctrl;
 
-       pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
+       pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
        if (state)
                gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
        else
                gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-       pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
+       pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
        return 0;
 }
 
index 0b2e842fef0151070b09af535d54fdcee2215602..30c627c7b7ba18a0dbd546859b047a769cad1d64 100644 (file)
@@ -3326,11 +3326,19 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
 }
 
 /* check the VBT to see whether the eDP is on DP-D port */
-bool intel_dpd_is_edp(struct drm_device *dev)
+bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        union child_device_config *p_child;
        int i;
+       static const short port_mapping[] = {
+               [PORT_B] = PORT_IDPB,
+               [PORT_C] = PORT_IDPC,
+               [PORT_D] = PORT_IDPD,
+       };
+
+       if (port == PORT_A)
+               return true;
 
        if (!dev_priv->vbt.child_dev_num)
                return false;
@@ -3338,7 +3346,7 @@ bool intel_dpd_is_edp(struct drm_device *dev)
        for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
                p_child = dev_priv->vbt.child_dev + i;
 
-               if (p_child->common.dvo_port == PORT_IDPD &&
+               if (p_child->common.dvo_port == port_mapping[port] &&
                    (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
                    (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
                        return true;
@@ -3616,26 +3624,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        intel_dp->DP = I915_READ(intel_dp->output_reg);
        intel_dp->attached_connector = intel_connector;
 
-       type = DRM_MODE_CONNECTOR_DisplayPort;
-       /*
-        * FIXME : We need to initialize built-in panels before external panels.
-        * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
-        */
-       switch (port) {
-       case PORT_A:
+       if (intel_dp_is_edp(dev, port))
                type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       case PORT_C:
-               if (IS_VALLEYVIEW(dev))
-                       type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       case PORT_D:
-               if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
-                       type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       default:        /* silence GCC warning */
-               break;
-       }
+       else
+               type = DRM_MODE_CONNECTOR_DisplayPort;
 
        /*
         * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
index 1e49aa8f5377395c8803d5a55765199bd38af037..79f91f26e288d4bf2ae7815cb82cfc3271745bd5 100644 (file)
@@ -708,7 +708,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 void intel_dp_check_link_status(struct intel_dp *intel_dp);
 bool intel_dp_compute_config(struct intel_encoder *encoder,
                             struct intel_crtc_config *pipe_config);
-bool intel_dpd_is_edp(struct drm_device *dev);
+bool intel_dp_is_edp(struct drm_device *dev, enum port port);
 void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
 void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
 void ironlake_edp_panel_on(struct intel_dp *intel_dp);
@@ -821,6 +821,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane,
                                    uint32_t sprite_width, int pixel_size,
                                    bool enabled, bool scaled);
 void intel_init_pm(struct drm_device *dev);
+void intel_pm_setup(struct drm_device *dev);
 bool intel_fbc_enabled(struct drm_device *dev);
 void intel_update_fbc(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
index f161ac02c4f6e613efbfc7f763cbb3566dc75248..e6f782d1c6696d94fe4d4a80cf7f4d6ee6b5c7d7 100644 (file)
@@ -451,7 +451,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev,
 
        spin_lock_irqsave(&dev_priv->backlight.lock, flags);
 
-       if (HAS_PCH_SPLIT(dev)) {
+       if (IS_BROADWELL(dev)) {
+               val = I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
+       } else if (HAS_PCH_SPLIT(dev)) {
                val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
        } else {
                if (IS_VALLEYVIEW(dev))
@@ -479,6 +481,13 @@ static u32 intel_panel_get_backlight(struct drm_device *dev,
        return val;
 }
 
+static void intel_bdw_panel_set_backlight(struct drm_device *dev, u32 level)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
+}
+
 static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -496,7 +505,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev,
        DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
        level = intel_panel_compute_brightness(dev, pipe, level);
 
-       if (HAS_PCH_SPLIT(dev))
+       if (IS_BROADWELL(dev))
+               return intel_bdw_panel_set_backlight(dev, level);
+       else if (HAS_PCH_SPLIT(dev))
                return intel_pch_panel_set_backlight(dev, level);
 
        if (is_backlight_combination_mode(dev)) {
@@ -666,7 +677,16 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
                POSTING_READ(reg);
                I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
 
-               if (HAS_PCH_SPLIT(dev) &&
+               if (IS_BROADWELL(dev)) {
+                       /*
+                        * Broadwell requires PCH override to drive the PCH
+                        * backlight pin. The above will configure the CPU
+                        * backlight pin, which we don't plan to use.
+                        */
+                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
+                       tmp |= BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE;
+                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
+               } else if (HAS_PCH_SPLIT(dev) &&
                    !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
                        tmp = I915_READ(BLC_PWM_PCH_CTL1);
                        tmp |= BLM_PCH_PWM_ENABLE;
index caf2ee4e5441426527234453dbb43ed4c4c7273f..26c29c173221058aeeaa9a3c0d889500b8db9fec 100644 (file)
@@ -1180,7 +1180,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
 
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -1267,7 +1267,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
        crtc = intel_get_crtc_for_plane(dev, plane);
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -1498,7 +1498,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
                const struct drm_display_mode *adjusted_mode =
                        &to_intel_crtc(crtc)->config.adjusted_mode;
                int clock = adjusted_mode->crtc_clock;
-               int htotal = adjusted_mode->htotal;
+               int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
                int pixel_size = crtc->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
@@ -1624,7 +1624,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                const struct drm_display_mode *adjusted_mode =
                        &to_intel_crtc(enabled)->config.adjusted_mode;
                int clock = adjusted_mode->crtc_clock;
-               int htotal = adjusted_mode->htotal;
+               int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
                int pixel_size = enabled->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
@@ -1776,7 +1776,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
        crtc = intel_get_crtc_for_plane(dev, plane);
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -2469,8 +2469,9 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
        /* The WM are computed with base on how long it takes to fill a single
         * row at the given clock rate, multiplied by 8.
         * */
-       linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
-       ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
+       linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
+                                    mode->crtc_clock);
+       ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
                                         intel_ddi_get_cdclk_freq(dev_priv));
 
        return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
@@ -5684,8 +5685,11 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool is_enabled, enable_requested;
+       unsigned long irqflags;
        uint32_t tmp;
 
+       WARN_ON(dev_priv->pc8.enabled);
+
        tmp = I915_READ(HSW_PWR_WELL_DRIVER);
        is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
        enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5701,9 +5705,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
                                      HSW_PWR_WELL_STATE_ENABLED), 20))
                                DRM_ERROR("Timeout enabling power well\n");
                }
+
+               if (IS_BROADWELL(dev)) {
+                       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
+                                  dev_priv->de_irq_mask[PIPE_B]);
+                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
+                                  ~dev_priv->de_irq_mask[PIPE_B] |
+                                  GEN8_PIPE_VBLANK);
+                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
+                                  dev_priv->de_irq_mask[PIPE_C]);
+                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
+                                  ~dev_priv->de_irq_mask[PIPE_C] |
+                                  GEN8_PIPE_VBLANK);
+                       POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
+                       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+               }
        } else {
                if (enable_requested) {
-                       unsigned long irqflags;
                        enum pipe p;
 
                        I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
@@ -5730,16 +5749,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 static void __intel_power_well_get(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
-       if (!power_well->count++)
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!power_well->count++) {
+               hsw_disable_package_c8(dev_priv);
                __intel_set_power_well(dev, true);
+       }
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        WARN_ON(!power_well->count);
-       if (!--power_well->count && i915_disable_power_well)
+       if (!--power_well->count && i915_disable_power_well) {
                __intel_set_power_well(dev, false);
+               hsw_enable_package_c8(dev_priv);
+       }
 }
 
 void intel_display_power_get(struct drm_device *dev,
@@ -6129,10 +6156,19 @@ int vlv_freq_opcode(int ddr_freq, int val)
        return val;
 }
 
-void intel_pm_init(struct drm_device *dev)
+void intel_pm_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       mutex_init(&dev_priv->rps.hw_lock);
+
+       mutex_init(&dev_priv->pc8.lock);
+       dev_priv->pc8.requirements_met = false;
+       dev_priv->pc8.gpu_idle = false;
+       dev_priv->pc8.irqs_disabled = false;
+       dev_priv->pc8.enabled = false;
+       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
+       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
 }
index b620337e6d672c164448090016a27d1b713a2a24..c2f09d4563008ff7e32238675dab1b4da02ec967 100644 (file)
@@ -965,6 +965,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
        } else if (IS_GEN6(ring->dev)) {
                mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
        } else {
+               /* XXX: gen8 returns to sanity */
                mmio = RING_HWS_PGA(ring->mmio_base);
        }
 
index 0b02078a0b848c4127385b1d3b5d3ab6be755c80..25cbe073c388a3185d1a32afeb805993e43d12d3 100644 (file)
@@ -784,6 +784,7 @@ static int gen6_do_reset(struct drm_device *dev)
 int intel_gpu_reset(struct drm_device *dev)
 {
        switch (INTEL_INFO(dev)->gen) {
+       case 8:
        case 7:
        case 6: return gen6_do_reset(dev);
        case 5: return ironlake_do_reset(dev);
index edcf801613e66ea5c34665eafe1147d39cda62db..b3fa1ba191b7115be412894936c3633bf9221188 100644 (file)
@@ -59,6 +59,7 @@ nouveau-y += core/subdev/clock/nv40.o
 nouveau-y += core/subdev/clock/nv50.o
 nouveau-y += core/subdev/clock/nv84.o
 nouveau-y += core/subdev/clock/nva3.o
+nouveau-y += core/subdev/clock/nvaa.o
 nouveau-y += core/subdev/clock/nvc0.o
 nouveau-y += core/subdev/clock/nve0.o
 nouveau-y += core/subdev/clock/pllnv04.o
index db139827047cf4a6b103a2d98cc7fe5c208721db..db3fc7be856a733d07f8431a182326e3f20b4182 100644 (file)
@@ -283,7 +283,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
@@ -311,7 +311,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
index 5f555788121c9ff8c63a7e66da794011b67f237e..e6352bd5b4ff53c066b587bf51595b8ca54ac3af 100644 (file)
@@ -33,6 +33,7 @@
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+#include "nv04.h"
 #include "nv50.h"
 
 /*******************************************************************************
@@ -460,6 +461,8 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        nv_subdev(priv)->intr = nv04_fifo_intr;
        nv_engine(priv)->cclass = &nv50_fifo_cclass;
        nv_engine(priv)->sclass = nv50_fifo_sclass;
+       priv->base.pause = nv04_fifo_pause;
+       priv->base.start = nv04_fifo_start;
        return 0;
 }
 
index 0908dc834c84c48ac34f91afde1984ed593531bd..fe0f41e65d9b9c6ab6abfa5b1d5f7b3031fe5557 100644 (file)
@@ -35,6 +35,7 @@
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+#include "nv04.h"
 #include "nv50.h"
 
 /*******************************************************************************
@@ -432,6 +433,8 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        nv_subdev(priv)->intr = nv04_fifo_intr;
        nv_engine(priv)->cclass = &nv84_fifo_cclass;
        nv_engine(priv)->sclass = nv84_fifo_sclass;
+       priv->base.pause = nv04_fifo_pause;
+       priv->base.start = nv04_fifo_start;
        return 0;
 }
 
index b574dd4bb8285e65ccdbcf23db7b6f139e1cb73c..5ce686ee729ea5d937164d55892a9aebd2312b77 100644 (file)
@@ -176,7 +176,7 @@ nv50_software_context_ctor(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       chan->vblank.nr_event = pdisp->vblank->index_nr;
+       chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0;
        chan->vblank.event = kzalloc(chan->vblank.nr_event *
                                     sizeof(*chan->vblank.event), GFP_KERNEL);
        if (!chan->vblank.event)
index e2675bc0edba5f9baefc5d514750d151a2ce23a7..8f4ced75444a95478887b4be5791fc99dd3499dc 100644 (file)
@@ -14,6 +14,9 @@ enum nv_clk_src {
        nv_clk_src_hclk,
        nv_clk_src_hclkm3,
        nv_clk_src_hclkm3d2,
+       nv_clk_src_hclkm2d3, /* NVAA */
+       nv_clk_src_hclkm4, /* NVAA */
+       nv_clk_src_cclk, /* NVAA */
 
        nv_clk_src_host,
 
@@ -127,6 +130,7 @@ extern struct nouveau_oclass nv04_clock_oclass;
 extern struct nouveau_oclass nv40_clock_oclass;
 extern struct nouveau_oclass *nv50_clock_oclass;
 extern struct nouveau_oclass *nv84_clock_oclass;
+extern struct nouveau_oclass *nvaa_clock_oclass;
 extern struct nouveau_oclass nva3_clock_oclass;
 extern struct nouveau_oclass nvc0_clock_oclass;
 extern struct nouveau_oclass nve0_clock_oclass;
index da50c1b129283923f841eef8c4192df09131f935..30c1f3a4158e3de87fd2bfb24592b9ea685b2d88 100644 (file)
@@ -69,6 +69,11 @@ nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1,
        return 0;
 }
 
+static struct nouveau_clocks
+nv04_domain[] = {
+       { nv_clk_src_max }
+};
+
 static int
 nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,7 +82,7 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, NULL, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
new file mode 100644 (file)
index 0000000..7a723b4
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/fifo.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/timer.h>
+#include <subdev/clock.h>
+
+#include "pll.h"
+
+struct nvaa_clock_priv {
+       struct nouveau_clock base;
+       enum nv_clk_src csrc, ssrc, vsrc;
+       u32 cctrl, sctrl;
+       u32 ccoef, scoef;
+       u32 cpost, spost;
+       u32 vdiv;
+};
+
+static u32
+read_div(struct nouveau_clock *clk)
+{
+       return nv_rd32(clk, 0x004600);
+}
+
+static u32
+read_pll(struct nouveau_clock *clk, u32 base)
+{
+       u32 ctrl = nv_rd32(clk, base + 0);
+       u32 coef = nv_rd32(clk, base + 4);
+       u32 ref = clk->read(clk, nv_clk_src_href);
+       u32 post_div = 0;
+       u32 clock = 0;
+       int N1, M1;
+
+       switch (base){
+       case 0x4020:
+               post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16);
+               break;
+       case 0x4028:
+               post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16;
+               break;
+       default:
+               break;
+       }
+
+       N1 = (coef & 0x0000ff00) >> 8;
+       M1 = (coef & 0x000000ff);
+       if ((ctrl & 0x80000000) && M1) {
+               clock = ref * N1 / M1;
+               clock = clock / post_div;
+       }
+
+       return clock;
+}
+
+static int
+nvaa_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       u32 mast = nv_rd32(clk, 0x00c054);
+       u32 P = 0;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_href:
+               return 100000; /* PCIE reference clock */
+       case nv_clk_src_hclkm4:
+               return clk->read(clk, nv_clk_src_href) * 4;
+       case nv_clk_src_hclkm2d3:
+               return clk->read(clk, nv_clk_src_href) * 2 / 3;
+       case nv_clk_src_host:
+               switch (mast & 0x000c0000) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3);
+               case 0x00040000: break;
+               case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x000c0000: return clk->read(clk, nv_clk_src_cclk);
+               }
+               break;
+       case nv_clk_src_core:
+               P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16;
+
+               switch (mast & 0x00000003) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000001: return 0;
+               case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P;
+               case 0x00000003: return read_pll(clk, 0x004028) >> P;
+               }
+               break;
+       case nv_clk_src_cclk:
+               if ((mast & 0x03000000) != 0x03000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               if ((mast & 0x00000200) == 0x00000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               switch (mast & 0x00000c00) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_href);
+               case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3);
+               default: return 0;
+               }
+       case nv_clk_src_shader:
+               P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16;
+               switch (mast & 0x00000030) {
+               case 0x00000000:
+                       if (mast & 0x00000040)
+                               return clk->read(clk, nv_clk_src_href) >> P;
+                       return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000010: break;
+               case 0x00000020: return read_pll(clk, 0x004028) >> P;
+               case 0x00000030: return read_pll(clk, 0x004020) >> P;
+               }
+               break;
+       case nv_clk_src_mem:
+               return 0;
+               break;
+       case nv_clk_src_vdec:
+               P = (read_div(clk) & 0x00000700) >> 8;
+
+               switch (mast & 0x00400000) {
+               case 0x00400000:
+                       return clk->read(clk, nv_clk_src_core) >> P;
+                       break;
+               default:
+                       return 500000 >> P;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
+       return 0;
+}
+
+static u32
+calc_pll(struct nvaa_clock_priv *priv, u32 reg,
+        u32 clock, int *N, int *M, int *P)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll pll;
+       struct nouveau_clock *clk = &priv->base;
+       int ret;
+
+       ret = nvbios_pll_parse(bios, reg, &pll);
+       if (ret)
+               return 0;
+
+       pll.vco2.max_freq = 0;
+       pll.refclk = clk->read(clk, nv_clk_src_href);
+       if (!pll.refclk)
+               return 0;
+
+       return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P);
+}
+
+static inline u32
+calc_P(u32 src, u32 target, int *div)
+{
+       u32 clk0 = src, clk1 = src;
+       for (*div = 0; *div <= 7; (*div)++) {
+               if (clk0 <= target) {
+                       clk1 = clk0 << (*div ? 1 : 0);
+                       break;
+               }
+               clk0 >>= 1;
+       }
+
+       if (target - clk0 <= clk1 - target)
+               return clk0;
+       (*div)--;
+       return clk1;
+}
+
+static int
+nvaa_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       const int shader = cstate->domain[nv_clk_src_shader];
+       const int core = cstate->domain[nv_clk_src_core];
+       const int vdec = cstate->domain[nv_clk_src_vdec];
+       u32 out = 0, clock = 0;
+       int N, M, P1, P2 = 0;
+       int divs = 0;
+
+       /* cclk: find suitable source, disable PLL if we can */
+       if (core < clk->read(clk, nv_clk_src_hclkm4))
+               out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs);
+
+       /* Calculate clock * 2, so shader clock can use it too */
+       clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1);
+
+       if (abs(core - out) <=
+           abs(core - (clock >> 1))) {
+               priv->csrc = nv_clk_src_hclkm4;
+               priv->cctrl = divs << 16;
+       } else {
+               /* NVCTRL is actually used _after_ NVPOST, and after what we
+                * call NVPLL. To make matters worse, NVPOST is an integer
+                * divider instead of a right-shift number. */
+               if(P1 > 2) {
+                       P2 = P1 - 2;
+                       P1 = 2;
+               }
+
+               priv->csrc = nv_clk_src_core;
+               priv->ccoef = (N << 8) | M;
+
+               priv->cctrl = (P2 + 1) << 16;
+               priv->cpost = (1 << P1) << 16;
+       }
+
+       /* sclk: nvpll + divisor, href or spll */
+       out = 0;
+       if (shader == clk->read(clk, nv_clk_src_href)) {
+               priv->ssrc = nv_clk_src_href;
+       } else {
+               clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
+               if (priv->csrc == nv_clk_src_core) {
+                       out = calc_P((core << 1), shader, &divs);
+               }
+
+               if (abs(shader - out) <=
+                   abs(shader - clock) &&
+                  (divs + P2) <= 7) {
+                       priv->ssrc = nv_clk_src_core;
+                       priv->sctrl = (divs + P2) << 16;
+               } else {
+                       priv->ssrc = nv_clk_src_shader;
+                       priv->scoef = (N << 8) | M;
+                       priv->sctrl = P1 << 16;
+               }
+       }
+
+       /* vclk */
+       out = calc_P(core, vdec, &divs);
+       clock = calc_P(500000, vdec, &P1);
+       if(abs(vdec - out) <=
+          abs(vdec - clock)) {
+               priv->vsrc = nv_clk_src_cclk;
+               priv->vdiv = divs << 16;
+       } else {
+               priv->vsrc = nv_clk_src_vdec;
+               priv->vdiv = P1 << 16;
+       }
+
+       /* Print strategy! */
+       nv_debug(priv, "nvpll: %08x %08x %08x\n",
+                       priv->ccoef, priv->cpost, priv->cctrl);
+       nv_debug(priv, " spll: %08x %08x %08x\n",
+                       priv->scoef, priv->spost, priv->sctrl);
+       nv_debug(priv, " vdiv: %08x\n", priv->vdiv);
+       if (priv->csrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "core: hrefm4\n");
+       else
+               nv_debug(priv, "core: nvpll\n");
+
+       if (priv->ssrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "shader: hrefm4\n");
+       else if (priv->ssrc == nv_clk_src_core)
+               nv_debug(priv, "shader: nvpll\n");
+       else
+               nv_debug(priv, "shader: spll\n");
+
+       if (priv->vsrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "vdec: 500MHz\n");
+       else
+               nv_debug(priv, "vdec: core\n");
+
+       return 0;
+}
+
+static int
+nvaa_clock_prog(struct nouveau_clock *clk)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+       unsigned long flags;
+       u32 pllmask = 0, mast, ptherm_gate;
+       int ret = -EBUSY;
+
+       /* halt and idle execution engines */
+       ptherm_gate = nv_mask(clk, 0x020060, 0x00070000, 0x00000000);
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000001);
+       /* Wait until the interrupt handler is finished */
+       if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000))
+               goto resume;
+
+       if (pfifo)
+               pfifo->pause(pfifo, &flags);
+
+       if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010))
+               goto resume;
+       if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f))
+               goto resume;
+
+       /* First switch to safe clocks: href */
+       mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640);
+       mast &= ~0x00400e73;
+       mast |= 0x03000000;
+
+       switch (priv->csrc) {
+       case nv_clk_src_hclkm4:
+               nv_mask(clk, 0x4028, 0x00070000, priv->cctrl);
+               mast |= 0x00000002;
+               break;
+       case nv_clk_src_core:
+               nv_wr32(clk, 0x402c, priv->ccoef);
+               nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl);
+               nv_wr32(clk, 0x4040, priv->cpost);
+               pllmask |= (0x3 << 8);
+               mast |= 0x00000003;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown core clock\n");
+               goto resume;
+       }
+
+       switch (priv->ssrc) {
+       case nv_clk_src_href:
+               nv_mask(clk, 0x4020, 0x00070000, 0x00000000);
+               /* mast |= 0x00000000; */
+               break;
+       case nv_clk_src_core:
+               nv_mask(clk, 0x4020, 0x00070000, priv->sctrl);
+               mast |= 0x00000020;
+               break;
+       case nv_clk_src_shader:
+               nv_wr32(clk, 0x4024, priv->scoef);
+               nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl);
+               nv_wr32(clk, 0x4070, priv->spost);
+               pllmask |= (0x3 << 12);
+               mast |= 0x00000030;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown sclk clock\n");
+               goto resume;
+       }
+
+       if (!nv_wait(clk, 0x004080, pllmask, pllmask)) {
+               nv_warn(priv,"Reclocking failed: unstable PLLs\n");
+               goto resume;
+       }
+
+       switch (priv->vsrc) {
+       case nv_clk_src_cclk:
+               mast |= 0x00400000;
+       default:
+               nv_wr32(clk, 0x4600, priv->vdiv);
+       }
+
+       nv_wr32(clk, 0xc054, mast);
+       ret = 0;
+
+resume:
+       if (pfifo)
+               pfifo->start(pfifo, &flags);
+
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000000);
+       nv_wr32(clk, 0x020060, ptherm_gate);
+
+       /* Disable some PLLs and dividers when unused */
+       if (priv->csrc != nv_clk_src_core) {
+               nv_wr32(clk, 0x4040, 0x00000000);
+               nv_mask(clk, 0x4028, 0x80000000, 0x00000000);
+       }
+
+       if (priv->ssrc != nv_clk_src_shader) {
+               nv_wr32(clk, 0x4070, 0x00000000);
+               nv_mask(clk, 0x4020, 0x80000000, 0x00000000);
+       }
+
+       return ret;
+}
+
+static void
+nvaa_clock_tidy(struct nouveau_clock *clk)
+{
+}
+
+static struct nouveau_clocks
+nvaa_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_vdec   , 0xff, 0, "vdec", 1000 },
+       { nv_clk_src_max }
+};
+
+static int
+nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nvaa_clock_priv *priv;
+       int ret;
+
+       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nvaa_clock_read;
+       priv->base.calc = nvaa_clock_calc;
+       priv->base.prog = nvaa_clock_prog;
+       priv->base.tidy = nvaa_clock_tidy;
+       return 0;
+}
+
+struct nouveau_oclass *
+nvaa_clock_oclass = &(struct nouveau_oclass) {
+       .handle = NV_SUBDEV(CLOCK, 0xaa),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvaa_clock_ctor,
+               .dtor = _nouveau_clock_dtor,
+               .init = _nouveau_clock_init,
+               .fini = _nouveau_clock_fini,
+       },
+};
index 3618ac6b6316416797a36e474bf613a12cf032ab..32e7064b819b6df4f9e5847beba7a826eaaed726 100644 (file)
@@ -58,8 +58,8 @@ struct nouveau_plane {
 };
 
 static uint32_t formats[] = {
-       DRM_FORMAT_NV12,
        DRM_FORMAT_UYVY,
+       DRM_FORMAT_NV12,
 };
 
 /* Sine can be approximated with
@@ -99,13 +99,28 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_bo *cur = nv_plane->cur;
        bool flip = nv_plane->flip;
-       int format = ALIGN(src_w * 4, 0x100);
        int soff = NV_PCRTC0_SIZE * nv_crtc->index;
        int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
-       int ret;
+       int format, ret;
+
+       /* Source parameters given in 16.16 fixed point, ignore fractional. */
+       src_x >>= 16;
+       src_y >>= 16;
+       src_w >>= 16;
+       src_h >>= 16;
+
+       format = ALIGN(src_w * 4, 0x100);
 
        if (format > 0xffff)
-               return -EINVAL;
+               return -ERANGE;
+
+       if (dev->chipset >= 0x30) {
+               if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
+                       return -ERANGE;
+       } else {
+               if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3))
+                       return -ERANGE;
+       }
 
        ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
        if (ret)
@@ -113,12 +128,6 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
        nv_plane->cur = nv_fb->nvbo;
 
-       /* Source parameters given in 16.16 fixed point, ignore fractional. */
-       src_x = src_x >> 16;
-       src_y = src_y >> 16;
-       src_w = src_w >> 16;
-       src_h = src_h >> 16;
-
        nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
        nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
 
@@ -245,14 +254,25 @@ nv10_overlay_init(struct drm_device *device)
 {
        struct nouveau_device *dev = nouveau_dev(device);
        struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
+       int num_formats = ARRAY_SIZE(formats);
        int ret;
 
        if (!plane)
                return;
 
+       switch (dev->chipset) {
+       case 0x10:
+       case 0x11:
+       case 0x15:
+       case 0x1a:
+       case 0x20:
+               num_formats = 1;
+               break;
+       }
+
        ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */,
                             &nv10_plane_funcs,
-                            formats, ARRAY_SIZE(formats), false);
+                            formats, num_formats, false);
        if (ret)
                goto err;
 
index 7809d92183c4236c9f1f937ea6cde6a39e780063..29c3efdfc7dd714e00ae03525d0b9528fce841cd 100644 (file)
@@ -608,6 +608,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        fence = nouveau_fence_ref(new_bo->bo.sync_obj);
        spin_unlock(&new_bo->bo.bdev->fence_lock);
        ret = nouveau_fence_sync(fence, chan);
+       nouveau_fence_unref(&fence);
        if (ret)
                return ret;
 
@@ -701,7 +702,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
 
        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
        if (s->event)
-               drm_send_vblank_event(dev, -1, s->event);
+               drm_send_vblank_event(dev, s->crtc, s->event);
 
        list_del(&s->head);
        if (ps)
index 7a3759f1c41a67bac6b48cdcfd5b10b5ac30ae39..98a22e6e27a11f73045fdbab161452309f2416ab 100644 (file)
@@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        if (nouveau_runtime_pm == 0)
                return -EINVAL;
 
+       /* are we optimus enabled? */
+       if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
+               DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+               return -EINVAL;
+       }
+
        nv_debug_level(SILENT);
        drm_kms_helper_poll_disable(drm_dev);
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
index 38a4db5bfe21f22b8713bff3ad20466c5f631411..4aff04fa483c5e82acf1c66b1e63833bc23391cf 100644 (file)
@@ -630,7 +630,6 @@ error:
        hwmon->hwmon = NULL;
        return ret;
 #else
-       hwmon->hwmon = NULL;
        return 0;
 #endif
 }
index f8e66c08b11a292545a29e327966d3d4256e5f09..4e384a2f99c3627ea0fc6e31f5f0e34ac95e71e8 100644 (file)
@@ -1265,7 +1265,7 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
                    uint32_t start, uint32_t size)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-       u32 end = max(start + size, (u32)256);
+       u32 end = min_t(u32, start + size, 256);
        u32 i;
 
        for (i = start; i < end; i++) {
index 037d324bf58f6ccfda14ff471f3c98b4405981a0..66ac0ff95f5a30408bf722b43e49e76138e74546 100644 (file)
@@ -8,5 +8,6 @@ config DRM_QXL
         select DRM_KMS_HELPER
        select DRM_KMS_FB_HELPER
         select DRM_TTM
+       select CRC32
        help
                QXL virtual GPU for Spice virtualization desktop integration. Do not enable this driver unless your distro ships a corresponding X.org QXL driver that can handle kernel modesetting.
index 5e827c29d1948a658cf61205b7607ff5a53263d7..d70aafb83307d2a085afdbba6a2d4762309667ea 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 
-#include "linux/crc32.h"
+#include <linux/crc32.h>
 
 #include "qxl_drv.h"
 #include "qxl_object.h"
index 0109a9644cb29ef7a6e13ac76a90544effcefd20..821ab7b9409bb866c61d793c4e0ab9d63d73ec98 100644 (file)
@@ -92,6 +92,7 @@ qxl_release_free(struct qxl_device *qdev,
                                                - DRM_FILE_OFFSET);
                qxl_fence_remove_release(&bo->fence, release->id);
                qxl_bo_unref(&bo);
+               kfree(entry);
        }
        spin_lock(&qdev->release_idr_lock);
        idr_remove(&qdev->release_idr, release->id);
index 80a20120e6253590d07e9ec4b0085b6ea9d31437..b1970596a782a437547a1fe32475253a69557f97 100644 (file)
@@ -1196,7 +1196,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        } else if ((rdev->family == CHIP_TAHITI) ||
                   (rdev->family == CHIP_PITCAIRN))
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
-       else if (rdev->family == CHIP_VERDE)
+       else if ((rdev->family == CHIP_VERDE) ||
+                (rdev->family == CHIP_OLAND) ||
+                (rdev->family == CHIP_HAINAN)) /* for completeness.  HAINAN has no display hw */
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
 
        switch (radeon_crtc->crtc_id) {
index 0652ee0a20989db0b69f816d45e17f9354e5ca8a..f685035dbe39a7d7ad48e63a9b4ca2ea717701fe 100644 (file)
@@ -44,7 +44,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
        PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
        unsigned char *base;
-       u16 out;
+       u16 out = cpu_to_le16(0);
 
        memset(&args, 0, sizeof(args));
 
@@ -55,11 +55,14 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
                        DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
                        return -EINVAL;
                }
-               args.ucRegIndex = buf[0];
-               if (num > 1) {
+               if (buf == NULL)
+                       args.ucRegIndex = 0;
+               else
+                       args.ucRegIndex = buf[0];
+               if (num)
                        num--;
+               if (num)
                        memcpy(&out, &buf[1], num);
-               }
                args.lpI2CDataOut = cpu_to_le16(out);
        } else {
                if (num > ATOM_MAX_HW_I2C_READ) {
@@ -96,14 +99,14 @@ int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
        struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
        struct i2c_msg *p;
        int i, remaining, current_count, buffer_offset, max_bytes, ret;
-       u8 buf = 0, flags;
+       u8 flags;
 
        /* check for bus probe */
        p = &msgs[0];
        if ((num == 1) && (p->len == 0)) {
                ret = radeon_process_i2c_ch(i2c,
                                            p->addr, HW_I2C_WRITE,
-                                           &buf, 1);
+                                           NULL, 0);
                if (ret)
                        return ret;
                else
index 0300727a4f70d52c71e24931bbec8335ce6ba6d3..d08b83c6267b4cde4ff5ce0ad71754c1e5e446a1 100644 (file)
@@ -458,7 +458,7 @@ int cik_copy_dma(struct radeon_device *rdev,
                radeon_ring_write(ring, 0); /* src/dst endian swap */
                radeon_ring_write(ring, src_offset & 0xffffffff);
                radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff);
-               radeon_ring_write(ring, dst_offset & 0xfffffffc);
+               radeon_ring_write(ring, dst_offset & 0xffffffff);
                radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff);
                src_offset += cur_size_in_bytes;
                dst_offset += cur_size_in_bytes;
index 009f46e0ce72db47534d2b7667bcd0119607d91b..713a5d35990102ea315fa078a93c11d6c1aae1f5 100644 (file)
@@ -93,11 +93,13 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
        struct radeon_device *rdev = encoder->dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       u32 offset = dig->afmt->offset;
+       u32 offset;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
+       offset = dig->afmt->offset;
+
        WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
               AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
 }
@@ -112,7 +114,7 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
        struct radeon_connector *radeon_connector = NULL;
        u32 tmp = 0, offset;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -156,7 +158,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -172,7 +174,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -217,7 +219,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
                { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
        };
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -233,7 +235,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
@@ -306,7 +308,9 @@ int dce6_audio_init(struct radeon_device *rdev)
        rdev->audio.enabled = true;
 
        if (ASIC_IS_DCE8(rdev))
-               rdev->audio.num_pins = 7;
+               rdev->audio.num_pins = 6;
+       else if (ASIC_IS_DCE61(rdev))
+               rdev->audio.num_pins = 4;
        else
                rdev->audio.num_pins = 6;
 
index aa695c4feb3d00d393c2e9b74e2395a3a7395164..0c6d5cef4cf121770c63fcb559bf6cc187640292 100644 (file)
@@ -118,7 +118,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -173,7 +173,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
index 11aab2ab54ce27fb5c0279cbaaad797e95bea42f..f59a9e9fccf8a803ce6097e4e185d8824ad5f714 100644 (file)
@@ -895,6 +895,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                    (rdev->pdev->device == 0x999C)) {
                        rdev->config.cayman.max_simds_per_se = 6;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9903) ||
                           (rdev->pdev->device == 0x9904) ||
                           (rdev->pdev->device == 0x990A) ||
@@ -905,6 +909,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x999D)) {
                        rdev->config.cayman.max_simds_per_se = 4;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9919) ||
                           (rdev->pdev->device == 0x9990) ||
                           (rdev->pdev->device == 0x9991) ||
@@ -915,9 +923,17 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x99A0)) {
                        rdev->config.cayman.max_simds_per_se = 3;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                } else {
                        rdev->config.cayman.max_simds_per_se = 2;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                }
                rdev->config.cayman.max_texture_channel_caches = 2;
                rdev->config.cayman.max_gprs = 256;
@@ -925,10 +941,6 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                rdev->config.cayman.max_gs_threads = 32;
                rdev->config.cayman.max_stack_entries = 512;
                rdev->config.cayman.sx_num_of_sets = 8;
-               rdev->config.cayman.sx_max_export_size = 256;
-               rdev->config.cayman.sx_max_export_pos_size = 64;
-               rdev->config.cayman.sx_max_export_smx_size = 192;
-               rdev->config.cayman.max_hw_contexts = 8;
                rdev->config.cayman.sq_num_cf_insts = 2;
 
                rdev->config.cayman.sc_prim_fifo_size = 0x40;
index cdc003085a76b802eddba1d1ba1a9df5e739dc26..49c4d48f54d616b49b7af261d8fa2d71586ab8fd 100644 (file)
@@ -785,8 +785,8 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
        struct ni_ps *ps = ni_get_ps(rps);
        struct radeon_clock_and_voltage_limits *max_limits;
        bool disable_mclk_switching;
-       u32 mclk, sclk;
-       u16 vddc, vddci;
+       u32 mclk;
+       u16 vddci;
        u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
@@ -839,24 +839,14 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
 
        /* XXX validate the min clocks required for display */
 
+       /* adjust low state */
        if (disable_mclk_switching) {
-               mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
-               sclk = ps->performance_levels[0].sclk;
-               vddc = ps->performance_levels[0].vddc;
-               vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
-       } else {
-               sclk = ps->performance_levels[0].sclk;
-               mclk = ps->performance_levels[0].mclk;
-               vddc = ps->performance_levels[0].vddc;
-               vddci = ps->performance_levels[0].vddci;
+               ps->performance_levels[0].mclk =
+                       ps->performance_levels[ps->performance_level_count - 1].mclk;
+               ps->performance_levels[0].vddci =
+                       ps->performance_levels[ps->performance_level_count - 1].vddci;
        }
 
-       /* adjusted low state */
-       ps->performance_levels[0].sclk = sclk;
-       ps->performance_levels[0].mclk = mclk;
-       ps->performance_levels[0].vddc = vddc;
-       ps->performance_levels[0].vddci = vddci;
-
        btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
                                  &ps->performance_levels[0].sclk,
                                  &ps->performance_levels[0].mclk);
@@ -868,11 +858,15 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
                        ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
        }
 
+       /* adjust remaining states */
        if (disable_mclk_switching) {
                mclk = ps->performance_levels[0].mclk;
+               vddci = ps->performance_levels[0].vddci;
                for (i = 1; i < ps->performance_level_count; i++) {
                        if (mclk < ps->performance_levels[i].mclk)
                                mclk = ps->performance_levels[i].mclk;
+                       if (vddci < ps->performance_levels[i].vddci)
+                               vddci = ps->performance_levels[i].vddci;
                }
                for (i = 0; i < ps->performance_level_count; i++) {
                        ps->performance_levels[i].mclk = mclk;
index 4b89262f3f0e37242de23b7b6ea2fc555d141da3..b7d3ecba43e34d3b559ee072800101532150c631 100644 (file)
@@ -304,9 +304,9 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
-       } else if (ASIC_IS_DCE3(rdev)) {
+       } else {
                /* according to the reg specs, this should DCE3.2 only, but in
-                * practice it seems to cover DCE3.0/3.1 as well.
+                * practice it seems to cover DCE2.0/3.0/3.1 as well.
                 */
                if (dig->dig_encoder == 0) {
                        WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
@@ -317,10 +317,6 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
-       } else {
-               /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */
-               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
-                      AUDIO_DTO_MODULE(clock / 10));
        }
 }
 
index ecf2a3960c0786ca02fc3aef84afab61e0e6303f..b1f990d0eaa101d1bce56fabfc4b286ff01de7e9 100644 (file)
@@ -2710,10 +2710,10 @@ void radeon_vm_fence(struct radeon_device *rdev,
                     struct radeon_vm *vm,
                     struct radeon_fence *fence);
 uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr);
-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
-                           struct radeon_vm *vm,
-                           struct radeon_bo *bo,
-                           struct ttm_mem_reg *mem);
+int radeon_vm_bo_update(struct radeon_device *rdev,
+                       struct radeon_vm *vm,
+                       struct radeon_bo *bo,
+                       struct ttm_mem_reg *mem);
 void radeon_vm_bo_invalidate(struct radeon_device *rdev,
                             struct radeon_bo *bo);
 struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm,
index e354ce94cdd17492030e2bd85ef1406810e9e5df..c0425bb6223a99fae5eab07a069ab73ace19eec7 100644 (file)
@@ -2021,7 +2021,7 @@ static struct radeon_asic ci_asic = {
                .hdmi_setmode = &evergreen_hdmi_setmode,
        },
        .copy = {
-               .blit = NULL,
+               .blit = &cik_copy_cpdma,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
@@ -2122,7 +2122,7 @@ static struct radeon_asic kv_asic = {
                .hdmi_setmode = &evergreen_hdmi_setmode,
        },
        .copy = {
-               .blit = NULL,
+               .blit = &cik_copy_cpdma,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
index f79ee184ffd5849f4d0e0ec1b87b0d94d0f1f131..5c39bf7c3d88668bad65ef9667de82a0a145f196 100644 (file)
@@ -2918,7 +2918,7 @@ int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev,
                        mpll_param->dll_speed = args.ucDllSpeed;
                        mpll_param->bwcntl = args.ucBWCntl;
                        mpll_param->vco_mode =
-                               (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0;
+                               (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK);
                        mpll_param->yclk_sel =
                                (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0;
                        mpll_param->qdr =
index f41594b2eeac775794f3d2b2d050a06e387d9025..0b366169d64de55c52e4c2d9c26d1c3b9db19b2d 100644 (file)
@@ -360,13 +360,13 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser,
        struct radeon_bo *bo;
        int r;
 
-       r = radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
+       r = radeon_vm_bo_update(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
        if (r) {
                return r;
        }
        list_for_each_entry(lobj, &parser->validated, tv.head) {
                bo = lobj->bo;
-               r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem);
+               r = radeon_vm_bo_update(parser->rdev, vm, bo, &bo->tbo.mem);
                if (r) {
                        return r;
                }
index 9f5ff28864f6e3ccf4f4736cc55307735d87a70a..1958b36ad0e5cdddf623b8a54a16df0c501ca668 100644 (file)
@@ -508,15 +508,6 @@ static const struct file_operations radeon_driver_kms_fops = {
 #endif
 };
 
-
-static void
-radeon_pci_shutdown(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-
-       radeon_driver_unload_kms(dev);
-}
-
 static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP |
@@ -586,7 +577,6 @@ static struct pci_driver radeon_kms_pci_driver = {
        .probe = radeon_pci_probe,
        .remove = radeon_pci_remove,
        .driver.pm = &radeon_pm_ops,
-       .shutdown = radeon_pci_shutdown,
 };
 
 static int __init radeon_init(void)
index 543dcfae7e6f5f9a01797a9bb90455be5fef88c5..00e0d449021c343015540ea3baf1028b85a10090 100644 (file)
  * 1.31- Add support for num Z pipes from GET_PARAM
  * 1.32- fixes for rv740 setup
  * 1.33- Add r6xx/r7xx const buffer support
+ * 1.34- fix evergreen/cayman GS register
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           33
+#define DRIVER_MINOR           34
 #define DRIVER_PATCHLEVEL      0
 
 long radeon_drm_ioctl(struct file *filp,
index 3044e504f4ec9a8a4cbf6ef18bbd009fe7672c01..96e440061bdbf5b65a6213047f62bbeb89aea77f 100644 (file)
@@ -29,6 +29,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_reg.h"
+#include "radeon_trace.h"
 
 /*
  * GART
@@ -737,6 +738,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
        for (i = 0; i < 2; ++i) {
                if (choices[i]) {
                        vm->id = choices[i];
+                       trace_radeon_vm_grab_id(vm->id, ring);
                        return rdev->vm_manager.active[choices[i]];
                }
        }
@@ -1116,7 +1118,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
 }
 
 /**
- * radeon_vm_bo_update_pte - map a bo into the vm page table
+ * radeon_vm_bo_update - map a bo into the vm page table
  *
  * @rdev: radeon_device pointer
  * @vm: requested vm
@@ -1128,10 +1130,10 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
  *
  * Object have to be reserved & global and local mutex must be locked!
  */
-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
-                           struct radeon_vm *vm,
-                           struct radeon_bo *bo,
-                           struct ttm_mem_reg *mem)
+int radeon_vm_bo_update(struct radeon_device *rdev,
+                       struct radeon_vm *vm,
+                       struct radeon_bo *bo,
+                       struct ttm_mem_reg *mem)
 {
        struct radeon_ib ib;
        struct radeon_bo_va *bo_va;
@@ -1176,6 +1178,8 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                bo_va->valid = false;
        }
 
+       trace_radeon_vm_bo_update(bo_va);
+
        nptes = radeon_bo_ngpu_pages(bo);
 
        /* assume two extra pdes in case the mapping overlaps the borders */
@@ -1257,7 +1261,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
        mutex_lock(&rdev->vm_manager.lock);
        mutex_lock(&bo_va->vm->mutex);
        if (bo_va->soffset) {
-               r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL);
+               r = radeon_vm_bo_update(rdev, bo_va->vm, bo_va->bo, NULL);
        }
        mutex_unlock(&rdev->vm_manager.lock);
        list_del(&bo_va->vm_list);
index d1385ccc672c4976aff90d9150fb221f98c29441..984097b907ef5ee67c8e59faf4198ccf8add5f1b 100644 (file)
@@ -537,8 +537,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf)
 {
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
        int temp;
 
        if (rdev->asic->pm.get_temperature)
@@ -553,8 +552,7 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
                                             struct device_attribute *attr,
                                             char *buf)
 {
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
        int hyst = to_sensor_dev_attr(attr)->index;
        int temp;
 
@@ -566,23 +564,14 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
 
-static ssize_t radeon_hwmon_show_name(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "radeon\n");
-}
-
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1);
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_crit.dev_attr.attr,
        &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
-       &sensor_dev_attr_name.dev_attr.attr,
        NULL
 };
 
@@ -590,8 +579,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
                                        struct attribute *attr, int index)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
 
        /* Skip limit attributes if DPM is not enabled */
        if (rdev->pm.pm_method != PM_METHOD_DPM &&
@@ -607,11 +595,15 @@ static const struct attribute_group hwmon_attrgroup = {
        .is_visible = hwmon_attributes_visible,
 };
 
+static const struct attribute_group *hwmon_groups[] = {
+       &hwmon_attrgroup,
+       NULL
+};
+
 static int radeon_hwmon_init(struct radeon_device *rdev)
 {
        int err = 0;
-
-       rdev->pm.int_hwmon_dev = NULL;
+       struct device *hwmon_dev;
 
        switch (rdev->pm.int_thermal_type) {
        case THERMAL_TYPE_RV6XX:
@@ -624,20 +616,13 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        case THERMAL_TYPE_KV:
                if (rdev->asic->pm.get_temperature == NULL)
                        return err;
-               rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
-               if (IS_ERR(rdev->pm.int_hwmon_dev)) {
-                       err = PTR_ERR(rdev->pm.int_hwmon_dev);
+               hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
+                                                             "radeon", rdev,
+                                                             hwmon_groups);
+               if (IS_ERR(hwmon_dev)) {
+                       err = PTR_ERR(hwmon_dev);
                        dev_err(rdev->dev,
                                "Unable to register hwmon device: %d\n", err);
-                       break;
-               }
-               dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev);
-               err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj,
-                                        &hwmon_attrgroup);
-               if (err) {
-                       dev_err(rdev->dev,
-                               "Unable to create hwmon sysfs file: %d\n", err);
-                       hwmon_device_unregister(rdev->dev);
                }
                break;
        default:
@@ -647,14 +632,6 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        return err;
 }
 
-static void radeon_hwmon_fini(struct radeon_device *rdev)
-{
-       if (rdev->pm.int_hwmon_dev) {
-               sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup);
-               hwmon_device_unregister(rdev->pm.int_hwmon_dev);
-       }
-}
-
 static void radeon_dpm_thermal_work_handler(struct work_struct *work)
 {
        struct radeon_device *rdev =
@@ -1337,8 +1314,6 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
 
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
-
-       radeon_hwmon_fini(rdev);
 }
 
 static void radeon_pm_fini_dpm(struct radeon_device *rdev)
@@ -1358,8 +1333,6 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
 
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
-
-       radeon_hwmon_fini(rdev);
 }
 
 void radeon_pm_fini(struct radeon_device *rdev)
index 9f0e18172b6e8074bf865e93902d67f1584141bd..0473257d407886e175f77347078b2de54c61cfc3 100644 (file)
@@ -47,6 +47,39 @@ TRACE_EVENT(radeon_cs,
                      __entry->fences)
 );
 
+TRACE_EVENT(radeon_vm_grab_id,
+           TP_PROTO(unsigned vmid, int ring),
+           TP_ARGS(vmid, ring),
+           TP_STRUCT__entry(
+                            __field(u32, vmid)
+                            __field(u32, ring)
+                            ),
+
+           TP_fast_assign(
+                          __entry->vmid = vmid;
+                          __entry->ring = ring;
+                          ),
+           TP_printk("vmid=%u, ring=%u", __entry->vmid, __entry->ring)
+);
+
+TRACE_EVENT(radeon_vm_bo_update,
+           TP_PROTO(struct radeon_bo_va *bo_va),
+           TP_ARGS(bo_va),
+           TP_STRUCT__entry(
+                            __field(u64, soffset)
+                            __field(u64, eoffset)
+                            __field(u32, flags)
+                            ),
+
+           TP_fast_assign(
+                          __entry->soffset = bo_va->soffset;
+                          __entry->eoffset = bo_va->eoffset;
+                          __entry->flags = bo_va->flags;
+                          ),
+           TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x",
+                     __entry->soffset, __entry->eoffset, __entry->flags)
+);
+
 TRACE_EVENT(radeon_vm_set_page,
            TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
                     uint32_t incr, uint32_t flags),
index a072fa8c46b04a00a9c78886b20a29615f7ad86c..d46b58d078aad94eaca7050eb3deb9c1375583a7 100644 (file)
@@ -21,7 +21,7 @@ cayman 0x9400
 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
 0x000089B0 VGT_HS_OFFCHIP_PARAM
 0x00008A14 PA_CL_ENHANCE
-0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008A60 PA_SU_LINE_STIPPLE_VALUE
 0x00008B10 PA_SC_LINE_STIPPLE_STATE
 0x00008BF0 PA_SC_ENHANCE
 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
@@ -532,7 +532,7 @@ cayman 0x9400
 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
-0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028B90 VGT_GS_INSTANCE_CNT
 0x00028BD4 PA_SC_CENTROID_PRIORITY_0
 0x00028BD8 PA_SC_CENTROID_PRIORITY_1
 0x00028BDC PA_SC_LINE_CNTL
index b912a37689bf818a0fccd576f6436f71e4e936ff..57745c8761c863714abe07ba2ff73324980ea18e 100644 (file)
@@ -22,7 +22,7 @@ evergreen 0x9400
 0x000089A4 VGT_COMPUTE_START_Z
 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
 0x00008A14 PA_CL_ENHANCE
-0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008A60 PA_SU_LINE_STIPPLE_VALUE
 0x00008B10 PA_SC_LINE_STIPPLE_STATE
 0x00008BF0 PA_SC_ENHANCE
 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
@@ -545,7 +545,7 @@ evergreen 0x9400
 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
-0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028B90 VGT_GS_INSTANCE_CNT
 0x00028C00 PA_SC_LINE_CNTL
 0x00028C08 PA_SU_VTX_CNTL
 0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
index 1c560629575a8906fb74e006285096f07eac7f19..e7dab069cccf48a05e19cfd7caf27bd65d38c53d 100644 (file)
@@ -162,6 +162,16 @@ static void rs690_mc_init(struct radeon_device *rdev)
        base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
        base = G_000100_MC_FB_START(base) << 16;
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+       /* Some boards seem to be configured for 128MB of sideport memory,
+        * but really only have 64MB.  Just skip the sideport and use
+        * UMA memory.
+        */
+       if (rdev->mc.igp_sideport_enabled &&
+           (rdev->mc.real_vram_size == (384 * 1024 * 1024))) {
+               base += 128 * 1024 * 1024;
+               rdev->mc.real_vram_size -= 128 * 1024 * 1024;
+               rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+       }
 
        /* Use K8 direct mapping for fast fb access. */ 
        rdev->fastfb_working = false;
index 913b025ae9b399695bed47af97cccf08fe68caf7..374499db20c7e59b55d956b066a30bdc42b4f71f 100644 (file)
@@ -2328,6 +2328,12 @@ void rv770_get_engine_memory_ss(struct radeon_device *rdev)
        pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
                                                       ASIC_INTERNAL_MEMORY_SS, 0);
 
+       /* disable ss, causes hangs on some cayman boards */
+       if (rdev->family == CHIP_CAYMAN) {
+               pi->sclk_ss = false;
+               pi->mclk_ss = false;
+       }
+
        if (pi->sclk_ss || pi->mclk_ss)
                pi->dynamic_ss = true;
        else
index 6a64ccaa0695643add9ee7e6b3f383202d35a988..a36736dab5e0694cd5a7b78d6dbb013b484cb8f6 100644 (file)
@@ -3882,8 +3882,15 @@ static int si_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        /* size in MB on si */
-       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
-       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+       tmp = RREG32(CONFIG_MEMSIZE);
+       /* some boards may have garbage in the upper 16 bits */
+       if (tmp & 0xffff0000) {
+               DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
+               if (tmp & 0xffff)
+                       tmp &= 0xffff;
+       }
+       rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL;
+       rdev->mc.real_vram_size = rdev->mc.mc_vram_size;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        si_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
index 28e178137718090f317c8884da071458900cce65..07eba596d458d22b63bc9f0a731d6ca3befae036 100644 (file)
@@ -135,11 +135,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
        unsigned int num_relocs = args->num_relocs;
        unsigned int num_waitchks = args->num_waitchks;
        struct drm_tegra_cmdbuf __user *cmdbufs =
-               (void * __user)(uintptr_t)args->cmdbufs;
+               (void __user *)(uintptr_t)args->cmdbufs;
        struct drm_tegra_reloc __user *relocs =
-               (void * __user)(uintptr_t)args->relocs;
+               (void __user *)(uintptr_t)args->relocs;
        struct drm_tegra_waitchk __user *waitchks =
-               (void * __user)(uintptr_t)args->waitchks;
+               (void __user *)(uintptr_t)args->waitchks;
        struct drm_tegra_syncpt syncpt;
        struct host1x_job *job;
        int err;
@@ -163,9 +163,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                struct drm_tegra_cmdbuf cmdbuf;
                struct host1x_bo *bo;
 
-               err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
-               if (err)
+               if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) {
+                       err = -EFAULT;
                        goto fail;
+               }
 
                bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
                if (!bo) {
@@ -178,10 +179,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                cmdbufs++;
        }
 
-       err = copy_from_user(job->relocarray, relocs,
-                            sizeof(*relocs) * num_relocs);
-       if (err)
+       if (copy_from_user(job->relocarray, relocs,
+                          sizeof(*relocs) * num_relocs)) {
+               err = -EFAULT;
                goto fail;
+       }
 
        while (num_relocs--) {
                struct host1x_reloc *reloc = &job->relocarray[num_relocs];
@@ -199,15 +201,17 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                }
        }
 
-       err = copy_from_user(job->waitchk, waitchks,
-                            sizeof(*waitchks) * num_waitchks);
-       if (err)
+       if (copy_from_user(job->waitchk, waitchks,
+                          sizeof(*waitchks) * num_waitchks)) {
+               err = -EFAULT;
                goto fail;
+       }
 
-       err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
-                            sizeof(syncpt));
-       if (err)
+       if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts,
+                          sizeof(syncpt))) {
+               err = -EFAULT;
                goto fail;
+       }
 
        job->is_addr_reg = context->client->ops->is_addr_reg;
        job->syncpt_incrs = syncpt.incrs;
@@ -573,7 +577,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
 }
 #endif
 
-struct drm_driver tegra_drm_driver = {
+static struct drm_driver tegra_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
index fdfe259ed7f8e5e403f984d533b54a3257128aef..7da0b923131f05ca5f67fb8113f2fd9754023a15 100644 (file)
@@ -116,7 +116,7 @@ host1x_client_to_dc(struct host1x_client *client)
 
 static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
 {
-       return container_of(crtc, struct tegra_dc, base);
+       return crtc ? container_of(crtc, struct tegra_dc, base) : NULL;
 }
 
 static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
index 490f7719e317ed80319f4961a69d3e349d1ad333..a3835e7de1842b84145e52c40ef15ed21e183323 100644 (file)
@@ -247,7 +247,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
                 info->var.yoffset * fb->pitches[0];
 
        drm->mode_config.fb_base = (resource_size_t)bo->paddr;
-       info->screen_base = bo->vaddr + offset;
+       info->screen_base = (void __iomem *)bo->vaddr + offset;
        info->screen_size = size;
        info->fix.smem_start = (unsigned long)(bo->paddr + offset);
        info->fix.smem_len = size;
index ba47ca4fb880cc239a9b5c454b3b6c5b5adcddc8..3b29018913a5f2bb9da1a2ae2f57ddc89280bbe8 100644 (file)
@@ -14,6 +14,8 @@
 
 struct tegra_rgb {
        struct tegra_output output;
+       struct tegra_dc *dc;
+
        struct clk *clk_parent;
        struct clk *clk;
 };
@@ -84,18 +86,18 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
 
 static int tegra_output_rgb_enable(struct tegra_output *output)
 {
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_rgb *rgb = to_rgb(output);
 
-       tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
+       tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
        return 0;
 }
 
 static int tegra_output_rgb_disable(struct tegra_output *output)
 {
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_rgb *rgb = to_rgb(output);
 
-       tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
+       tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
        return 0;
 }
@@ -146,6 +148,7 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
 
        rgb->output.dev = dc->dev;
        rgb->output.of_node = np;
+       rgb->dc = dc;
 
        err = tegra_output_probe(&rgb->output);
        if (err < 0)
index 15b86a94949dcb875d3cd716322875ad8c763e88..4061521523154e0fbc102623b6a9d348e03d0313 100644 (file)
@@ -353,7 +353,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
         * Don't move nonexistent data. Clear destination instead.
         */
        if (old_iomap == NULL &&
-           (ttm == NULL || ttm->state == tt_unpopulated)) {
+           (ttm == NULL || (ttm->state == tt_unpopulated &&
+                            !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) {
                memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
                goto out2;
        }
index b249ab9b1eb29c402d407049a42c2fda83b3ffb1..6440eeac22d250844d2203018258654e54483cd3 100644 (file)
@@ -169,9 +169,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
-           drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
-       page_last = vma_pages(vma) +
-           drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
+               vma->vm_pgoff - drm_vma_node_start(&bo->vma_node);
+       page_last = vma_pages(vma) + vma->vm_pgoff -
+               drm_vma_node_start(&bo->vma_node);
 
        if (unlikely(page_offset >= bo->num_pages)) {
                retval = VM_FAULT_SIGBUS;
index 24ffbe990736e3e0751609e78d113d08c952b69f..8d67b943ac05ce2d1dd44597d00a1e5a07fd9bdb 100644 (file)
@@ -125,6 +125,12 @@ static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask)
 
 static void udl_gem_put_pages(struct udl_gem_object *obj)
 {
+       if (obj->base.import_attach) {
+               drm_free_large(obj->pages);
+               obj->pages = NULL;
+               return;
+       }
+
        drm_gem_put_pages(&obj->base, obj->pages, false, false);
        obj->pages = NULL;
 }
index 7776e6f0aef650d475e39640b3d781b42f8d7036..0489c61524826f2e2b673628783393639f0c591e 100644 (file)
@@ -150,6 +150,8 @@ struct vmw_ttm_tt {
        bool mapped;
 };
 
+const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
+
 /**
  * Helper functions to advance a struct vmw_piter iterator.
  *
index db85985c7086f04648b6a4bb89b83f352c393ec2..20890ad8408bb5ef377c4ff54c80397c3105efaf 100644 (file)
@@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
  * TTM buffer object driver - vmwgfx_buffer.c
  */
 
+extern const size_t vmw_tt_size;
 extern struct ttm_placement vmw_vram_placement;
 extern struct ttm_placement vmw_vram_ne_placement;
 extern struct ttm_placement vmw_vram_sys_placement;
index a51f48e3e917e0d3f5d4c73202be335df6f6919b..45d5b5ab6ca9d8788fe80f0fbfd9f164203c026a 100644 (file)
@@ -68,6 +68,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                                  SVGA_FIFO_3D_HWVERSION));
                break;
        }
+       case DRM_VMW_PARAM_MAX_SURF_MEMORY:
+               param->value = dev_priv->memory_size;
+               break;
        default:
                DRM_ERROR("Illegal vmwgfx get param request: %d\n",
                          param->param);
index ecb3d867b4260d9c9ada27438fb252dac1fc77e9..03f1c203863193621d9941af3051169ea2f79afb 100644 (file)
@@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du)
                vmw_surface_unreference(&du->cursor_surface);
        if (du->cursor_dmabuf)
                vmw_dmabuf_unreference(&du->cursor_dmabuf);
+       drm_sysfs_connector_remove(&du->connector);
        drm_crtc_cleanup(&du->crtc);
        drm_encoder_cleanup(&du->encoder);
        drm_connector_cleanup(&du->connector);
index 79f7e8e605296902bb4355b78e2e78d1792f89fa..a055a26819c2b6b7963d6d245576e17b8d9a7500 100644 (file)
@@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
                connector->encoder = NULL;
                encoder->crtc = NULL;
                crtc->fb = NULL;
+               crtc->enabled = false;
 
                vmw_ldu_del_active(dev_priv, ldu);
 
@@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
        crtc->x = set->x;
        crtc->y = set->y;
        crtc->mode = *mode;
+       crtc->enabled = true;
 
        vmw_ldu_add_active(dev_priv, ldu, vfb);
 
@@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
+       (void) drm_sysfs_connector_add(connector);
+
        drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
        drm_mode_crtc_set_gamma_size(crtc, 256);
index efe2b74c5eb17f1f86b12048be5884c9aabf50b2..9b5ea2ac7ddff21562aa7ef52a2f96872c623116 100644 (file)
@@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
 /**
  * Buffer management.
  */
+
+/**
+ * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers
+ *
+ * @dev_priv: Pointer to a struct vmw_private identifying the device.
+ * @size: The requested buffer size.
+ * @user: Whether this is an ordinary dma buffer or a user dma buffer.
+ */
+static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size,
+                                 bool user)
+{
+       static size_t struct_size, user_struct_size;
+       size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+       size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *));
+
+       if (unlikely(struct_size == 0)) {
+               size_t backend_size = ttm_round_pot(vmw_tt_size);
+
+               struct_size = backend_size +
+                       ttm_round_pot(sizeof(struct vmw_dma_buffer));
+               user_struct_size = backend_size +
+                       ttm_round_pot(sizeof(struct vmw_user_dma_buffer));
+       }
+
+       if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+               page_array_size +=
+                       ttm_round_pot(num_pages * sizeof(dma_addr_t));
+
+       return ((user) ? user_struct_size : struct_size) +
+               page_array_size;
+}
+
 void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
 {
        struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
@@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
        kfree(vmw_bo);
 }
 
+static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
+{
+       struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
+
+       ttm_prime_object_kfree(vmw_user_bo, prime);
+}
+
 int vmw_dmabuf_init(struct vmw_private *dev_priv,
                    struct vmw_dma_buffer *vmw_bo,
                    size_t size, struct ttm_placement *placement,
@@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
        struct ttm_bo_device *bdev = &dev_priv->bdev;
        size_t acc_size;
        int ret;
+       bool user = (bo_free == &vmw_user_dmabuf_destroy);
 
-       BUG_ON(!bo_free);
+       BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free)));
 
-       acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer));
+       acc_size = vmw_dmabuf_acc_size(dev_priv, size, user);
        memset(vmw_bo, 0, sizeof(*vmw_bo));
 
        INIT_LIST_HEAD(&vmw_bo->res_list);
 
        ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-                         ttm_bo_type_device, placement,
+                         (user) ? ttm_bo_type_device :
+                         ttm_bo_type_kernel, placement,
                          0, interruptible,
                          NULL, acc_size, NULL, bo_free);
        return ret;
 }
 
-static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
-{
-       struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
-
-       ttm_prime_object_kfree(vmw_user_bo, prime);
-}
-
 static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
 {
        struct vmw_user_dma_buffer *vmw_user_bo;
@@ -781,54 +815,55 @@ err_ref:
 }
 
 
+/**
+ * vmw_dumb_create - Create a dumb kms buffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @args: Pointer to a struct drm_mode_create_dumb structure
+ *
+ * This is a driver callback for the core drm create_dumb functionality.
+ * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except
+ * that the arguments have a different format.
+ */
 int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
                    struct drm_mode_create_dumb *args)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct vmw_master *vmaster = vmw_master(file_priv->master);
-       struct vmw_user_dma_buffer *vmw_user_bo;
-       struct ttm_buffer_object *tmp;
+       struct vmw_dma_buffer *dma_buf;
        int ret;
 
        args->pitch = args->width * ((args->bpp + 7) / 8);
        args->size = args->pitch * args->height;
 
-       vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
-       if (vmw_user_bo == NULL)
-               return -ENOMEM;
-
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (ret != 0) {
-               kfree(vmw_user_bo);
+       if (unlikely(ret != 0))
                return ret;
-       }
 
-       ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size,
-                             &vmw_vram_sys_placement, true,
-                             &vmw_user_dmabuf_destroy);
-       if (ret != 0)
-               goto out_no_dmabuf;
-
-       tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
-       ret = ttm_prime_object_init(vmw_fpriv(file_priv)->tfile,
-                                   args->size,
-                                   &vmw_user_bo->prime,
-                                   false,
-                                   ttm_buffer_type,
-                                   &vmw_user_dmabuf_release, NULL);
+       ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
+                                   args->size, false, &args->handle,
+                                   &dma_buf);
        if (unlikely(ret != 0))
-               goto out_no_base_object;
-
-       args->handle = vmw_user_bo->prime.base.hash.key;
+               goto out_no_dmabuf;
 
-out_no_base_object:
-       ttm_bo_unref(&tmp);
+       vmw_dmabuf_unreference(&dma_buf);
 out_no_dmabuf:
        ttm_read_unlock(&vmaster->lock);
        return ret;
 }
 
+/**
+ * vmw_dumb_map_offset - Return the address space offset of a dumb buffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @handle: Handle identifying the dumb buffer.
+ * @offset: The address space offset returned.
+ *
+ * This is a driver callback for the core drm dumb_map_offset functionality.
+ */
 int vmw_dumb_map_offset(struct drm_file *file_priv,
                        struct drm_device *dev, uint32_t handle,
                        uint64_t *offset)
@@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
        return 0;
 }
 
+/**
+ * vmw_dumb_destroy - Destroy a dumb boffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @handle: Handle identifying the dumb buffer.
+ *
+ * This is a driver callback for the core drm dumb_destroy functionality.
+ */
 int vmw_dumb_destroy(struct drm_file *file_priv,
                     struct drm_device *dev,
                     uint32_t handle)
index 26387c3d5a21f01c51d844c228f26a6232b84453..22406c8651ead6caa629ce6ae2de963bdd0a35d7 100644 (file)
@@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
                crtc->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
+               crtc->enabled = false;
 
                vmw_sou_del_active(dev_priv, sou);
 
@@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
                crtc->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
+               crtc->enabled = false;
 
                return ret;
        }
@@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
        crtc->fb = fb;
        crtc->x = set->x;
        crtc->y = set->y;
+       crtc->enabled = true;
 
        return 0;
 }
@@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
+       (void) drm_sysfs_connector_add(connector);
+
        drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
 
        drm_mode_crtc_set_gamma_size(crtc, 256);
index 509383f8be034ec3512c95b1c2100818bad5d71e..6a929591aa73801df1126433bc514980e80d1465 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
+#include "bus.h"
 #include "dev.h"
 
 static DEFINE_MUTEX(clients_lock);
@@ -257,7 +258,7 @@ static int host1x_unregister_client(struct host1x *host1x,
        return -ENODEV;
 }
 
-struct bus_type host1x_bus_type = {
+static struct bus_type host1x_bus_type = {
        .name = "host1x",
 };
 
@@ -301,7 +302,7 @@ static int host1x_device_add(struct host1x *host1x,
        device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
        device->dev.dma_mask = &device->dev.coherent_dma_mask;
        device->dev.release = host1x_device_release;
-       dev_set_name(&device->dev, driver->name);
+       dev_set_name(&device->dev, "%s", driver->name);
        device->dev.bus = &host1x_bus_type;
        device->dev.parent = host1x->dev;
 
index 37e2a63241a9d6150b1554896fde15ac0294c157..6b09b71940c2d5df0251ec2b3cd417ec2eb93e2d 100644 (file)
@@ -54,8 +54,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,
                u32 *p = (u32 *)((u32)pb->mapped + getptr);
                *(p++) = HOST1X_OPCODE_NOP;
                *(p++) = HOST1X_OPCODE_NOP;
-               dev_dbg(host1x->dev, "%s: NOP at 0x%x\n", __func__,
-                       pb->phys + getptr);
+               dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__,
+                       (u64)pb->phys + getptr);
                getptr = (getptr + 8) & (pb->size_bytes - 1);
        }
        wmb();
index 640c75ca5a8bbc465dcc9f1350d4f5efdd928d5d..f72c873eff819f831202a742cf02ec70e94753f2 100644 (file)
@@ -163,8 +163,8 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
                                continue;
                        }
 
-                       host1x_debug_output(o, "    GATHER at %08x+%04x, %d words\n",
-                                           g->base, g->offset, g->words);
+                       host1x_debug_output(o, "    GATHER at %#llx+%04x, %d words\n",
+                                           (u64)g->base, g->offset, g->words);
 
                        show_gather(o, g->base + g->offset, g->words, cdma,
                                    g->base, mapped);
index 329fbb9b59766f82af6c744e4e85a6ee1dc88208..34e2d39d4ce814cb312de6eee14dae43179cb5c3 100644 (file)
@@ -460,6 +460,7 @@ config HID_MULTITOUCH
          - Stantum multitouch panels
          - Touch International Panels
          - Unitec Panels
+         - Wistron optical touch panels
          - XAT optical touch panels
          - Xiroku optical touch panels
          - Zytronic touch panels
index a42e6a394c5ec33d663f7a00eadd2b362c24763d..0e6a42d37eb6f374ef864f383fc23d15bf844736 100644 (file)
@@ -297,6 +297,9 @@ static int appleir_probe(struct hid_device *hid, const struct hid_device_id *id)
 
        appleir->hid = hid;
 
+       /* force input as some remotes bypass the input registration */
+       hid->quirks |= HID_QUIRK_HIDINPUT_FORCE;
+
        spin_lock_init(&appleir->lock);
        setup_timer(&appleir->key_up_timer,
                    key_up_tick, (unsigned long) appleir);
index 8c10f2742233e2f731aa7b798f49b178cee93279..253fe23ef7fe5332ea03f96449f312a69a6b80c0 100644 (file)
@@ -1723,6 +1723,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_MANTICORE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
@@ -1879,7 +1880,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO2, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
        { }
 };
index 76559629568c44dc2fd5b38c072faf446c063b17..f9304cb37154982da4de6774894c213bf412163f 100644 (file)
 #define USB_VENDOR_ID_KYE              0x0458
 #define USB_DEVICE_ID_KYE_ERGO_525V    0x0087
 #define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138
+#define USB_DEVICE_ID_GENIUS_MANTICORE 0x0153
 #define USB_DEVICE_ID_GENIUS_GX_IMPERATOR      0x4018
 #define USB_DEVICE_ID_KYE_GPEN_560     0x5003
 #define USB_DEVICE_ID_KYE_EASYPEN_I405X        0x5010
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN   0x0003
 
 #define USB_VENDOR_ID_NINTENDO         0x057e
-#define USB_VENDOR_ID_NINTENDO2                0x054c
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE2        0x0330
 
 #define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802
 #define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804
 
+#define USB_VENDOR_ID_WISTRON          0x0fb8
+#define USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH            0x1109
+
 #define USB_VENDOR_ID_X_TENSIONS               0x1ae7
 #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE    0x9001
 
index 73845120295eba6f678679715c9ca3f97917a643..e7769636759129f2540c5c670f1cc332180191fe 100644 (file)
@@ -342,6 +342,10 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
                                        "Genius Gx Imperator Keyboard");
                break;
+       case USB_DEVICE_ID_GENIUS_MANTICORE:
+               rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
+                                       "Genius Manticore Keyboard");
+               break;
        }
        return rdesc;
 }
@@ -418,6 +422,14 @@ static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id)
                        goto enabling_err;
                }
                break;
+       case USB_DEVICE_ID_GENIUS_MANTICORE:
+               /*
+                * The manticore keyboard needs to have all the interfaces
+                * opened at least once to be fully functional.
+                */
+               if (hid_hw_open(hdev))
+                       hid_hw_close(hdev);
+               break;
        }
 
        return 0;
@@ -439,6 +451,8 @@ static const struct hid_device_id kye_devices[] = {
                                USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
                                USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+                               USB_DEVICE_ID_GENIUS_MANTICORE) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, kye_devices);
index a2cedb8ae1c0cf57c98e185e7b285d7555834b1a..d83b1e8b505b512769d8c5955eb8a0b8ca4e5b23 100644 (file)
@@ -1335,6 +1335,12 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
                        USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+
+       /* Wistron panels */
+       { .driver_data = MT_CLS_NSMU,
+               MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
+                       USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) },
+
        /* XAT */
        { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XAT,
index a184e1921c11190ffce1033e5b7d4f512d55f798..8fab82829f8b11321f957059837e8f50feb71828 100644 (file)
@@ -112,13 +112,15 @@ static int sensor_hub_get_physical_device_count(
 
 static void sensor_hub_fill_attr_info(
                struct hid_sensor_hub_attribute_info *info,
-               s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size)
+               s32 index, s32 report_id, struct hid_field *field)
 {
        info->index = index;
        info->report_id = report_id;
-       info->units = units;
-       info->unit_expo = unit_expo;
-       info->size = size/8;
+       info->units = field->unit;
+       info->unit_expo = field->unit_exponent;
+       info->size = (field->report_size * field->report_count)/8;
+       info->logical_minimum = field->logical_minimum;
+       info->logical_maximum = field->logical_maximum;
 }
 
 static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
@@ -325,9 +327,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                        if (field->physical == usage_id &&
                                field->logical == attr_usage_id) {
                                sensor_hub_fill_attr_info(info, i, report->id,
-                                       field->unit, field->unit_exponent,
-                                       field->report_size *
-                                                       field->report_count);
+                                                         field);
                                ret = 0;
                        } else {
                                for (j = 0; j < field->maxusage; ++j) {
@@ -336,11 +336,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                                        field->usage[j].collection_index ==
                                        collection_index) {
                                                sensor_hub_fill_attr_info(info,
-                                                       i, report->id,
-                                                       field->unit,
-                                                       field->unit_exponent,
-                                                       field->report_size *
-                                                       field->report_count);
+                                                         i, report->id, field);
                                                ret = 0;
                                                break;
                                        }
@@ -572,6 +568,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
                                        ret = -ENOMEM;
                                        goto err_free_names;
                        }
+                       sd->hid_sensor_hub_client_devs[
+                               sd->hid_sensor_client_cnt].id = PLATFORM_DEVID_AUTO;
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].name = name;
                        sd->hid_sensor_hub_client_devs[
index da551d11376257a328419e22ad7cd487784bea51..098af2f84b8c653dca9542d78de33c5c5777fe8b 100644 (file)
@@ -225,6 +225,13 @@ static const unsigned int buzz_keymap[] = {
 struct sony_sc {
        unsigned long quirks;
 
+#ifdef CONFIG_SONY_FF
+       struct work_struct rumble_worker;
+       struct hid_device *hdev;
+       __u8 left;
+       __u8 right;
+#endif
+
        void *extra;
 };
 
@@ -615,9 +622,9 @@ static void buzz_remove(struct hid_device *hdev)
 }
 
 #ifdef CONFIG_SONY_FF
-static int sony_play_effect(struct input_dev *dev, void *data,
-                           struct ff_effect *effect)
+static void sony_rumble_worker(struct work_struct *work)
 {
+       struct sony_sc *sc = container_of(work, struct sony_sc, rumble_worker);
        unsigned char buf[] = {
                0x01,
                0x00, 0xff, 0x00, 0xff, 0x00,
@@ -628,21 +635,28 @@ static int sony_play_effect(struct input_dev *dev, void *data,
                0xff, 0x27, 0x10, 0x00, 0x32,
                0x00, 0x00, 0x00, 0x00, 0x00
        };
-       __u8 left;
-       __u8 right;
+
+       buf[3] = sc->right;
+       buf[5] = sc->left;
+
+       sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
+                                       HID_OUTPUT_REPORT);
+}
+
+static int sony_play_effect(struct input_dev *dev, void *data,
+                           struct ff_effect *effect)
+{
        struct hid_device *hid = input_get_drvdata(dev);
+       struct sony_sc *sc = hid_get_drvdata(hid);
 
        if (effect->type != FF_RUMBLE)
                return 0;
 
-       left = effect->u.rumble.strong_magnitude / 256;
-       right = effect->u.rumble.weak_magnitude ? 1 : 0;
-
-       buf[3] = right;
-       buf[5] = left;
+       sc->left = effect->u.rumble.strong_magnitude / 256;
+       sc->right = effect->u.rumble.weak_magnitude ? 1 : 0;
 
-       return hid->hid_output_raw_report(hid, buf, sizeof(buf),
-                                         HID_OUTPUT_REPORT);
+       schedule_work(&sc->rumble_worker);
+       return 0;
 }
 
 static int sony_init_ff(struct hid_device *hdev)
@@ -650,16 +664,31 @@ static int sony_init_ff(struct hid_device *hdev)
        struct hid_input *hidinput = list_entry(hdev->inputs.next,
                                                struct hid_input, list);
        struct input_dev *input_dev = hidinput->input;
+       struct sony_sc *sc = hid_get_drvdata(hdev);
+
+       sc->hdev = hdev;
+       INIT_WORK(&sc->rumble_worker, sony_rumble_worker);
 
        input_set_capability(input_dev, EV_FF, FF_RUMBLE);
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
 }
 
+static void sony_destroy_ff(struct hid_device *hdev)
+{
+       struct sony_sc *sc = hid_get_drvdata(hdev);
+
+       cancel_work_sync(&sc->rumble_worker);
+}
+
 #else
 static int sony_init_ff(struct hid_device *hdev)
 {
        return 0;
 }
+
+static void sony_destroy_ff(struct hid_device *hdev)
+{
+}
 #endif
 
 static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -728,6 +757,8 @@ static void sony_remove(struct hid_device *hdev)
        if (sc->quirks & BUZZ_CONTROLLER)
                buzz_remove(hdev);
 
+       sony_destroy_ff(hdev);
+
        hid_hw_stop(hdev);
 }
 
index 1446f526ee8bbade2290b615fc14b6aae35dc09f..abb20db2b443ccdcc34159a97fcc83307db65c40 100644 (file)
@@ -834,8 +834,7 @@ static void wiimote_init_set_type(struct wiimote_data *wdata,
                goto done;
        }
 
-       if (vendor == USB_VENDOR_ID_NINTENDO ||
-           vendor == USB_VENDOR_ID_NINTENDO2) {
+       if (vendor == USB_VENDOR_ID_NINTENDO) {
                if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE) {
                        devtype = WIIMOTE_DEV_GEN10;
                        goto done;
@@ -1856,8 +1855,6 @@ static void wiimote_hid_remove(struct hid_device *hdev)
 static const struct hid_device_id wiimote_hid_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
                                USB_DEVICE_ID_NINTENDO_WIIMOTE) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO2,
-                               USB_DEVICE_ID_NINTENDO_WIIMOTE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
                                USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
        { }
index 93b00d76374cee2b82be0a9deab2a0f8d7c6755b..cedc6da93c19c5c77136127feb207a424899a321 100644 (file)
@@ -287,7 +287,7 @@ static int uhid_event_from_user(const char __user *buffer, size_t len,
                         */
                        struct uhid_create_req_compat *compat;
 
-                       compat = kmalloc(sizeof(*compat), GFP_KERNEL);
+                       compat = kzalloc(sizeof(*compat), GFP_KERNEL);
                        if (!compat)
                                return -ENOMEM;
 
index 1d7ff46812c3dc9d72abb977b02cbf4db04fbd2c..dafc63c6932dfa47001a0269fc283984c16c321e 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/err.h>
 
 #include <acpi/acpi.h>
-#include <acpi/acpixf.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 
index 2dc37c7c6947cfa6dd5fde0e72ff5701f7162dd0..7d68a08baaa83eb42366e17c29b4ff88bda68152 100644 (file)
@@ -43,6 +43,7 @@
  * @last_update: time of last update (jiffies)
  * @temperature: cached temperature measurement value
  * @humidity: cached humidity measurement value
+ * @write_length: length for I2C measurement request
  */
 struct hih6130 {
        struct device *hwmon_dev;
@@ -51,6 +52,7 @@ struct hih6130 {
        unsigned long last_update;
        int temperature;
        int humidity;
+       size_t write_length;
 };
 
 /**
@@ -121,8 +123,15 @@ static int hih6130_update_measurements(struct i2c_client *client)
         */
        if (time_after(jiffies, hih6130->last_update + HZ) || !hih6130->valid) {
 
-               /* write to slave address, no data, to request a measurement */
-               ret = i2c_master_send(client, tmp, 0);
+               /*
+                * Write to slave address to request a measurement.
+                * According with the datasheet it should be with no data, but
+                * for systems with I2C bus drivers that do not allow zero
+                * length packets we write one dummy byte to allow sensor
+                * measurements on them.
+                */
+               tmp[0] = 0;
+               ret = i2c_master_send(client, tmp, hih6130->write_length);
                if (ret < 0)
                        goto out;
 
@@ -252,6 +261,9 @@ static int hih6130_probe(struct i2c_client *client,
                goto fail_remove_sysfs;
        }
 
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
+               hih6130->write_length = 1;
+
        return 0;
 
 fail_remove_sysfs:
index 6cf6bff790033756a70d1d57ebe9f8f1096899f8..a2f3b4a365e4bbafa17385df4fdca298a7ece0e5 100644 (file)
@@ -94,6 +94,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm <= 0)
                return 255;
+       if (rpm > 1350000)
+               return 1;
        return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
index 4c4c1421bf28f66462d8d0bf5f2ee70947005ac0..8b8f3aa49726873b89267ebe45f4e145eab2c7bb 100644 (file)
@@ -1610,12 +1610,14 @@ static int lm90_probe(struct i2c_client *client,
                                                "lm90", client);
                if (err < 0) {
                        dev_err(dev, "cannot request IRQ %d\n", client->irq);
-                       goto exit_remove_files;
+                       goto exit_unregister;
                }
        }
 
        return 0;
 
+exit_unregister:
+       hwmon_device_unregister(data->hwmon_dev);
 exit_remove_files:
        lm90_remove_files(client, data);
 exit_restore:
index 1404e6319deb3cf918c1874f1be8b09b85902d65..72a889702f0dc091b895f653ce39a540aa40bf3b 100644 (file)
@@ -141,6 +141,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm <= 0)
                return 255;
+       if (rpm > 1350000)
+               return 1;
        return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
index 0e7017841f7dacb9b1341e4313f4acaf009349a6..aee14e2192f8813dbb59dee615142db9505dcd9a 100644 (file)
@@ -145,7 +145,7 @@ static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
  */
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
-       if (rpm == 0)
+       if (rpm <= 0 || rpm > 1310720)
                return 0;
        return clamp_val(1310720 / (rpm * div), 1, 255);
 }
index edb06cda5a689a4be87046b138051f5b4b42e3ca..6ed76ceb92709078497571ad4cb6f8740d3490bb 100644 (file)
@@ -481,9 +481,11 @@ store_pwm(struct device *dev, struct device_attribute *attr,
        if (err)
                return err;
        val = clamp_val(val, 0, 255);
+       val = DIV_ROUND_CLOSEST(val, 0x11);
 
        mutex_lock(&data->update_lock);
-       data->pwm[nr] = val;
+       data->pwm[nr] = val * 0x11;
+       val |= w83l786ng_read_value(client, W83L786NG_REG_PWM[nr]) & 0xf0;
        w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val);
        mutex_unlock(&data->update_lock);
        return count;
@@ -510,7 +512,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
        mutex_lock(&data->update_lock);
        reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
        data->pwm_enable[nr] = val;
-       reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
+       reg &= ~(0x03 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
        reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr];
        w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg);
        mutex_unlock(&data->update_lock);
@@ -776,9 +778,10 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
                            ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
                            ? 0 : 1;
                        data->pwm_enable[i] =
-                           ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1;
-                       data->pwm[i] = w83l786ng_read_value(client,
-                           W83L786NG_REG_PWM[i]);
+                           ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
+                       data->pwm[i] =
+                           (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
+                            & 0x0f) * 0x11;
                }
 
 
index 036cf03aeb612a7c62641c65e94552eb6c09af04..18a74a6751a97101568cb5d084b0f840e19322f7 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/slab.h>
 
 /* Hardware register offsets and field defintions */
@@ -891,7 +890,7 @@ static const struct of_device_id bcm_kona_i2c_of_match[] = {
        {.compatible = "brcm,kona-i2c",},
        {},
 };
-MODULE_DEVICE_TABLE(of, kona_i2c_of_match);
+MODULE_DEVICE_TABLE(of, bcm_kona_i2c_of_match);
 
 static struct platform_driver bcm_kona_i2c_driver = {
        .driver = {
index d7e8600f31fbba8c4eaec181e9c1b277b7c7740d..77df97b932af5399a39b0c52ec7e256aff4c8325 100644 (file)
@@ -299,6 +299,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
        strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
        adap->algo = &bcm2835_i2c_algo;
        adap->dev.parent = &pdev->dev;
+       adap->dev.of_node = pdev->dev.of_node;
 
        bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
 
index ff05d9fef4a8ee22f40c981bd11e90e9ad24e51e..af0b5830303d761378d9111ac141bda6502dd665 100644 (file)
@@ -125,12 +125,12 @@ static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = {
 static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev,
                                         int reg, u16 val)
 {
-       __raw_writew(val, i2c_dev->base + reg);
+       writew_relaxed(val, i2c_dev->base + reg);
 }
 
 static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
 {
-       return __raw_readw(i2c_dev->base + reg);
+       return readw_relaxed(i2c_dev->base + reg);
 }
 
 /* Generate a pulse on the i2c clock pin. */
index dae3ddfe7619cf69899d974992ea0e7b43264b59..721f7ebf9a3bcb034867dd8acfbb33236bf21e46 100644 (file)
@@ -25,8 +25,6 @@
 #define USB_VENDOR_ID_DIOLAN           0x0abf
 #define USB_DEVICE_ID_DIOLAN_U2C       0x3370
 
-#define DIOLAN_OUT_EP          0x02
-#define DIOLAN_IN_EP           0x84
 
 /* commands via USB, must match command ids in the firmware */
 #define CMD_I2C_READ           0x01
@@ -84,6 +82,7 @@
 struct i2c_diolan_u2c {
        u8 obuffer[DIOLAN_OUTBUF_LEN];  /* output buffer */
        u8 ibuffer[DIOLAN_INBUF_LEN];   /* input buffer */
+       int ep_in, ep_out;              /* Endpoints    */
        struct usb_device *usb_dev;     /* the usb device for this device */
        struct usb_interface *interface;/* the interface for this device */
        struct i2c_adapter adapter;     /* i2c related things */
@@ -109,7 +108,7 @@ static int diolan_usb_transfer(struct i2c_diolan_u2c *dev)
                return -EINVAL;
 
        ret = usb_bulk_msg(dev->usb_dev,
-                          usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP),
+                          usb_sndbulkpipe(dev->usb_dev, dev->ep_out),
                           dev->obuffer, dev->olen, &actual,
                           DIOLAN_USB_TIMEOUT);
        if (!ret) {
@@ -118,7 +117,7 @@ static int diolan_usb_transfer(struct i2c_diolan_u2c *dev)
 
                        tmpret = usb_bulk_msg(dev->usb_dev,
                                              usb_rcvbulkpipe(dev->usb_dev,
-                                                             DIOLAN_IN_EP),
+                                                             dev->ep_in),
                                              dev->ibuffer,
                                              sizeof(dev->ibuffer), &actual,
                                              DIOLAN_USB_TIMEOUT);
@@ -210,7 +209,7 @@ static void diolan_flush_input(struct i2c_diolan_u2c *dev)
                int ret;
 
                ret = usb_bulk_msg(dev->usb_dev,
-                                  usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP),
+                                  usb_rcvbulkpipe(dev->usb_dev, dev->ep_in),
                                   dev->ibuffer, sizeof(dev->ibuffer), &actual,
                                   DIOLAN_USB_TIMEOUT);
                if (ret < 0 || actual == 0)
@@ -445,9 +444,14 @@ static void diolan_u2c_free(struct i2c_diolan_u2c *dev)
 static int diolan_u2c_probe(struct usb_interface *interface,
                            const struct usb_device_id *id)
 {
+       struct usb_host_interface *hostif = interface->cur_altsetting;
        struct i2c_diolan_u2c *dev;
        int ret;
 
+       if (hostif->desc.bInterfaceNumber != 0
+           || hostif->desc.bNumEndpoints < 2)
+               return -ENODEV;
+
        /* allocate memory for our device state and initialize it */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
@@ -455,6 +459,8 @@ static int diolan_u2c_probe(struct usb_interface *interface,
                ret = -ENOMEM;
                goto error;
        }
+       dev->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
+       dev->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
 
        dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
index 1d7efa3169cd772ed2ba580b0c8cfd149eee09d5..d0cfbb4cb9643498540799281399cd1b314b91e3 100644 (file)
@@ -312,7 +312,9 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-       clk_prepare_enable(i2c_imx->clk);
+       result = clk_prepare_enable(i2c_imx->clk);
+       if (result)
+               return result;
        imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
        /* Enable I2C controller */
        imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
index a6a891d7970dd373414ca23ea7dd6924535dee38..90dcc2eaac5fb688fedba904b181be2312e40b3d 100644 (file)
@@ -266,13 +266,13 @@ static const u8 reg_map_ip_v2[] = {
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
                                      int reg, u16 val)
 {
-       __raw_writew(val, i2c_dev->base +
+       writew_relaxed(val, i2c_dev->base +
                        (i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
 static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
 {
-       return __raw_readw(i2c_dev->base +
+       return readw_relaxed(i2c_dev->base +
                                (i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
@@ -1037,6 +1037,20 @@ static const struct i2c_algorithm omap_i2c_algo = {
 };
 
 #ifdef CONFIG_OF
+static struct omap_i2c_bus_platform_data omap2420_pdata = {
+       .rev = OMAP_I2C_IP_VERSION_1,
+       .flags = OMAP_I2C_FLAG_NO_FIFO |
+                       OMAP_I2C_FLAG_SIMPLE_CLOCK |
+                       OMAP_I2C_FLAG_16BIT_DATA_REG |
+                       OMAP_I2C_FLAG_BUS_SHIFT_2,
+};
+
+static struct omap_i2c_bus_platform_data omap2430_pdata = {
+       .rev = OMAP_I2C_IP_VERSION_1,
+       .flags = OMAP_I2C_FLAG_BUS_SHIFT_2 |
+                       OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
+};
+
 static struct omap_i2c_bus_platform_data omap3_pdata = {
        .rev = OMAP_I2C_IP_VERSION_1,
        .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
@@ -1055,6 +1069,14 @@ static const struct of_device_id omap_i2c_of_match[] = {
                .compatible = "ti,omap3-i2c",
                .data = &omap3_pdata,
        },
+       {
+               .compatible = "ti,omap2430-i2c",
+               .data = &omap2430_pdata,
+       },
+       {
+               .compatible = "ti,omap2420-i2c",
+               .data = &omap2420_pdata,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
@@ -1140,9 +1162,9 @@ omap_i2c_probe(struct platform_device *pdev)
         * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2.
         * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset.
         * Also since the omap_i2c_read_reg uses reg_map_ip_* a
-        * raw_readw is done.
+        * readw_relaxed is done.
         */
-       rev = __raw_readw(dev->base + 0x04);
+       rev = readw_relaxed(dev->base + 0x04);
 
        dev->scheme = OMAP_I2C_SCHEME(rev);
        switch (dev->scheme) {
index 797e3117bef7437ef2d6f734431a16e43acaed34..2d0847b6be626d00ee642daab806aeb259f6eb0b 100644 (file)
@@ -139,6 +139,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
        priv->adap.algo = &priv->algo;
        priv->adap.algo_data = priv;
        priv->adap.dev.parent = &parent->dev;
+       priv->adap.retries = parent->retries;
+       priv->adap.timeout = parent->timeout;
 
        /* Sanity check on class */
        if (i2c_mux_parent_classes(parent) & class)
index cbd4e9abc47e8f47f512915d224f916166921110..f80b700f821ca4ece2a17ef1db08c099738f74fe 100644 (file)
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .enter = NULL }
 };
-static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state avn_cstates[] __initdata = {
        {
                .name = "C1-AVN",
                .desc = "MWAIT 0x00",
@@ -340,7 +340,7 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
        {
                .name = "C6-AVN",
                .desc = "MWAIT 0x51",
-               .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 15,
                .target_residency = 45,
                .enter = &intel_idle },
@@ -377,6 +377,9 @@ static int intel_idle(struct cpuidle_device *dev,
 
        if (!current_set_polling_and_test()) {
 
+               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
+                       clflush((void *)&current_thread_info()->flags);
+
                __monitor((void *)&current_thread_info()->flags, 0, 0);
                smp_mb();
                if (!need_resched())
index dcda17395c4e68f31f3382cd0c393a5845b025c5..1cae4e920c9ba980a45e3b17249b16ffa998f9e6 100644 (file)
@@ -350,7 +350,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
 error_iio_unreg:
        iio_device_unregister(indio_dev);
 error_remove_trigger:
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&accel_state->common_attributes);
 error_unreg_buffer_funcs:
        iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
@@ -363,10 +363,11 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct accel_3d_state *accel_state = iio_priv(indio_dev);
 
        sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D);
        iio_device_unregister(indio_dev);
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&accel_state->common_attributes);
        iio_triggered_buffer_cleanup(indio_dev);
        kfree(indio_dev->channels);
 
index d72118d1189c8648161496919ab17f7ad514df95..98ba761cbb9ce6943913c03b0a65d861e6956661 100644 (file)
@@ -112,9 +112,10 @@ static int kxsd9_read(struct iio_dev *indio_dev, u8 address)
        mutex_lock(&st->buf_lock);
        st->tx[0] = KXSD9_READ(address);
        ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
-       if (ret)
-               return ret;
-       return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
+       if (!ret)
+               ret = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
+       mutex_unlock(&st->buf_lock);
+       return ret;
 }
 
 static IIO_CONST_ATTR(accel_scale_available,
index acb7f90359a3460371c9d1e8a00cd15c3a77a26d..749a6cadab8b3708d9a9e2d50f9d086f6f17e80e 100644 (file)
@@ -200,7 +200,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 1,
                        .scan_index = 1,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[1] = {
                        .type = IIO_VOLTAGE,
@@ -210,7 +216,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 0,
                        .scan_index = 0,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
                .int_vref_mv = 2500,
index 17df74908db120a6e33e3f43a51fc4e67784da59..5b1aa027c034b09c1569047231716ea66f75f919 100644 (file)
@@ -1047,6 +1047,7 @@ static int at91_adc_probe(struct platform_device *pdev)
        } else {
                if (!st->caps->has_tsmr) {
                        dev_err(&pdev->dev, "We don't support non-TSMR adc\n");
+                       ret = -ENODEV;
                        goto error_disable_adc_clk;
                }
 
index 12948325431c98a1a01effc90d1bec0f6a564b50..c8c1baaec6c1bf7b590e144c79a6b73efbf13af2 100644 (file)
@@ -88,10 +88,10 @@ static const int mcp3422_sample_rates[4] = {
 
 /* sample rates to sign extension table */
 static const int mcp3422_sign_extend[4] = {
-       [MCP3422_SRATE_240] = 12,
-       [MCP3422_SRATE_60] = 14,
-       [MCP3422_SRATE_15] = 16,
-       [MCP3422_SRATE_3] = 18 };
+       [MCP3422_SRATE_240] = 11,
+       [MCP3422_SRATE_60] = 13,
+       [MCP3422_SRATE_15] = 15,
+       [MCP3422_SRATE_3] = 17 };
 
 /* Client data (each client gets its own) */
 struct mcp3422 {
index 728411ec764203c371270c390ac77176d788ffd9..d4d748214e4b364dc716889d2b66363353c2ee56 100644 (file)
@@ -229,12 +229,15 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
        unsigned long flags,
        const struct iio_buffer_setup_ops *setup_ops)
 {
+       struct iio_buffer *buffer;
        int ret;
 
-       indio_dev->buffer = iio_kfifo_allocate(indio_dev);
-       if (!indio_dev->buffer)
+       buffer = iio_kfifo_allocate(indio_dev);
+       if (!buffer)
                return -ENOMEM;
 
+       iio_device_attach_buffer(indio_dev, buffer);
+
        ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh,
                                flags, indio_dev->name, indio_dev);
        if (ret)
index 1178121b55b032989257e3167c6724815458ec26..39188b72cd3b2865a763e5a0b3c4715ad3d93570 100644 (file)
@@ -25,13 +25,4 @@ config HID_SENSOR_IIO_TRIGGER
          If this driver is compiled as a module, it will be named
          hid-sensor-trigger.
 
-config HID_SENSOR_ENUM_BASE_QUIRKS
-       bool "ENUM base quirks for HID Sensor IIO drivers"
-       depends on HID_SENSOR_IIO_COMMON
-       help
-         Say yes here to build support for sensor hub FW using
-         enumeration, which is using 1 as base instead of 0.
-         Since logical minimum is still set 0 instead of 1,
-         there is no easy way to differentiate.
-
 endmenu
index b6e77e0fc420133af7a324de6a0531bfb045f33d..7dcf83998e6f7fc58de8c5c3a894207abcd06bab 100644 (file)
@@ -33,33 +33,42 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 {
        struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
        int state_val;
+       int report_val;
 
        if (state) {
                if (sensor_hub_device_open(st->hsdev))
                        return -EIO;
-       } else
+               state_val =
+               HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
+               report_val =
+               HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
+
+       } else {
                sensor_hub_device_close(st->hsdev);
+               state_val =
+               HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
+               report_val =
+               HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
+       }
 
-       state_val = state ? 1 : 0;
-       if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
-               ++state_val;
        st->data_ready = state;
+       state_val += st->power_state.logical_minimum;
+       report_val += st->report_state.logical_minimum;
        sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
                                        st->power_state.index,
                                        (s32)state_val);
 
        sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
                                        st->report_state.index,
-                                       (s32)state_val);
+                                       (s32)report_val);
 
        return 0;
 }
 
-void hid_sensor_remove_trigger(struct iio_dev *indio_dev)
+void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
 {
-       iio_trigger_unregister(indio_dev->trig);
-       iio_trigger_free(indio_dev->trig);
-       indio_dev->trig = NULL;
+       iio_trigger_unregister(attrb->trigger);
+       iio_trigger_free(attrb->trigger);
 }
 EXPORT_SYMBOL(hid_sensor_remove_trigger);
 
@@ -90,7 +99,7 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
                dev_err(&indio_dev->dev, "Trigger Register Failed\n");
                goto error_free_trig;
        }
-       indio_dev->trig = trig;
+       indio_dev->trig = attrb->trigger = trig;
 
        return ret;
 
index 9a8731478eda4cdb95867e5dffdd10d1ec9bcbae..ca02f7811aa8c6f6a44dc8a955a064dfa1e07219 100644 (file)
@@ -21,6 +21,6 @@
 
 int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
                                struct hid_sensor_common *attrb);
-void hid_sensor_remove_trigger(struct iio_dev *indio_dev);
+void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
 
 #endif
index ea01c6bcfb56825979efc7bfc588eeb9e429e059..e54f0f4959d37abc28202ae75e044ec249cdd73c 100644 (file)
@@ -348,7 +348,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
 error_iio_unreg:
        iio_device_unregister(indio_dev);
 error_remove_trigger:
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&gyro_state->common_attributes);
 error_unreg_buffer_funcs:
        iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
@@ -361,10 +361,11 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
 
        sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
        iio_device_unregister(indio_dev);
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&gyro_state->common_attributes);
        iio_triggered_buffer_cleanup(indio_dev);
        kfree(indio_dev->channels);
 
index 3fb7757a10287b1991b4ef23676a8e4d2b315dad..368660dfe135a51c3cac05dd90d7dcb75dacb7c2 100644 (file)
@@ -651,7 +651,12 @@ static const struct iio_chan_spec adis16448_channels[] = {
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = ADIS16448_BARO_OUT,
                .scan_index = ADIS16400_SCAN_BARO,
-               .scan_type = IIO_ST('s', 16, 16, 0),
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 16,
+                       .storagebits = 16,
+                       .endianness = IIO_BE,
+               },
        },
        ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
        IIO_CHAN_SOFT_TIMESTAMP(11)
index f98c2b509254e2b8fdce8cd77db408f11b244495..a022f27c6690d56ba9c70caaa3953919b15c492e 100644 (file)
@@ -43,6 +43,7 @@ config GP2AP020A00F
        depends on I2C
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
+       select IRQ_WORK
        help
          Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip
          hooked to an I2C bus.
@@ -81,6 +82,8 @@ config SENSORS_LM3533
 config TCS3472
        tristate "TAOS TCS3472 color light-to-digital converter"
        depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
         If you say yes here you get support for the TAOS TCS3472
         family of color light-to-digital converters with IR filter.
index 21df5713001831f91f5dbd592df94837bf612186..0922e39b0ea979a8355ac5da395d527ab871d269 100644 (file)
@@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651,
                return -EINVAL;
        }
 
-       return IIO_VAL_INT_PLUS_MICRO;
+       return IIO_VAL_INT;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
index fa6ae8cf89eaa9edfdfffe379939bc7cc8a491f0..8e8b9d72285373b2a41be93c937407d51dcc637f 100644 (file)
@@ -314,7 +314,7 @@ static int hid_als_probe(struct platform_device *pdev)
 error_iio_unreg:
        iio_device_unregister(indio_dev);
 error_remove_trigger:
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&als_state->common_attributes);
 error_unreg_buffer_funcs:
        iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
@@ -327,10 +327,11 @@ static int hid_als_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct als_state *als_state = iio_priv(indio_dev);
 
        sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS);
        iio_device_unregister(indio_dev);
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&als_state->common_attributes);
        iio_triggered_buffer_cleanup(indio_dev);
        kfree(indio_dev->channels);
 
index 0cf09637b35b64f16a37c3adece1416cc453fee1..d86d226dcd67e09b585652ef983c9ccb038cdb99 100644 (file)
@@ -19,6 +19,8 @@ config AK8975
 config MAG3110
        tristate "Freescale MAG3110 3-Axis Magnetometer"
        depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          Say yes here to build support for the Freescale MAG3110 3-Axis
          magnetometer.
index 2634920562fb7263bad4ac9d8c6c75fe7a434b49..b26e1028a0a0b17ae6f0b94d936f50186b1d3f28 100644 (file)
@@ -351,7 +351,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
 error_iio_unreg:
        iio_device_unregister(indio_dev);
 error_remove_trigger:
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&magn_state->common_attributes);
 error_unreg_buffer_funcs:
        iio_triggered_buffer_cleanup(indio_dev);
 error_free_dev_mem:
@@ -364,10 +364,11 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
 {
        struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct magn_3d_state *magn_state = iio_priv(indio_dev);
 
        sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
        iio_device_unregister(indio_dev);
-       hid_sensor_remove_trigger(indio_dev);
+       hid_sensor_remove_trigger(&magn_state->common_attributes);
        iio_triggered_buffer_cleanup(indio_dev);
        kfree(indio_dev->channels);
 
index 783c5b417356e0ecaf0d3c095f33c2b4a24fa496..becf54496967aee126fb6449b54341394645d9bd 100644 (file)
@@ -250,7 +250,12 @@ done:
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
                BIT(IIO_CHAN_INFO_SCALE), \
        .scan_index = idx, \
-       .scan_type = IIO_ST('s', 16, 16, IIO_BE), \
+       .scan_type = { \
+               .sign = 's', \
+               .realbits = 16, \
+               .storagebits = 16, \
+               .endianness = IIO_BE, \
+       }, \
 }
 
 static const struct iio_chan_spec mag3110_channels[] = {
index c47c2034ca71f9a95f3153fbc31756fc34b1fde0..0717940ec3b5080083cb53e8d8526bdf692c829a 100644 (file)
@@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id)
 static void rem_ref(struct iw_cm_id *cm_id)
 {
        struct iwcm_id_private *cm_id_priv;
+       int cb_destroy;
+
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-       if (iwcm_deref_id(cm_id_priv) &&
-           test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+
+       /*
+        * Test bit before deref in case the cm_id gets freed on another
+        * thread.
+        */
+       cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
+       if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
                BUG_ON(!list_empty(&cm_id_priv->work_list));
                free_cm_id(cm_id_priv);
        }
index bdc842e9faefe4ba477b96c479975643bfdc6366..a283274a5a09fa17b0dede8f5819ef9dfaf4458b 100644 (file)
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
        do {                                                            \
-               (udata)->inbuf  = (void __user *) (ibuf);               \
+               (udata)->inbuf  = (const void __user *) (ibuf);         \
                (udata)->outbuf = (void __user *) (obuf);               \
                (udata)->inlen  = (ilen);                               \
                (udata)->outlen = (olen);                               \
        } while (0)
 
+#define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen)                  \
+       do {                                                                    \
+               (udata)->inbuf  = (ilen) ? (const void __user *) (ibuf) : NULL; \
+               (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL;       \
+               (udata)->inlen  = (ilen);                                       \
+               (udata)->outlen = (olen);                                       \
+       } while (0)
+
 /*
  * Our lifetime rules for these structs are the following:
  *
index 65f6e7dc380c382cc0335e495fb2f583a4eef7b7..f1cc83855af65dd334a21d7c82a94f252413e42a 100644 (file)
@@ -2593,6 +2593,9 @@ out_put:
 static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
                                union ib_flow_spec *ib_spec)
 {
+       if (kern_spec->reserved)
+               return -EINVAL;
+
        ib_spec->type = kern_spec->type;
 
        switch (ib_spec->type) {
@@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        void *ib_spec;
        int i;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        if (ucore->outlen < sizeof(resp))
                return -ENOSPC;
 
@@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
            (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
                return -EINVAL;
 
+       if (cmd.flow_attr.reserved[0] ||
+           cmd.flow_attr.reserved[1])
+               return -EINVAL;
+
        if (cmd.flow_attr.num_of_specs) {
                kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
                                         GFP_KERNEL);
@@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
                pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
                        i, cmd.flow_attr.size);
+               err = -EINVAL;
                goto err_free;
        }
        flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
@@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
        struct ib_uobject               *uobj;
        int                             ret;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
        if (ret)
                return ret;
 
+       if (cmd.comp_mask)
+               return -EINVAL;
+
        uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
                              file->ucontext);
        if (!uobj)
index 34386943ebcff4cf18849082add568f5fc73bc5a..08219fb3338b0652f350da1af864b4cfb355ff3c 100644 (file)
@@ -668,25 +668,30 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
                        return -EINVAL;
 
+               if (ex_hdr.cmd_hdr_reserved)
+                       return -EINVAL;
+
                if (ex_hdr.response) {
                        if (!hdr.out_words && !ex_hdr.provider_out_words)
                                return -EINVAL;
+
+                       if (!access_ok(VERIFY_WRITE,
+                                      (void __user *) (unsigned long) ex_hdr.response,
+                                      (hdr.out_words + ex_hdr.provider_out_words) * 8))
+                               return -EFAULT;
                } else {
                        if (hdr.out_words || ex_hdr.provider_out_words)
                                return -EINVAL;
                }
 
-               INIT_UDATA(&ucore,
-                          (hdr.in_words) ? buf : 0,
-                          (unsigned long)ex_hdr.response,
-                          hdr.in_words * 8,
-                          hdr.out_words * 8);
-
-               INIT_UDATA(&uhw,
-                          (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
-                          (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
-                          ex_hdr.provider_in_words * 8,
-                          ex_hdr.provider_out_words * 8);
+               INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
+                                      hdr.in_words * 8, hdr.out_words * 8);
+
+               INIT_UDATA_BUF_OR_NULL(&uhw,
+                                      buf + ucore.inlen,
+                                      (unsigned long) ex_hdr.response + ucore.outlen,
+                                      ex_hdr.provider_in_words * 8,
+                                      ex_hdr.provider_out_words * 8);
 
                err = uverbs_ex_cmd_table[command](file,
                                                   &ucore,
index 4cb8eb24497cfa61821b4863c4026ff5a061405a..84e45006451cd3983cd1b28bfb22d2c0a9c02ef7 100644 (file)
@@ -173,7 +173,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
        return ret;
 }
 
-int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
+static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
 {
        u32 remain = len;
        u32 dmalen;
index 6be57c38638d28dd0a39464bffe391c4a093f478..9804fca6bf0605a074c13f470e4bf6cf8413bd66 100644 (file)
@@ -207,7 +207,9 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn)
        isert_conn->conn_rx_descs = NULL;
 }
 
+static void isert_cq_tx_work(struct work_struct *);
 static void isert_cq_tx_callback(struct ib_cq *, void *);
+static void isert_cq_rx_work(struct work_struct *);
 static void isert_cq_rx_callback(struct ib_cq *, void *);
 
 static int
@@ -259,26 +261,36 @@ isert_create_device_ib_res(struct isert_device *device)
                cq_desc[i].device = device;
                cq_desc[i].cq_index = i;
 
+               INIT_WORK(&cq_desc[i].cq_rx_work, isert_cq_rx_work);
                device->dev_rx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_rx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_RX_CQ_LEN, i);
-               if (IS_ERR(device->dev_rx_cq[i]))
+               if (IS_ERR(device->dev_rx_cq[i])) {
+                       ret = PTR_ERR(device->dev_rx_cq[i]);
+                       device->dev_rx_cq[i] = NULL;
                        goto out_cq;
+               }
 
+               INIT_WORK(&cq_desc[i].cq_tx_work, isert_cq_tx_work);
                device->dev_tx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_tx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_TX_CQ_LEN, i);
-               if (IS_ERR(device->dev_tx_cq[i]))
+               if (IS_ERR(device->dev_tx_cq[i])) {
+                       ret = PTR_ERR(device->dev_tx_cq[i]);
+                       device->dev_tx_cq[i] = NULL;
                        goto out_cq;
+               }
 
-               if (ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
 
-               if (ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
        }
 
@@ -1724,7 +1736,6 @@ isert_cq_tx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_tx_work, isert_cq_tx_work);
        queue_work(isert_comp_wq, &cq_desc->cq_tx_work);
 }
 
@@ -1768,7 +1779,6 @@ isert_cq_rx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_rx_work, isert_cq_rx_work);
        queue_work(isert_rx_wq, &cq_desc->cq_rx_work);
 }
 
index dbd2047f1641f0751340eade88c408f31201f318..3ed23513d881301fa06c1bde1ed14f56546d0147 100644 (file)
@@ -536,7 +536,8 @@ static int adp5588_probe(struct i2c_client *client,
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        if (kpad->gpimapsize)
index 67d12b3427c9ee9bcb5da69d276a6bc814467586..60dafd4fa692e1d41457c471d5a79ef0bcdf21f0 100644 (file)
@@ -992,7 +992,8 @@ static int adp5589_probe(struct i2c_client *client,
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        if (kpad->gpimapsize)
index fc88fb48d70d6740ef96f8fdbe9afc32760218c5..09b91d09308780ceebc25d9f860f88eb56b68183 100644 (file)
@@ -289,7 +289,8 @@ static int bfin_kpad_probe(struct platform_device *pdev)
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (bf54x_kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(bf54x_kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        error = input_register_device(input);
index 0735de3a6468f85cad2c08a1dc601d5a67a67a23..1cb1da2944191cdefbec3c8b910ce16ea994a758 100644 (file)
 
 /* ORIENT ADXL346 only */
 #define ADXL346_2D_VALID               (1 << 6)
-#define ADXL346_2D_ORIENT(x)           (((x) & 0x3) >> 4)
+#define ADXL346_2D_ORIENT(x)           (((x) & 0x30) >> 4)
 #define ADXL346_3D_VALID               (1 << 3)
 #define ADXL346_3D_ORIENT(x)           ((x) & 0x7)
 #define ADXL346_2D_PORTRAIT_POS                0       /* +X */
index 86b822806e95b504f9f4b23303365cff0d6b6a1d..45e0e3e55de28dfdbdfb347ebdba74ca2e698544 100644 (file)
@@ -180,7 +180,10 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
        if (WARN_ON(down_interruptible(&i8042tregs)))
                return -1;
 
-       if (hp_sdc_enqueue_transaction(&t)) return -1;
+       if (hp_sdc_enqueue_transaction(&t)) {
+               up(&i8042tregs);
+               return -1;
+       }
        
        /* Sleep until results come back. */
        if (WARN_ON(down_interruptible(&i8042tregs)))
index e37392976fdd5f3f252ca5f2af2a2477fc8265b7..0deca5a3c87fe1adacdce8259a052738486749cb 100644 (file)
@@ -113,9 +113,12 @@ static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_i
        idev->keycodemax = ARRAY_SIZE(lp->btncode);
 
        for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) {
-               lp->btncode[i] = pcf8574_kp_btncode[i];
-               __set_bit(lp->btncode[i] & KEY_MAX, idev->keybit);
+               if (lp->btncode[i] <= KEY_MAX) {
+                       lp->btncode[i] = pcf8574_kp_btncode[i];
+                       __set_bit(lp->btncode[i], idev->keybit);
+               }
        }
+       __clear_bit(KEY_RESERVED, idev->keybit);
 
        sprintf(lp->name, DRV_NAME);
        sprintf(lp->phys, "kp_data/input0");
index ca7a26f1dce81c37c6cd8524f8c4698effbfd739..5cf62e315218386817972a74aafcca22dc572113 100644 (file)
@@ -70,6 +70,25 @@ static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
        { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
 };
 
+static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
+       { PSMOUSE_CMD_ENABLE,           0x00 }, /* 0 */
+       { PSMOUSE_CMD_SETRATE,          0x0a }, /* 1 */
+       { PSMOUSE_CMD_SETRATE,          0x14 }, /* 2 */
+       { PSMOUSE_CMD_SETRATE,          0x28 }, /* 3 */
+       { PSMOUSE_CMD_SETRATE,          0x3c }, /* 4 */
+       { PSMOUSE_CMD_SETRATE,          0x50 }, /* 5 */
+       { PSMOUSE_CMD_SETRATE,          0x64 }, /* 6 */
+       { PSMOUSE_CMD_SETRATE,          0xc8 }, /* 7 */
+       { PSMOUSE_CMD_GETID,            0x00 }, /* 8 */
+       { PSMOUSE_CMD_GETINFO,          0x00 }, /* 9 */
+       { PSMOUSE_CMD_SETRES,           0x00 }, /* a */
+       { PSMOUSE_CMD_SETRES,           0x01 }, /* b */
+       { PSMOUSE_CMD_SETRES,           0x02 }, /* c */
+       { PSMOUSE_CMD_SETRES,           0x03 }, /* d */
+       { PSMOUSE_CMD_SETSCALE21,       0x00 }, /* e */
+       { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
+};
+
 
 #define ALPS_DUALPOINT         0x02    /* touchpad has trackstick */
 #define ALPS_PASS              0x04    /* device has a pass-through port */
@@ -103,6 +122,7 @@ static const struct alps_model_info alps_model_data[] = {
        /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
        { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf,
                ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
+       { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT },              /* Dell XT2 */
        { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS },           /* Dell Vostro 1400 */
        { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff,
                ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },                            /* Toshiba Tecra A11-11L */
@@ -645,6 +665,76 @@ static void alps_process_packet_v3(struct psmouse *psmouse)
        alps_process_touchpad_packet_v3(psmouse);
 }
 
+static void alps_process_packet_v6(struct psmouse *psmouse)
+{
+       struct alps_data *priv = psmouse->private;
+       unsigned char *packet = psmouse->packet;
+       struct input_dev *dev = psmouse->dev;
+       struct input_dev *dev2 = priv->dev2;
+       int x, y, z, left, right, middle;
+
+       /*
+        * We can use Byte5 to distinguish if the packet is from Touchpad
+        * or Trackpoint.
+        * Touchpad:    0 - 0x7E
+        * Trackpoint:  0x7F
+        */
+       if (packet[5] == 0x7F) {
+               /* It should be a DualPoint when received Trackpoint packet */
+               if (!(priv->flags & ALPS_DUALPOINT))
+                       return;
+
+               /* Trackpoint packet */
+               x = packet[1] | ((packet[3] & 0x20) << 2);
+               y = packet[2] | ((packet[3] & 0x40) << 1);
+               z = packet[4];
+               left = packet[3] & 0x01;
+               right = packet[3] & 0x02;
+               middle = packet[3] & 0x04;
+
+               /* To prevent the cursor jump when finger lifted */
+               if (x == 0x7F && y == 0x7F && z == 0x7F)
+                       x = y = z = 0;
+
+               /* Divide 4 since trackpoint's speed is too fast */
+               input_report_rel(dev2, REL_X, (char)x / 4);
+               input_report_rel(dev2, REL_Y, -((char)y / 4));
+
+               input_report_key(dev2, BTN_LEFT, left);
+               input_report_key(dev2, BTN_RIGHT, right);
+               input_report_key(dev2, BTN_MIDDLE, middle);
+
+               input_sync(dev2);
+               return;
+       }
+
+       /* Touchpad packet */
+       x = packet[1] | ((packet[3] & 0x78) << 4);
+       y = packet[2] | ((packet[4] & 0x78) << 4);
+       z = packet[5];
+       left = packet[3] & 0x01;
+       right = packet[3] & 0x02;
+
+       if (z > 30)
+               input_report_key(dev, BTN_TOUCH, 1);
+       if (z < 25)
+               input_report_key(dev, BTN_TOUCH, 0);
+
+       if (z > 0) {
+               input_report_abs(dev, ABS_X, x);
+               input_report_abs(dev, ABS_Y, y);
+       }
+
+       input_report_abs(dev, ABS_PRESSURE, z);
+       input_report_key(dev, BTN_TOOL_FINGER, z > 0);
+
+       /* v6 touchpad does not have middle button */
+       input_report_key(dev, BTN_LEFT, left);
+       input_report_key(dev, BTN_RIGHT, right);
+
+       input_sync(dev);
+}
+
 static void alps_process_packet_v4(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
@@ -897,7 +987,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
        }
 
        /* Bytes 2 - pktsize should have 0 in the highest bit */
-       if (priv->proto_version != ALPS_PROTO_V5 &&
+       if ((priv->proto_version < ALPS_PROTO_V5) &&
            psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
            (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
                psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
@@ -1085,6 +1175,80 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
        return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
 }
 
+static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
+{
+       int i, nibble;
+
+       /*
+        * b0-b11 are valid bits, send sequence is inverse.
+        * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
+        */
+       for (i = 0; i <= 8; i += 4) {
+               nibble = (word >> i) & 0xf;
+               if (alps_command_mode_send_nibble(psmouse, nibble))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
+                                      u16 addr, u16 value)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+       /* 0x0A0 is the command to write the word */
+       if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
+           alps_monitor_mode_send_word(psmouse, 0x0A0) ||
+           alps_monitor_mode_send_word(psmouse, addr) ||
+           alps_monitor_mode_send_word(psmouse, value) ||
+           ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
+               return -1;
+
+       return 0;
+}
+
+static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+       if (enable) {
+               /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
+               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
+                       return -1;
+       } else {
+               /* EC to exit monitor mode */
+               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alps_absolute_mode_v6(struct psmouse *psmouse)
+{
+       u16 reg_val = 0x181;
+       int ret = -1;
+
+       /* enter monitor mode, to write the register */
+       if (alps_monitor_mode(psmouse, true))
+               return -1;
+
+       ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
+
+       if (alps_monitor_mode(psmouse, false))
+               ret = -1;
+
+       return ret;
+}
+
 static int alps_get_status(struct psmouse *psmouse, char *param)
 {
        /* Get status: 0xF5 0xF5 0xF5 0xE9 */
@@ -1189,6 +1353,32 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse)
        return 0;
 }
 
+static int alps_hw_init_v6(struct psmouse *psmouse)
+{
+       unsigned char param[2] = {0xC8, 0x14};
+
+       /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
+       if (alps_passthrough_mode_v2(psmouse, true))
+               return -1;
+
+       if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+           ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+               return -1;
+
+       if (alps_passthrough_mode_v2(psmouse, false))
+               return -1;
+
+       if (alps_absolute_mode_v6(psmouse)) {
+               psmouse_err(psmouse, "Failed to enable absolute mode\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 /*
  * Enable or disable passthrough mode to the trackstick.
  */
@@ -1553,6 +1743,8 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->hw_init = alps_hw_init_v1_v2;
                priv->process_packet = alps_process_packet_v1_v2;
                priv->set_abs_params = alps_set_abs_params_st;
+               priv->x_max = 1023;
+               priv->y_max = 767;
                break;
        case ALPS_PROTO_V3:
                priv->hw_init = alps_hw_init_v3;
@@ -1584,6 +1776,14 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->x_bits = 23;
                priv->y_bits = 12;
                break;
+       case ALPS_PROTO_V6:
+               priv->hw_init = alps_hw_init_v6;
+               priv->process_packet = alps_process_packet_v6;
+               priv->set_abs_params = alps_set_abs_params_st;
+               priv->nibble_commands = alps_v6_nibble_commands;
+               priv->x_max = 2047;
+               priv->y_max = 1535;
+               break;
        }
 }
 
@@ -1705,8 +1905,8 @@ static void alps_disconnect(struct psmouse *psmouse)
 static void alps_set_abs_params_st(struct alps_data *priv,
                                   struct input_dev *dev1)
 {
-       input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
-       input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
+       input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
+       input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
 }
 
 static void alps_set_abs_params_mt(struct alps_data *priv,
index eee59853b9ce0c21bc755c206430911e15789964..704f0f9243076190213b1c1876ef833348e61c99 100644 (file)
@@ -17,6 +17,7 @@
 #define ALPS_PROTO_V3  3
 #define ALPS_PROTO_V4  4
 #define ALPS_PROTO_V5  5
+#define ALPS_PROTO_V6  6
 
 /**
  * struct alps_model_info - touchpad ID table
index 8551dcaf24dbadc854a7f6a6664128598c99a067..597e9b8fc18db99c5bf1f33b3a274c632b2ba24b 100644 (file)
@@ -1313,6 +1313,7 @@ static int elantech_set_properties(struct elantech_data *etd)
                        break;
                case 6:
                case 7:
+               case 8:
                        etd->hw_version = 4;
                        break;
                default:
index 98707fb2cb5d672b6b5bcdc8b787bb37c90c9989..8f4c4ab04bc2d8c61d5fda2a65696806e61ad6f2 100644 (file)
@@ -455,16 +455,26 @@ static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(proto);
 static DEVICE_ATTR_RO(id);
 static DEVICE_ATTR_RO(extra);
-static DEVICE_ATTR_RO(modalias);
-static DEVICE_ATTR_WO(drvctl);
-static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
-static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
 
 static struct attribute *serio_device_id_attrs[] = {
        &dev_attr_type.attr,
        &dev_attr_proto.attr,
        &dev_attr_id.attr,
        &dev_attr_extra.attr,
+       NULL
+};
+
+static struct attribute_group serio_id_attr_group = {
+       .name   = "id",
+       .attrs  = serio_device_id_attrs,
+};
+
+static DEVICE_ATTR_RO(modalias);
+static DEVICE_ATTR_WO(drvctl);
+static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
+static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
+
+static struct attribute *serio_device_attrs[] = {
        &dev_attr_modalias.attr,
        &dev_attr_description.attr,
        &dev_attr_drvctl.attr,
@@ -472,13 +482,13 @@ static struct attribute *serio_device_id_attrs[] = {
        NULL
 };
 
-static struct attribute_group serio_id_attr_group = {
-       .name   = "id",
-       .attrs  = serio_device_id_attrs,
+static struct attribute_group serio_device_attr_group = {
+       .attrs  = serio_device_attrs,
 };
 
 static const struct attribute_group *serio_device_attr_groups[] = {
        &serio_id_attr_group,
+       &serio_device_attr_group,
        NULL
 };
 
index 00d1e547b21119bb72e723633a08023f3eb2052f..961d58d3264769fb3daec51182effd8742bd1b5e 100644 (file)
@@ -906,6 +906,17 @@ config TOUCHSCREEN_STMPE
          To compile this driver as a module, choose M here: the
          module will be called stmpe-ts.
 
+config TOUCHSCREEN_SUR40
+       tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
+       depends on USB
+       select INPUT_POLLDEV
+       help
+         Say Y here if you want support for the Samsung SUR40 touchscreen
+         (also known as Microsoft Surface 2.0 or Microsoft PixelSense).
+
+         To compile this driver as a module, choose M here: the
+         module will be called sur40.
+
 config TOUCHSCREEN_TPS6507X
        tristate "TPS6507x based touchscreens"
        depends on I2C
index 7587883b8d387b30cbcf63be49f2c8cc55e58974..62801f213346a8e358af358e409e0768130744bc 100644 (file)
@@ -54,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR)      += pixcir_i2c_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)      += s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)       += st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)                += stmpe-ts.o
+obj-$(CONFIG_TOUCHSCREEN_SUR40)                += sur40.o
 obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC)        += ti_am335x_tsc.o
 obj-$(CONFIG_TOUCHSCREEN_TNETV107X)    += tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)   += touchit213.o
index 268a35e55d7f160fd632a673276f67ee6672665f..279c0e42b8a7515a161550621ac82dd2ccd7d0f0 100644 (file)
@@ -391,7 +391,7 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int atmel_wm97xx_suspend(struct *dev)
+static int atmel_wm97xx_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
index 42d830efa316ec9c44f53306123e0ffb2a2d04b5..a035a390f8e29f4caa36e4949fd54d469e9cdc24 100644 (file)
@@ -1246,8 +1246,7 @@ static void cyttsp4_watchdog_timer(unsigned long handle)
 
        dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__);
 
-       if (!work_pending(&cd->watchdog_work))
-               schedule_work(&cd->watchdog_work);
+       schedule_work(&cd->watchdog_work);
 
        return;
 }
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
new file mode 100644 (file)
index 0000000..f1cb051
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Surface2.0/SUR40/PixelSense input driver
+ *
+ * Copyright (c) 2013 by Florian 'floe' Echtler <floe@butterbrot.org>
+ *
+ * Derived from the USB Skeleton driver 1.1,
+ * Copyright (c) 2003 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * and from the Apple USB BCM5974 multitouch driver,
+ * Copyright (c) 2008 Henrik Rydberg (rydberg@euromail.se)
+ *
+ * and from the generic hid-multitouch driver,
+ * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
+ *
+ * This program is 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/errno.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/printk.h>
+#include <linux/input-polldev.h>
+#include <linux/input/mt.h>
+#include <linux/usb/input.h>
+
+/* read 512 bytes from endpoint 0x86 -> get header + blobs */
+struct sur40_header {
+
+       __le16 type;       /* always 0x0001 */
+       __le16 count;      /* count of blobs (if 0: continue prev. packet) */
+
+       __le32 packet_id;  /* unique ID for all packets in one frame */
+
+       __le32 timestamp;  /* milliseconds (inc. by 16 or 17 each frame) */
+       __le32 unknown;    /* "epoch?" always 02/03 00 00 00 */
+
+} __packed;
+
+struct sur40_blob {
+
+       __le16 blob_id;
+
+       u8 action;         /* 0x02 = enter/exit, 0x03 = update (?) */
+       u8 unknown;        /* always 0x01 or 0x02 (no idea what this is?) */
+
+       __le16 bb_pos_x;   /* upper left corner of bounding box */
+       __le16 bb_pos_y;
+
+       __le16 bb_size_x;  /* size of bounding box */
+       __le16 bb_size_y;
+
+       __le16 pos_x;      /* finger tip position */
+       __le16 pos_y;
+
+       __le16 ctr_x;      /* centroid position */
+       __le16 ctr_y;
+
+       __le16 axis_x;     /* somehow related to major/minor axis, mostly: */
+       __le16 axis_y;     /* axis_x == bb_size_y && axis_y == bb_size_x */
+
+       __le32 angle;      /* orientation in radians relative to x axis -
+                             actually an IEEE754 float, don't use in kernel */
+
+       __le32 area;       /* size in pixels/pressure (?) */
+
+       u8 padding[32];
+
+} __packed;
+
+/* combined header/blob data */
+struct sur40_data {
+       struct sur40_header header;
+       struct sur40_blob   blobs[];
+} __packed;
+
+
+/* version information */
+#define DRIVER_SHORT   "sur40"
+#define DRIVER_AUTHOR  "Florian 'floe' Echtler <floe@butterbrot.org>"
+#define DRIVER_DESC    "Surface2.0/SUR40/PixelSense input driver"
+
+/* vendor and device IDs */
+#define ID_MICROSOFT 0x045e
+#define ID_SUR40     0x0775
+
+/* sensor resolution */
+#define SENSOR_RES_X 1920
+#define SENSOR_RES_Y 1080
+
+/* touch data endpoint */
+#define TOUCH_ENDPOINT 0x86
+
+/* polling interval (ms) */
+#define POLL_INTERVAL 10
+
+/* maximum number of contacts FIXME: this is a guess? */
+#define MAX_CONTACTS 64
+
+/* control commands */
+#define SUR40_GET_VERSION 0xb0 /* 12 bytes string    */
+#define SUR40_UNKNOWN1    0xb3 /*  5 bytes           */
+#define SUR40_UNKNOWN2    0xc1 /* 24 bytes           */
+
+#define SUR40_GET_STATE   0xc5 /*  4 bytes state (?) */
+#define SUR40_GET_SENSORS 0xb1 /*  8 bytes sensors   */
+
+/*
+ * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
+ * here by mistake which is very likely to have corrupted the firmware EEPROM
+ * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
+ * Should you ever run into a similar problem, the background story to this
+ * incident and instructions on how to fix the corrupted EEPROM are available
+ * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
+*/
+
+struct sur40_state {
+
+       struct usb_device *usbdev;
+       struct device *dev;
+       struct input_polled_dev *input;
+
+       struct sur40_data *bulk_in_buffer;
+       size_t bulk_in_size;
+       u8 bulk_in_epaddr;
+
+       char phys[64];
+};
+
+static int sur40_command(struct sur40_state *dev,
+                        u8 command, u16 index, void *buffer, u16 size)
+{
+       return usb_control_msg(dev->usbdev, usb_rcvctrlpipe(dev->usbdev, 0),
+                              command,
+                              USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                              0x00, index, buffer, size, 1000);
+}
+
+/* Initialization routine, called from sur40_open */
+static int sur40_init(struct sur40_state *dev)
+{
+       int result;
+       u8 buffer[24];
+
+       /* stupidly replay the original MS driver init sequence */
+       result = sur40_command(dev, SUR40_GET_VERSION, 0x00, buffer, 12);
+       if (result < 0)
+               return result;
+
+       result = sur40_command(dev, SUR40_GET_VERSION, 0x01, buffer, 12);
+       if (result < 0)
+               return result;
+
+       result = sur40_command(dev, SUR40_GET_VERSION, 0x02, buffer, 12);
+       if (result < 0)
+               return result;
+
+       result = sur40_command(dev, SUR40_UNKNOWN2,    0x00, buffer, 24);
+       if (result < 0)
+               return result;
+
+       result = sur40_command(dev, SUR40_UNKNOWN1,    0x00, buffer,  5);
+       if (result < 0)
+               return result;
+
+       result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12);
+
+       /*
+        * Discard the result buffer - no known data inside except
+        * some version strings, maybe extract these sometime...
+        */
+
+       return result;
+}
+
+/*
+ * Callback routines from input_polled_dev
+ */
+
+/* Enable the device, polling will now start. */
+static void sur40_open(struct input_polled_dev *polldev)
+{
+       struct sur40_state *sur40 = polldev->private;
+
+       dev_dbg(sur40->dev, "open\n");
+       sur40_init(sur40);
+}
+
+/* Disable device, polling has stopped. */
+static void sur40_close(struct input_polled_dev *polldev)
+{
+       struct sur40_state *sur40 = polldev->private;
+
+       dev_dbg(sur40->dev, "close\n");
+       /*
+        * There is no known way to stop the device, so we simply
+        * stop polling.
+        */
+}
+
+/*
+ * This function is called when a whole contact has been processed,
+ * so that it can assign it to a slot and store the data there.
+ */
+static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
+{
+       int wide, major, minor;
+
+       int bb_size_x = le16_to_cpu(blob->bb_size_x);
+       int bb_size_y = le16_to_cpu(blob->bb_size_y);
+
+       int pos_x = le16_to_cpu(blob->pos_x);
+       int pos_y = le16_to_cpu(blob->pos_y);
+
+       int ctr_x = le16_to_cpu(blob->ctr_x);
+       int ctr_y = le16_to_cpu(blob->ctr_y);
+
+       int slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
+       if (slotnum < 0 || slotnum >= MAX_CONTACTS)
+               return;
+
+       input_mt_slot(input, slotnum);
+       input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
+       wide = (bb_size_x > bb_size_y);
+       major = max(bb_size_x, bb_size_y);
+       minor = min(bb_size_x, bb_size_y);
+
+       input_report_abs(input, ABS_MT_POSITION_X, pos_x);
+       input_report_abs(input, ABS_MT_POSITION_Y, pos_y);
+       input_report_abs(input, ABS_MT_TOOL_X, ctr_x);
+       input_report_abs(input, ABS_MT_TOOL_Y, ctr_y);
+
+       /* TODO: use a better orientation measure */
+       input_report_abs(input, ABS_MT_ORIENTATION, wide);
+       input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
+       input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
+}
+
+/* core function: poll for new input data */
+static void sur40_poll(struct input_polled_dev *polldev)
+{
+
+       struct sur40_state *sur40 = polldev->private;
+       struct input_dev *input = polldev->input;
+       int result, bulk_read, need_blobs, packet_blobs, i;
+       u32 uninitialized_var(packet_id);
+
+       struct sur40_header *header = &sur40->bulk_in_buffer->header;
+       struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0];
+
+       dev_dbg(sur40->dev, "poll\n");
+
+       need_blobs = -1;
+
+       do {
+
+               /* perform a blocking bulk read to get data from the device */
+               result = usb_bulk_msg(sur40->usbdev,
+                       usb_rcvbulkpipe(sur40->usbdev, sur40->bulk_in_epaddr),
+                       sur40->bulk_in_buffer, sur40->bulk_in_size,
+                       &bulk_read, 1000);
+
+               dev_dbg(sur40->dev, "received %d bytes\n", bulk_read);
+
+               if (result < 0) {
+                       dev_err(sur40->dev, "error in usb_bulk_read\n");
+                       return;
+               }
+
+               result = bulk_read - sizeof(struct sur40_header);
+
+               if (result % sizeof(struct sur40_blob) != 0) {
+                       dev_err(sur40->dev, "transfer size mismatch\n");
+                       return;
+               }
+
+               /* first packet? */
+               if (need_blobs == -1) {
+                       need_blobs = le16_to_cpu(header->count);
+                       dev_dbg(sur40->dev, "need %d blobs\n", need_blobs);
+                       packet_id = le32_to_cpu(header->packet_id);
+               }
+
+               /*
+                * Sanity check. when video data is also being retrieved, the
+                * packet ID will usually increase in the middle of a series
+                * instead of at the end.
+                */
+               if (packet_id != header->packet_id)
+                       dev_warn(sur40->dev, "packet ID mismatch\n");
+
+               packet_blobs = result / sizeof(struct sur40_blob);
+               dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs);
+
+               /* packets always contain at least 4 blobs, even if empty */
+               if (packet_blobs > need_blobs)
+                       packet_blobs = need_blobs;
+
+               for (i = 0; i < packet_blobs; i++) {
+                       need_blobs--;
+                       dev_dbg(sur40->dev, "processing blob\n");
+                       sur40_report_blob(&(inblob[i]), input);
+               }
+
+       } while (need_blobs > 0);
+
+       input_mt_sync_frame(input);
+       input_sync(input);
+}
+
+/* Initialize input device parameters. */
+static void sur40_input_setup(struct input_dev *input_dev)
+{
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(EV_ABS, input_dev->evbit);
+
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                            0, SENSOR_RES_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                            0, SENSOR_RES_Y, 0, 0);
+
+       input_set_abs_params(input_dev, ABS_MT_TOOL_X,
+                            0, SENSOR_RES_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOOL_Y,
+                            0, SENSOR_RES_Y, 0, 0);
+
+       /* max value unknown, but major/minor axis
+        * can never be larger than screen */
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+                            0, SENSOR_RES_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
+                            0, SENSOR_RES_Y, 0, 0);
+
+       input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+
+       input_mt_init_slots(input_dev, MAX_CONTACTS,
+                           INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+}
+
+/* Check candidate USB interface. */
+static int sur40_probe(struct usb_interface *interface,
+                      const struct usb_device_id *id)
+{
+       struct usb_device *usbdev = interface_to_usbdev(interface);
+       struct sur40_state *sur40;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct input_polled_dev *poll_dev;
+       int error;
+
+       /* Check if we really have the right interface. */
+       iface_desc = &interface->altsetting[0];
+       if (iface_desc->desc.bInterfaceClass != 0xFF)
+               return -ENODEV;
+
+       /* Use endpoint #4 (0x86). */
+       endpoint = &iface_desc->endpoint[4].desc;
+       if (endpoint->bEndpointAddress != TOUCH_ENDPOINT)
+               return -ENODEV;
+
+       /* Allocate memory for our device state and initialize it. */
+       sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL);
+       if (!sur40)
+               return -ENOMEM;
+
+       poll_dev = input_allocate_polled_device();
+       if (!poll_dev) {
+               error = -ENOMEM;
+               goto err_free_dev;
+       }
+
+       /* Set up polled input device control structure */
+       poll_dev->private = sur40;
+       poll_dev->poll_interval = POLL_INTERVAL;
+       poll_dev->open = sur40_open;
+       poll_dev->poll = sur40_poll;
+       poll_dev->close = sur40_close;
+
+       /* Set up regular input device structure */
+       sur40_input_setup(poll_dev->input);
+
+       poll_dev->input->name = "Samsung SUR40";
+       usb_to_input_id(usbdev, &poll_dev->input->id);
+       usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
+       strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
+       poll_dev->input->phys = sur40->phys;
+       poll_dev->input->dev.parent = &interface->dev;
+
+       sur40->usbdev = usbdev;
+       sur40->dev = &interface->dev;
+       sur40->input = poll_dev;
+
+       /* use the bulk-in endpoint tested above */
+       sur40->bulk_in_size = usb_endpoint_maxp(endpoint);
+       sur40->bulk_in_epaddr = endpoint->bEndpointAddress;
+       sur40->bulk_in_buffer = kmalloc(sur40->bulk_in_size, GFP_KERNEL);
+       if (!sur40->bulk_in_buffer) {
+               dev_err(&interface->dev, "Unable to allocate input buffer.");
+               error = -ENOMEM;
+               goto err_free_polldev;
+       }
+
+       error = input_register_polled_device(poll_dev);
+       if (error) {
+               dev_err(&interface->dev,
+                       "Unable to register polled input device.");
+               goto err_free_buffer;
+       }
+
+       /* we can register the device now, as it is ready */
+       usb_set_intfdata(interface, sur40);
+       dev_dbg(&interface->dev, "%s is now attached\n", DRIVER_DESC);
+
+       return 0;
+
+err_free_buffer:
+       kfree(sur40->bulk_in_buffer);
+err_free_polldev:
+       input_free_polled_device(sur40->input);
+err_free_dev:
+       kfree(sur40);
+
+       return error;
+}
+
+/* Unregister device & clean up. */
+static void sur40_disconnect(struct usb_interface *interface)
+{
+       struct sur40_state *sur40 = usb_get_intfdata(interface);
+
+       input_unregister_polled_device(sur40->input);
+       input_free_polled_device(sur40->input);
+       kfree(sur40->bulk_in_buffer);
+       kfree(sur40);
+
+       usb_set_intfdata(interface, NULL);
+       dev_dbg(&interface->dev, "%s is now disconnected\n", DRIVER_DESC);
+}
+
+static const struct usb_device_id sur40_table[] = {
+       { USB_DEVICE(ID_MICROSOFT, ID_SUR40) },  /* Samsung SUR40 */
+       { }                                      /* terminating null entry */
+};
+MODULE_DEVICE_TABLE(usb, sur40_table);
+
+/* USB-specific object needed to register this driver with the USB subsystem. */
+static struct usb_driver sur40_driver = {
+       .name = DRIVER_SHORT,
+       .probe = sur40_probe,
+       .disconnect = sur40_disconnect,
+       .id_table = sur40_table,
+};
+
+module_usb_driver(sur40_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index ae4b6b9036292c23387fafb1124247fc377c3f72..5f87bed054674b487e724d3588806235b5b5f738 100644 (file)
@@ -106,6 +106,7 @@ struct usbtouch_device_info {
 struct usbtouch_usb {
        unsigned char *data;
        dma_addr_t data_dma;
+       int data_size;
        unsigned char *buffer;
        int buf_len;
        struct urb *irq;
@@ -1521,7 +1522,7 @@ static int usbtouch_reset_resume(struct usb_interface *intf)
 static void usbtouch_free_buffers(struct usb_device *udev,
                                  struct usbtouch_usb *usbtouch)
 {
-       usb_free_coherent(udev, usbtouch->type->rept_size,
+       usb_free_coherent(udev, usbtouch->data_size,
                          usbtouch->data, usbtouch->data_dma);
        kfree(usbtouch->buffer);
 }
@@ -1566,7 +1567,20 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (!type->process_pkt)
                type->process_pkt = usbtouch_process_pkt;
 
-       usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
+       usbtouch->data_size = type->rept_size;
+       if (type->get_pkt_len) {
+               /*
+                * When dealing with variable-length packets we should
+                * not request more than wMaxPacketSize bytes at once
+                * as we do not know if there is more data coming or
+                * we filled exactly wMaxPacketSize bytes and there is
+                * nothing else.
+                */
+               usbtouch->data_size = min(usbtouch->data_size,
+                                         usb_endpoint_maxp(endpoint));
+       }
+
+       usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size,
                                            GFP_KERNEL, &usbtouch->data_dma);
        if (!usbtouch->data)
                goto out_free;
@@ -1626,12 +1640,12 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
                usb_fill_int_urb(usbtouch->irq, udev,
                         usb_rcvintpipe(udev, endpoint->bEndpointAddress),
-                        usbtouch->data, type->rept_size,
+                        usbtouch->data, usbtouch->data_size,
                         usbtouch_irq, usbtouch, endpoint->bInterval);
        else
                usb_fill_bulk_urb(usbtouch->irq, udev,
                         usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
-                        usbtouch->data, type->rept_size,
+                        usbtouch->data, usbtouch->data_size,
                         usbtouch_irq, usbtouch);
 
        usbtouch->irq->dev = udev;
index 1abfb5684ab7ebcb7c735e10c71625439490ca09..e46a88700b6824c735967118281c9f7feb6e41b0 100644 (file)
@@ -392,7 +392,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             root_cfg;
        phys_addr_t                     output_mask;
 
-       spinlock_t                      lock;
+       struct mutex                    lock;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -900,7 +900,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
                goto out_free_domain;
        smmu_domain->root_cfg.pgd = pgd;
 
-       spin_lock_init(&smmu_domain->lock);
+       mutex_init(&smmu_domain->lock);
        domain->priv = smmu_domain;
        return 0;
 
@@ -1137,7 +1137,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
         * Sanity check the domain. We don't currently support domains
         * that cross between different SMMU chains.
         */
-       spin_lock(&smmu_domain->lock);
+       mutex_lock(&smmu_domain->lock);
        if (!smmu_domain->leaf_smmu) {
                /* Now that we have a master, we can finalise the domain */
                ret = arm_smmu_init_domain_context(domain, dev);
@@ -1152,7 +1152,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                        dev_name(device_smmu->dev));
                goto err_unlock;
        }
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
 
        /* Looks ok, so add the device to the domain */
        master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1162,7 +1162,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        return arm_smmu_domain_add_master(smmu_domain, master);
 
 err_unlock:
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
        return ret;
 }
 
@@ -1394,7 +1394,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        if (paddr & ~output_mask)
                return -ERANGE;
 
-       spin_lock(&smmu_domain->lock);
+       mutex_lock(&smmu_domain->lock);
        pgd += pgd_index(iova);
        end = iova + size;
        do {
@@ -1410,7 +1410,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        } while (pgd++, iova != end);
 
 out_unlock:
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
 
        /* Ensure new page tables are visible to the hardware walker */
        if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
@@ -1423,9 +1423,8 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
                        phys_addr_t paddr, size_t size, int flags)
 {
        struct arm_smmu_domain *smmu_domain = domain->priv;
-       struct arm_smmu_device *smmu = smmu_domain->leaf_smmu;
 
-       if (!smmu_domain || !smmu)
+       if (!smmu_domain)
                return -ENODEV;
 
        /* Check for silent address truncation up the SMMU chain. */
@@ -1449,44 +1448,34 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
                                         dma_addr_t iova)
 {
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
+       pgd_t *pgdp, pgd;
+       pud_t pud;
+       pmd_t pmd;
+       pte_t pte;
        struct arm_smmu_domain *smmu_domain = domain->priv;
        struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-       struct arm_smmu_device *smmu = root_cfg->smmu;
 
-       spin_lock(&smmu_domain->lock);
-       pgd = root_cfg->pgd;
-       if (!pgd)
-               goto err_unlock;
+       pgdp = root_cfg->pgd;
+       if (!pgdp)
+               return 0;
 
-       pgd += pgd_index(iova);
-       if (pgd_none_or_clear_bad(pgd))
-               goto err_unlock;
+       pgd = *(pgdp + pgd_index(iova));
+       if (pgd_none(pgd))
+               return 0;
 
-       pud = pud_offset(pgd, iova);
-       if (pud_none_or_clear_bad(pud))
-               goto err_unlock;
+       pud = *pud_offset(&pgd, iova);
+       if (pud_none(pud))
+               return 0;
 
-       pmd = pmd_offset(pud, iova);
-       if (pmd_none_or_clear_bad(pmd))
-               goto err_unlock;
+       pmd = *pmd_offset(&pud, iova);
+       if (pmd_none(pmd))
+               return 0;
 
-       pte = pmd_page_vaddr(*pmd) + pte_index(iova);
+       pte = *(pmd_page_vaddr(pmd) + pte_index(iova));
        if (pte_none(pte))
-               goto err_unlock;
-
-       spin_unlock(&smmu_domain->lock);
-       return __pfn_to_phys(pte_pfn(*pte)) | (iova & ~PAGE_MASK);
+               return 0;
 
-err_unlock:
-       spin_unlock(&smmu_domain->lock);
-       dev_warn(smmu->dev,
-                "invalid (corrupt?) page tables detected for iova 0x%llx\n",
-                (unsigned long long)iova);
-       return -EINVAL;
+       return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
 }
 
 static int arm_smmu_domain_has_cap(struct iommu_domain *domain,
@@ -1863,6 +1852,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
                dev_err(dev,
                        "found only %d context interrupt(s) but %d required\n",
                        smmu->num_context_irqs, smmu->num_context_banks);
+               err = -ENODEV;
                goto out_put_parent;
        }
 
index 9031171c141b52c5e9175fdbf6eec9bd0c4224b3..341c6016812de0e17fbd4c1601708723409351c5 100644 (file)
@@ -957,12 +957,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
        if (WARN_ON(!gic->domain))
                return;
 
+       if (gic_nr == 0) {
 #ifdef CONFIG_SMP
-       set_smp_cross_call(gic_raise_softirq);
-       register_cpu_notifier(&gic_cpu_notifier);
+               set_smp_cross_call(gic_raise_softirq);
+               register_cpu_notifier(&gic_cpu_notifier);
 #endif
-
-       set_handle_irq(gic_handle_irq);
+               set_handle_irq(gic_handle_irq);
+       }
 
        gic_chip.flags |= gic_arch_extn.flags;
        gic_dist_init(gic);
index 82cec63a90112e184c96a2e21e612df977adf7b7..3ee78f02e5d7d940d531aa6ab03c8dc681c9cb3c 100644 (file)
@@ -149,8 +149,9 @@ static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
 static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
                                         int irq, int do_mask)
 {
-       int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
-       int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+       /* The PRIO register is assumed to be 32-bit with fixed 4-bit fields. */
+       int bitfield_width = 4;
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
                                      shift, bitfield_width,
@@ -159,8 +160,9 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
 
 static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
 {
+       /* The SENSE register is assumed to be 32-bit. */
        int bitfield_width = p->config.sense_bitfield_width;
-       int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
 
index 2848171b8576f3475c63b0669c5a9788d11e6069..b31d8e99c41992c77610fe5ca1694211035ea592 100644 (file)
@@ -82,22 +82,12 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
                      (sizeof(struct led_pwm_data) * num_leds);
 }
 
-static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+static int led_pwm_create_of(struct platform_device *pdev,
+                            struct led_pwm_priv *priv)
 {
        struct device_node *node = pdev->dev.of_node;
        struct device_node *child;
-       struct led_pwm_priv *priv;
-       int count, ret;
-
-       /* count LEDs in this device, so we know how much to allocate */
-       count = of_get_child_count(node);
-       if (!count)
-               return NULL;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
-                           GFP_KERNEL);
-       if (!priv)
-               return NULL;
+       int ret;
 
        for_each_child_of_node(node, child) {
                struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
@@ -109,6 +99,7 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
                if (IS_ERR(led_dat->pwm)) {
                        dev_err(&pdev->dev, "unable to request PWM for %s\n",
                                led_dat->cdev.name);
+                       ret = PTR_ERR(led_dat->pwm);
                        goto err;
                }
                /* Get the period from PWM core when n*/
@@ -137,28 +128,36 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
                priv->num_leds++;
        }
 
-       return priv;
+       return 0;
 err:
        while (priv->num_leds--)
                led_classdev_unregister(&priv->leds[priv->num_leds].cdev);
 
-       return NULL;
+       return ret;
 }
 
 static int led_pwm_probe(struct platform_device *pdev)
 {
        struct led_pwm_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct led_pwm_priv *priv;
-       int i, ret = 0;
+       int count, i;
+       int ret = 0;
+
+       if (pdata)
+               count = pdata->num_leds;
+       else
+               count = of_get_child_count(pdev->dev.of_node);
+
+       if (!count)
+               return -EINVAL;
 
-       if (pdata && pdata->num_leds) {
-               priv = devm_kzalloc(&pdev->dev,
-                                   sizeof_pwm_leds_priv(pdata->num_leds),
-                                   GFP_KERNEL);
-               if (!priv)
-                       return -ENOMEM;
+       priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               for (i = 0; i < pdata->num_leds; i++) {
+       if (pdata) {
+               for (i = 0; i < count; i++) {
                        struct led_pwm *cur_led = &pdata->leds[i];
                        struct led_pwm_data *led_dat = &priv->leds[i];
 
@@ -188,11 +187,11 @@ static int led_pwm_probe(struct platform_device *pdev)
                        if (ret < 0)
                                goto err;
                }
-               priv->num_leds = pdata->num_leds;
+               priv->num_leds = count;
        } else {
-               priv = led_pwm_create_of(pdev);
-               if (!priv)
-                       return -ENODEV;
+               ret = led_pwm_create_of(pdev, priv);
+               if (ret)
+                       return ret;
        }
 
        platform_set_drvdata(pdev, priv);
index 6753b65f8edeb2db67625a6fdf468b7c8b634928..d2f0120bc878379f460fc9a9d0416d2ae2e89bdd 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_WINDFARM_RM31)     += windfarm_fcu_controls.o \
                                   windfarm_ad7417_sensor.o \
                                   windfarm_lm75_sensor.o \
                                   windfarm_lm87_sensor.o \
+                                  windfarm_max6690_sensor.o \
                                   windfarm_pid.o \
                                   windfarm_cpufreq_clamp.o \
                                   windfarm_rm31.o
index 2b46bf1d7e40ca7375517ebb97a2225475844a91..4c9852d92b0a909d5b103510ae77d55f4bb05ad0 100644 (file)
@@ -421,9 +421,11 @@ out:
 
        if (watermark <= WATERMARK_METADATA) {
                SET_GC_MARK(b, GC_MARK_METADATA);
+               SET_GC_MOVE(b, 0);
                b->prio = BTREE_PRIO;
        } else {
                SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+               SET_GC_MOVE(b, 0);
                b->prio = INITIAL_PRIO;
        }
 
index 4beb55a0ff30dc9da10c340270e9cbd1c0e1c0b0..754f4317748322e7450d69da9591b6b72aff6dc4 100644 (file)
@@ -197,7 +197,7 @@ struct bucket {
        uint8_t         disk_gen;
        uint8_t         last_gc; /* Most out of date gen in the btree */
        uint8_t         gc_gen;
-       uint16_t        gc_mark;
+       uint16_t        gc_mark; /* Bitfield used by GC. See below for field */
 };
 
 /*
@@ -209,7 +209,8 @@ BITMASK(GC_MARK,     struct bucket, gc_mark, 0, 2);
 #define GC_MARK_RECLAIMABLE    0
 #define GC_MARK_DIRTY          1
 #define GC_MARK_METADATA       2
-BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 14);
+BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13);
+BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1);
 
 #include "journal.h"
 #include "stats.h"
@@ -372,14 +373,14 @@ struct cached_dev {
        unsigned char           writeback_percent;
        unsigned                writeback_delay;
 
-       int                     writeback_rate_change;
-       int64_t                 writeback_rate_derivative;
        uint64_t                writeback_rate_target;
+       int64_t                 writeback_rate_proportional;
+       int64_t                 writeback_rate_derivative;
+       int64_t                 writeback_rate_change;
 
        unsigned                writeback_rate_update_seconds;
        unsigned                writeback_rate_d_term;
        unsigned                writeback_rate_p_term_inverse;
-       unsigned                writeback_rate_d_smooth;
 };
 
 enum alloc_watermarks {
@@ -445,7 +446,6 @@ struct cache {
         * call prio_write() to keep gens from wrapping.
         */
        uint8_t                 need_save_prio;
-       unsigned                gc_move_threshold;
 
        /*
         * If nonzero, we know we aren't going to find any buckets to invalidate
index 5e2765aadce174e9b7cffd479667a2c48bcf500f..31bb53fcc67a40806cf73659a596f98297d36128 100644 (file)
@@ -1561,6 +1561,28 @@ size_t bch_btree_gc_finish(struct cache_set *c)
                SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i),
                            GC_MARK_METADATA);
 
+       /* don't reclaim buckets to which writeback keys point */
+       rcu_read_lock();
+       for (i = 0; i < c->nr_uuids; i++) {
+               struct bcache_device *d = c->devices[i];
+               struct cached_dev *dc;
+               struct keybuf_key *w, *n;
+               unsigned j;
+
+               if (!d || UUID_FLASH_ONLY(&c->uuids[i]))
+                       continue;
+               dc = container_of(d, struct cached_dev, disk);
+
+               spin_lock(&dc->writeback_keys.lock);
+               rbtree_postorder_for_each_entry_safe(w, n,
+                                       &dc->writeback_keys.keys, node)
+                       for (j = 0; j < KEY_PTRS(&w->key); j++)
+                               SET_GC_MARK(PTR_BUCKET(c, &w->key, j),
+                                           GC_MARK_DIRTY);
+               spin_unlock(&dc->writeback_keys.lock);
+       }
+       rcu_read_unlock();
+
        for_each_cache(ca, c, i) {
                uint64_t *i;
 
@@ -1817,7 +1839,8 @@ static bool fix_overlapping_extents(struct btree *b, struct bkey *insert,
                        if (KEY_START(k) > KEY_START(insert) + sectors_found)
                                goto check_failed;
 
-                       if (KEY_PTRS(replace_key) != KEY_PTRS(k))
+                       if (KEY_PTRS(k) != KEY_PTRS(replace_key) ||
+                           KEY_DIRTY(k) != KEY_DIRTY(replace_key))
                                goto check_failed;
 
                        /* skip past gen */
@@ -2217,7 +2240,7 @@ struct btree_insert_op {
        struct bkey     *replace_key;
 };
 
-int btree_insert_fn(struct btree_op *b_op, struct btree *b)
+static int btree_insert_fn(struct btree_op *b_op, struct btree *b)
 {
        struct btree_insert_op *op = container_of(b_op,
                                        struct btree_insert_op, op);
index 7c1275e66025b691ec8ee4896448d46e28a2c5d9..f2f0998c4a91872407dd036a54fe72d243885fed 100644 (file)
@@ -25,10 +25,9 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
        unsigned i;
 
        for (i = 0; i < KEY_PTRS(k); i++) {
-               struct cache *ca = PTR_CACHE(c, k, i);
                struct bucket *g = PTR_BUCKET(c, k, i);
 
-               if (GC_SECTORS_USED(g) < ca->gc_move_threshold)
+               if (GC_MOVE(g))
                        return true;
        }
 
@@ -65,11 +64,16 @@ static void write_moving_finish(struct closure *cl)
 
 static void read_moving_endio(struct bio *bio, int error)
 {
+       struct bbio *b = container_of(bio, struct bbio, bio);
        struct moving_io *io = container_of(bio->bi_private,
                                            struct moving_io, cl);
 
        if (error)
                io->op.error = error;
+       else if (!KEY_DIRTY(&b->key) &&
+                ptr_stale(io->op.c, &b->key, 0)) {
+               io->op.error = -EINTR;
+       }
 
        bch_bbio_endio(io->op.c, bio, error, "reading data to move");
 }
@@ -141,6 +145,11 @@ static void read_moving(struct cache_set *c)
                if (!w)
                        break;
 
+               if (ptr_stale(c, &w->key, 0)) {
+                       bch_keybuf_del(&c->moving_gc_keys, w);
+                       continue;
+               }
+
                io = kzalloc(sizeof(struct moving_io) + sizeof(struct bio_vec)
                             * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
                             GFP_KERNEL);
@@ -184,7 +193,8 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r)
 
 static unsigned bucket_heap_top(struct cache *ca)
 {
-       return GC_SECTORS_USED(heap_peek(&ca->heap));
+       struct bucket *b;
+       return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0;
 }
 
 void bch_moving_gc(struct cache_set *c)
@@ -226,9 +236,8 @@ void bch_moving_gc(struct cache_set *c)
                        sectors_to_move -= GC_SECTORS_USED(b);
                }
 
-               ca->gc_move_threshold = bucket_heap_top(ca);
-
-               pr_debug("threshold %u", ca->gc_move_threshold);
+               while (heap_pop(&ca->heap, b, bucket_cmp))
+                       SET_GC_MOVE(b, 1);
        }
 
        mutex_unlock(&c->bucket_lock);
index dec15cd2d797eaaa7fa0585abf8867c9f70a4cef..c57bfa071a57c58b06fabeb194cbf98f5f4fbf56 100644 (file)
@@ -1676,7 +1676,7 @@ err:
 static bool can_attach_cache(struct cache *ca, struct cache_set *c)
 {
        return ca->sb.block_size        == c->sb.block_size &&
-               ca->sb.bucket_size      == c->sb.block_size &&
+               ca->sb.bucket_size      == c->sb.bucket_size &&
                ca->sb.nr_in_set        == c->sb.nr_in_set;
 }
 
index 80d4c2bee18aa3fd1af0f58c050145af8e0a1c98..a1f85612f0b3dfc5c90b768aaef48118034c02c7 100644 (file)
@@ -83,7 +83,6 @@ rw_attribute(writeback_rate);
 rw_attribute(writeback_rate_update_seconds);
 rw_attribute(writeback_rate_d_term);
 rw_attribute(writeback_rate_p_term_inverse);
-rw_attribute(writeback_rate_d_smooth);
 read_attribute(writeback_rate_debug);
 
 read_attribute(stripe_size);
@@ -129,31 +128,41 @@ SHOW(__bch_cached_dev)
        var_printf(writeback_running,   "%i");
        var_print(writeback_delay);
        var_print(writeback_percent);
-       sysfs_print(writeback_rate,     dc->writeback_rate.rate);
+       sysfs_hprint(writeback_rate,    dc->writeback_rate.rate << 9);
 
        var_print(writeback_rate_update_seconds);
        var_print(writeback_rate_d_term);
        var_print(writeback_rate_p_term_inverse);
-       var_print(writeback_rate_d_smooth);
 
        if (attr == &sysfs_writeback_rate_debug) {
+               char rate[20];
                char dirty[20];
-               char derivative[20];
                char target[20];
-               bch_hprint(dirty,
-                          bcache_dev_sectors_dirty(&dc->disk) << 9);
-               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               char proportional[20];
+               char derivative[20];
+               char change[20];
+               s64 next_io;
+
+               bch_hprint(rate,        dc->writeback_rate.rate << 9);
+               bch_hprint(dirty,       bcache_dev_sectors_dirty(&dc->disk) << 9);
                bch_hprint(target,      dc->writeback_rate_target << 9);
+               bch_hprint(proportional,dc->writeback_rate_proportional << 9);
+               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               bch_hprint(change,      dc->writeback_rate_change << 9);
+
+               next_io = div64_s64(dc->writeback_rate.next - local_clock(),
+                                   NSEC_PER_MSEC);
 
                return sprintf(buf,
-                              "rate:\t\t%u\n"
-                              "change:\t\t%i\n"
+                              "rate:\t\t%s/sec\n"
                               "dirty:\t\t%s\n"
+                              "target:\t\t%s\n"
+                              "proportional:\t%s\n"
                               "derivative:\t%s\n"
-                              "target:\t\t%s\n",
-                              dc->writeback_rate.rate,
-                              dc->writeback_rate_change,
-                              dirty, derivative, target);
+                              "change:\t\t%s/sec\n"
+                              "next io:\t%llims\n",
+                              rate, dirty, target, proportional,
+                              derivative, change, next_io);
        }
 
        sysfs_hprint(dirty_data,
@@ -189,6 +198,7 @@ STORE(__cached_dev)
        struct kobj_uevent_env *env;
 
 #define d_strtoul(var)         sysfs_strtoul(var, dc->var)
+#define d_strtoul_nonzero(var) sysfs_strtoul_clamp(var, dc->var, 1, INT_MAX)
 #define d_strtoi_h(var)                sysfs_hatoi(var, dc->var)
 
        sysfs_strtoul(data_csum,        dc->disk.data_csum);
@@ -197,16 +207,15 @@ STORE(__cached_dev)
        d_strtoul(writeback_metadata);
        d_strtoul(writeback_running);
        d_strtoul(writeback_delay);
-       sysfs_strtoul_clamp(writeback_rate,
-                           dc->writeback_rate.rate, 1, 1000000);
+
        sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40);
 
-       d_strtoul(writeback_rate_update_seconds);
+       sysfs_strtoul_clamp(writeback_rate,
+                           dc->writeback_rate.rate, 1, INT_MAX);
+
+       d_strtoul_nonzero(writeback_rate_update_seconds);
        d_strtoul(writeback_rate_d_term);
-       d_strtoul(writeback_rate_p_term_inverse);
-       sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
-                           dc->writeback_rate_p_term_inverse, 1, INT_MAX);
-       d_strtoul(writeback_rate_d_smooth);
+       d_strtoul_nonzero(writeback_rate_p_term_inverse);
 
        d_strtoi_h(sequential_cutoff);
        d_strtoi_h(readahead);
@@ -313,7 +322,6 @@ static struct attribute *bch_cached_dev_files[] = {
        &sysfs_writeback_rate_update_seconds,
        &sysfs_writeback_rate_d_term,
        &sysfs_writeback_rate_p_term_inverse,
-       &sysfs_writeback_rate_d_smooth,
        &sysfs_writeback_rate_debug,
        &sysfs_dirty_data,
        &sysfs_stripe_size,
index 462214eeacbedbd9548e725be2e625723cda0d7e..bb37618e76648b7bc3caf99532e4f81b48666dfe 100644 (file)
@@ -209,7 +209,13 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
 {
        uint64_t now = local_clock();
 
-       d->next += div_u64(done, d->rate);
+       d->next += div_u64(done * NSEC_PER_SEC, d->rate);
+
+       if (time_before64(now + NSEC_PER_SEC, d->next))
+               d->next = now + NSEC_PER_SEC;
+
+       if (time_after64(now - NSEC_PER_SEC * 2, d->next))
+               d->next = now - NSEC_PER_SEC * 2;
 
        return time_after64(d->next, now)
                ? div_u64(d->next - now, NSEC_PER_SEC / HZ)
index 362c4b3f8b4a00e70d2e36af9ee7ec8cbe67e39e..1030c6020e986934e21c94628794e5e342271b49 100644 (file)
@@ -110,7 +110,7 @@ do {                                                                        \
        _r;                                                             \
 })
 
-#define heap_peek(h)   ((h)->size ? (h)->data[0] : NULL)
+#define heap_peek(h)   ((h)->used ? (h)->data[0] : NULL)
 
 #define heap_full(h)   ((h)->used == (h)->size)
 
index 99053b1251bea1049c627580f3614d1c18f89b60..6c44fe059c2769a4b2c317f25878596268726f0d 100644 (file)
@@ -30,38 +30,40 @@ static void __update_writeback_rate(struct cached_dev *dc)
 
        /* PD controller */
 
-       int change = 0;
-       int64_t error;
        int64_t dirty = bcache_dev_sectors_dirty(&dc->disk);
        int64_t derivative = dirty - dc->disk.sectors_dirty_last;
+       int64_t proportional = dirty - target;
+       int64_t change;
 
        dc->disk.sectors_dirty_last = dirty;
 
-       derivative *= dc->writeback_rate_d_term;
-       derivative = clamp(derivative, -dirty, dirty);
+       /* Scale to sectors per second */
 
-       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
-                             dc->writeback_rate_d_smooth, 0);
+       proportional *= dc->writeback_rate_update_seconds;
+       proportional = div_s64(proportional, dc->writeback_rate_p_term_inverse);
 
-       /* Avoid divide by zero */
-       if (!target)
-               goto out;
+       derivative = div_s64(derivative, dc->writeback_rate_update_seconds);
 
-       error = div64_s64((dirty + derivative - target) << 8, target);
+       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
+                             (dc->writeback_rate_d_term /
+                              dc->writeback_rate_update_seconds) ?: 1, 0);
+
+       derivative *= dc->writeback_rate_d_term;
+       derivative = div_s64(derivative, dc->writeback_rate_p_term_inverse);
 
-       change = div_s64((dc->writeback_rate.rate * error) >> 8,
-                        dc->writeback_rate_p_term_inverse);
+       change = proportional + derivative;
 
        /* Don't increase writeback rate if the device isn't keeping up */
        if (change > 0 &&
            time_after64(local_clock(),
-                        dc->writeback_rate.next + 10 * NSEC_PER_MSEC))
+                        dc->writeback_rate.next + NSEC_PER_MSEC))
                change = 0;
 
        dc->writeback_rate.rate =
-               clamp_t(int64_t, dc->writeback_rate.rate + change,
+               clamp_t(int64_t, (int64_t) dc->writeback_rate.rate + change,
                        1, NSEC_PER_MSEC);
-out:
+
+       dc->writeback_rate_proportional = proportional;
        dc->writeback_rate_derivative = derivative;
        dc->writeback_rate_change = change;
        dc->writeback_rate_target = target;
@@ -87,15 +89,11 @@ static void update_writeback_rate(struct work_struct *work)
 
 static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
 {
-       uint64_t ret;
-
        if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
            !dc->writeback_percent)
                return 0;
 
-       ret = bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
-
-       return min_t(uint64_t, ret, HZ);
+       return bch_next_delay(&dc->writeback_rate, sectors);
 }
 
 struct dirty_io {
@@ -241,7 +239,7 @@ static void read_dirty(struct cached_dev *dc)
                if (KEY_START(&w->key) != dc->last_read ||
                    jiffies_to_msecs(delay) > 50)
                        while (!kthread_should_stop() && delay)
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
 
                dc->last_read   = KEY_OFFSET(&w->key);
 
@@ -438,7 +436,7 @@ static int bch_writeback_thread(void *arg)
                        while (delay &&
                               !kthread_should_stop() &&
                               !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
                }
        }
 
@@ -476,6 +474,8 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
 
        bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0),
                           sectors_dirty_init_fn, 0);
+
+       dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
 }
 
 int bch_cached_dev_writeback_init(struct cached_dev *dc)
@@ -490,18 +490,15 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc)
        dc->writeback_delay             = 30;
        dc->writeback_rate.rate         = 1024;
 
-       dc->writeback_rate_update_seconds = 30;
-       dc->writeback_rate_d_term       = 16;
-       dc->writeback_rate_p_term_inverse = 64;
-       dc->writeback_rate_d_smooth     = 8;
+       dc->writeback_rate_update_seconds = 5;
+       dc->writeback_rate_d_term       = 30;
+       dc->writeback_rate_p_term_inverse = 6000;
 
        dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
                                              "bcache_writeback");
        if (IS_ERR(dc->writeback_thread))
                return PTR_ERR(dc->writeback_thread);
 
-       set_task_state(dc->writeback_thread, TASK_INTERRUPTIBLE);
-
        INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
        schedule_delayed_work(&dc->writeback_rate_update,
                              dc->writeback_rate_update_seconds * HZ);
index 173cbb20d10498b21440ada78b27f241b47af2cc..54bdd923316f92818d509f06986c9a9a3b7b1927 100644 (file)
@@ -1717,6 +1717,11 @@ static int __init dm_bufio_init(void)
 {
        __u64 mem;
 
+       dm_bufio_allocated_kmem_cache = 0;
+       dm_bufio_allocated_get_free_pages = 0;
+       dm_bufio_allocated_vmalloc = 0;
+       dm_bufio_current_allocated = 0;
+
        memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
        memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
 
index 416b7b752a6e0018d4a11800606a8be6b8890e22..64780ad73bb01737a957ea9682d016da4dbffa93 100644 (file)
@@ -730,15 +730,18 @@ static int pre_cache_entry_found(struct mq_policy *mq, struct entry *e,
        int r = 0;
        bool updated = updated_this_tick(mq, e);
 
-       requeue_and_update_tick(mq, e);
-
        if ((!discarded_oblock && updated) ||
-           !should_promote(mq, e, discarded_oblock, data_dir))
+           !should_promote(mq, e, discarded_oblock, data_dir)) {
+               requeue_and_update_tick(mq, e);
                result->op = POLICY_MISS;
-       else if (!can_migrate)
+
+       } else if (!can_migrate)
                r = -EWOULDBLOCK;
-       else
+
+       else {
+               requeue_and_update_tick(mq, e);
                r = pre_cache_to_cache(mq, e, result);
+       }
 
        return r;
 }
index 9efcf1059b99e3ae2e6e712eb150c0954646d5d8..1b1469ebe5cbad66af0853e0766ba20dbee63275 100644 (file)
@@ -2755,7 +2755,7 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size)
 {
        int r;
 
-       r = dm_cache_resize(cache->cmd, cache->cache_size);
+       r = dm_cache_resize(cache->cmd, new_size);
        if (r) {
                DMERR("could not resize cache metadata");
                return r;
index 496d5f3646a5df623e6c0a9b22d35ad003c610bc..2f91d6d4a2ccf40023c6bccfe142d7781024c810 100644 (file)
@@ -20,6 +20,7 @@
 struct delay_c {
        struct timer_list delay_timer;
        struct mutex timer_lock;
+       struct workqueue_struct *kdelayd_wq;
        struct work_struct flush_expired_bios;
        struct list_head delayed_bios;
        atomic_t may_delay;
@@ -45,14 +46,13 @@ struct dm_delay_info {
 
 static DEFINE_MUTEX(delayed_bios_lock);
 
-static struct workqueue_struct *kdelayd_wq;
 static struct kmem_cache *delayed_cache;
 
 static void handle_delayed_timer(unsigned long data)
 {
        struct delay_c *dc = (struct delay_c *)data;
 
-       queue_work(kdelayd_wq, &dc->flush_expired_bios);
+       queue_work(dc->kdelayd_wq, &dc->flush_expired_bios);
 }
 
 static void queue_timeout(struct delay_c *dc, unsigned long expires)
@@ -191,6 +191,12 @@ out:
                goto bad_dev_write;
        }
 
+       dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
+       if (!dc->kdelayd_wq) {
+               DMERR("Couldn't start kdelayd");
+               goto bad_queue;
+       }
+
        setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
 
        INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
@@ -203,6 +209,8 @@ out:
        ti->private = dc;
        return 0;
 
+bad_queue:
+       mempool_destroy(dc->delayed_pool);
 bad_dev_write:
        if (dc->dev_write)
                dm_put_device(ti, dc->dev_write);
@@ -217,7 +225,7 @@ static void delay_dtr(struct dm_target *ti)
 {
        struct delay_c *dc = ti->private;
 
-       flush_workqueue(kdelayd_wq);
+       destroy_workqueue(dc->kdelayd_wq);
 
        dm_put_device(ti, dc->dev_read);
 
@@ -350,12 +358,6 @@ static int __init dm_delay_init(void)
 {
        int r = -ENOMEM;
 
-       kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
-       if (!kdelayd_wq) {
-               DMERR("Couldn't start kdelayd");
-               goto bad_queue;
-       }
-
        delayed_cache = KMEM_CACHE(dm_delay_info, 0);
        if (!delayed_cache) {
                DMERR("Couldn't create delayed bio cache.");
@@ -373,8 +375,6 @@ static int __init dm_delay_init(void)
 bad_register:
        kmem_cache_destroy(delayed_cache);
 bad_memcache:
-       destroy_workqueue(kdelayd_wq);
-bad_queue:
        return r;
 }
 
@@ -382,7 +382,6 @@ static void __exit dm_delay_exit(void)
 {
        dm_unregister_target(&delay_target);
        kmem_cache_destroy(delayed_cache);
-       destroy_workqueue(kdelayd_wq);
 }
 
 /* Module hooks */
index aec57d76db5d616c8e692fa95cee58a8f62a0573..944690bafd93241d9348f0a4f1cad7f917ce7d83 100644 (file)
@@ -66,6 +66,18 @@ struct dm_snapshot {
 
        atomic_t pending_exceptions_count;
 
+       /* Protected by "lock" */
+       sector_t exception_start_sequence;
+
+       /* Protected by kcopyd single-threaded callback */
+       sector_t exception_complete_sequence;
+
+       /*
+        * A list of pending exceptions that completed out of order.
+        * Protected by kcopyd single-threaded callback.
+        */
+       struct list_head out_of_order_list;
+
        mempool_t *pending_pool;
 
        struct dm_exception_table pending;
@@ -173,6 +185,14 @@ struct dm_snap_pending_exception {
         */
        int started;
 
+       /* There was copying error. */
+       int copy_error;
+
+       /* A sequence number, it is used for in-order completion. */
+       sector_t exception_sequence;
+
+       struct list_head out_of_order_entry;
+
        /*
         * For writing a complete chunk, bypassing the copy.
         */
@@ -1094,6 +1114,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->valid = 1;
        s->active = 0;
        atomic_set(&s->pending_exceptions_count, 0);
+       s->exception_start_sequence = 0;
+       s->exception_complete_sequence = 0;
+       INIT_LIST_HEAD(&s->out_of_order_list);
        init_rwsem(&s->lock);
        INIT_LIST_HEAD(&s->list);
        spin_lock_init(&s->pe_lock);
@@ -1443,6 +1466,19 @@ static void commit_callback(void *context, int success)
        pending_complete(pe, success);
 }
 
+static void complete_exception(struct dm_snap_pending_exception *pe)
+{
+       struct dm_snapshot *s = pe->snap;
+
+       if (unlikely(pe->copy_error))
+               pending_complete(pe, 0);
+
+       else
+               /* Update the metadata if we are persistent */
+               s->store->type->commit_exception(s->store, &pe->e,
+                                                commit_callback, pe);
+}
+
 /*
  * Called when the copy I/O has finished.  kcopyd actually runs
  * this code so don't block.
@@ -1452,13 +1488,32 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
        struct dm_snap_pending_exception *pe = context;
        struct dm_snapshot *s = pe->snap;
 
-       if (read_err || write_err)
-               pending_complete(pe, 0);
+       pe->copy_error = read_err || write_err;
 
-       else
-               /* Update the metadata if we are persistent */
-               s->store->type->commit_exception(s->store, &pe->e,
-                                                commit_callback, pe);
+       if (pe->exception_sequence == s->exception_complete_sequence) {
+               s->exception_complete_sequence++;
+               complete_exception(pe);
+
+               while (!list_empty(&s->out_of_order_list)) {
+                       pe = list_entry(s->out_of_order_list.next,
+                                       struct dm_snap_pending_exception, out_of_order_entry);
+                       if (pe->exception_sequence != s->exception_complete_sequence)
+                               break;
+                       s->exception_complete_sequence++;
+                       list_del(&pe->out_of_order_entry);
+                       complete_exception(pe);
+               }
+       } else {
+               struct list_head *lh;
+               struct dm_snap_pending_exception *pe2;
+
+               list_for_each_prev(lh, &s->out_of_order_list) {
+                       pe2 = list_entry(lh, struct dm_snap_pending_exception, out_of_order_entry);
+                       if (pe2->exception_sequence < pe->exception_sequence)
+                               break;
+               }
+               list_add(&pe->out_of_order_entry, lh);
+       }
 }
 
 /*
@@ -1553,6 +1608,8 @@ __find_pending_exception(struct dm_snapshot *s,
                return NULL;
        }
 
+       pe->exception_sequence = s->exception_start_sequence++;
+
        dm_insert_exception(&s->pending, &pe->e);
 
        return pe;
@@ -2192,7 +2249,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 11, 1},
+       .version = {1, 12, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
index 3d404c1371ed2d7e6f4fa052fd4379fbc89ec388..28a90122a5a89272f5873ed0911d2de19125c15b 100644 (file)
@@ -964,6 +964,7 @@ int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
 
 int __init dm_statistics_init(void)
 {
+       shared_memory_amount = 0;
        dm_stat_need_rcu_barrier = 0;
        return 0;
 }
index 465f08ca62b1e355f8fd776fac4a6159d79a1a2e..3ba6a3859ce3c4957439ff3afdc4a5133bc2900b 100644 (file)
@@ -200,6 +200,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
 
        num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
 
+       if (!num_targets) {
+               kfree(t);
+               return -ENOMEM;
+       }
+
        if (alloc_targets(t, num_targets)) {
                kfree(t);
                return -ENOMEM;
index 60bce435f4fa1443c2994bd483e70ea096c7aa92..8a30ad54bd46aabc72f4ac1800890b5bd8041e11 100644 (file)
@@ -1697,6 +1697,14 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
        up_write(&pmd->root_lock);
 }
 
+void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd)
+{
+       down_write(&pmd->root_lock);
+       pmd->read_only = false;
+       dm_bm_set_read_write(pmd->bm);
+       up_write(&pmd->root_lock);
+}
+
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_block_t threshold,
                                        dm_sm_threshold_fn fn,
index 845ebbe589a9e0a00505bab0150df48331233928..7bcc0e1d62386768d540c41da8e0a25bf7fe9e78 100644 (file)
@@ -193,6 +193,7 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz
  * that nothing is changing.
  */
 void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
+void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd);
 
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_block_t threshold,
index 2c0cf511ec2385fa5a558b5d2e1e1ed0c874c9f6..ee29037ffc2e74633050b708718ccbe963bf20d1 100644 (file)
@@ -640,7 +640,9 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
        if (r) {
-               DMERR_LIMIT("dm_thin_insert_block() failed");
+               DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d",
+                           dm_device_name(pool->pool_md), r);
+               set_pool_mode(pool, PM_READ_ONLY);
                cell_error(pool, m->cell);
                goto out;
        }
@@ -881,32 +883,23 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
        }
 }
 
-static int commit(struct pool *pool)
-{
-       int r;
-
-       r = dm_pool_commit_metadata(pool->pmd);
-       if (r)
-               DMERR_LIMIT("%s: commit failed: error = %d",
-                           dm_device_name(pool->pool_md), r);
-
-       return r;
-}
-
 /*
  * A non-zero return indicates read_only or fail_io mode.
  * Many callers don't care about the return value.
  */
-static int commit_or_fallback(struct pool *pool)
+static int commit(struct pool *pool)
 {
        int r;
 
        if (get_pool_mode(pool) != PM_WRITE)
                return -EINVAL;
 
-       r = commit(pool);
-       if (r)
+       r = dm_pool_commit_metadata(pool->pmd);
+       if (r) {
+               DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d",
+                           dm_device_name(pool->pool_md), r);
                set_pool_mode(pool, PM_READ_ONLY);
+       }
 
        return r;
 }
@@ -943,7 +936,9 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                 * Try to commit to see if that will free up some
                 * more space.
                 */
-               (void) commit_or_fallback(pool);
+               r = commit(pool);
+               if (r)
+                       return r;
 
                r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
                if (r)
@@ -957,7 +952,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                 * table reload).
                 */
                if (!free_blocks) {
-                       DMWARN("%s: no free space available.",
+                       DMWARN("%s: no free data space available.",
                               dm_device_name(pool->pool_md));
                        spin_lock_irqsave(&pool->lock, flags);
                        pool->no_free_space = 1;
@@ -967,8 +962,16 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
        }
 
        r = dm_pool_alloc_data_block(pool->pmd, result);
-       if (r)
+       if (r) {
+               if (r == -ENOSPC &&
+                   !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
+                   !free_blocks) {
+                       DMWARN("%s: no free metadata space available.",
+                              dm_device_name(pool->pool_md));
+                       set_pool_mode(pool, PM_READ_ONLY);
+               }
                return r;
+       }
 
        return 0;
 }
@@ -1349,7 +1352,7 @@ static void process_deferred_bios(struct pool *pool)
        if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
                return;
 
-       if (commit_or_fallback(pool)) {
+       if (commit(pool)) {
                while ((bio = bio_list_pop(&bios)))
                        bio_io_error(bio);
                return;
@@ -1397,6 +1400,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
        case PM_FAIL:
                DMERR("%s: switching pool to failure mode",
                      dm_device_name(pool->pool_md));
+               dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_fail;
                pool->process_discard = process_bio_fail;
                pool->process_prepared_mapping = process_prepared_mapping_fail;
@@ -1421,6 +1425,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
                break;
 
        case PM_WRITE:
+               dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
                pool->process_discard = process_discard;
                pool->process_prepared_mapping = process_prepared_mapping;
@@ -1637,12 +1642,19 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
        struct pool_c *pt = ti->private;
 
        /*
-        * We want to make sure that degraded pools are never upgraded.
+        * We want to make sure that a pool in PM_FAIL mode is never upgraded.
         */
        enum pool_mode old_mode = pool->pf.mode;
        enum pool_mode new_mode = pt->adjusted_pf.mode;
 
-       if (old_mode > new_mode)
+       /*
+        * If we were in PM_FAIL mode, rollback of metadata failed.  We're
+        * not going to recover without a thin_repair.  So we never let the
+        * pool move out of the old mode.  On the other hand a PM_READ_ONLY
+        * may have been due to a lack of metadata or data space, and may
+        * now work (ie. if the underlying devices have been resized).
+        */
+       if (old_mode == PM_FAIL)
                new_mode = old_mode;
 
        pool->ti = ti;
@@ -2266,7 +2278,7 @@ static int pool_preresume(struct dm_target *ti)
                return r;
 
        if (need_commit1 || need_commit2)
-               (void) commit_or_fallback(pool);
+               (void) commit(pool);
 
        return 0;
 }
@@ -2293,7 +2305,7 @@ static void pool_postsuspend(struct dm_target *ti)
 
        cancel_delayed_work(&pool->waker);
        flush_workqueue(pool->wq);
-       (void) commit_or_fallback(pool);
+       (void) commit(pool);
 }
 
 static int check_arg_count(unsigned argc, unsigned args_required)
@@ -2427,7 +2439,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct
        if (r)
                return r;
 
-       (void) commit_or_fallback(pool);
+       (void) commit(pool);
 
        r = dm_pool_reserve_metadata_snap(pool->pmd);
        if (r)
@@ -2489,7 +2501,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
                DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
 
        if (!r)
-               (void) commit_or_fallback(pool);
+               (void) commit(pool);
 
        return r;
 }
@@ -2544,7 +2556,7 @@ static void pool_status(struct dm_target *ti, status_type_t type,
 
                /* Commit to ensure statistics aren't out-of-date */
                if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-                       (void) commit_or_fallback(pool);
+                       (void) commit(pool);
 
                r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id);
                if (r) {
index b6b7a2866c9e99533afd59a0a142712f58febe63..21f4d7ff0da22ee16e7556958502a2fb9ea74502 100644 (file)
@@ -776,16 +776,10 @@ void md_super_wait(struct mddev *mddev)
        finish_wait(&mddev->sb_wait, &wq);
 }
 
-static void bi_complete(struct bio *bio, int error)
-{
-       complete((struct completion*)bio->bi_private);
-}
-
 int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
                 struct page *page, int rw, bool metadata_op)
 {
        struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
-       struct completion event;
        int ret;
 
        rw |= REQ_SYNC;
@@ -801,11 +795,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
        else
                bio->bi_sector = sector + rdev->data_offset;
        bio_add_page(bio, page, size, 0);
-       init_completion(&event);
-       bio->bi_private = &event;
-       bio->bi_end_io = bi_complete;
-       submit_bio(rw, bio);
-       wait_for_completion(&event);
+       submit_bio_wait(rw, bio);
 
        ret = test_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_put(bio);
@@ -7777,7 +7767,7 @@ void md_check_recovery(struct mddev *mddev)
        if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
                return;
        if ( ! (
-               (mddev->flags & ~ (1<<MD_CHANGE_PENDING)) ||
+               (mddev->flags & MD_UPDATE_SB_FLAGS & ~ (1<<MD_CHANGE_PENDING)) ||
                test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
                test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
                (mddev->external == 0 && mddev->safemode == 1) ||
index af96e24ec3280ff9c29a7b7f13fde6fc4ba43e52..1d75b1dc1e2e2fcdd24a3be8cf9f0168efacd51e 100644 (file)
@@ -317,8 +317,16 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
         * The shadow op will often be a noop.  Only insert if it really
         * copied data.
         */
-       if (dm_block_location(*block) != b)
+       if (dm_block_location(*block) != b) {
+               /*
+                * dm_tm_shadow_block will have already decremented the old
+                * block, but it is still referenced by the btree.  We
+                * increment to stop the insert decrementing it below zero
+                * when overwriting the old value.
+                */
+               dm_tm_inc(info->btree_info.tm, b);
                r = insert_ablock(info, index, *block, root);
+       }
 
        return r;
 }
index a7e8bf2963886dfa349a03644cf33ff1ded748c5..064a3c271baa8843657dca3c374ed89061565ad4 100644 (file)
@@ -626,6 +626,12 @@ void dm_bm_set_read_only(struct dm_block_manager *bm)
 }
 EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
 
+void dm_bm_set_read_write(struct dm_block_manager *bm)
+{
+       bm->read_only = false;
+}
+EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
+
 u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
 {
        return crc32c(~(u32) 0, data, len) ^ init_xor;
index 9a82083a66b6a86833bccc1d2b6d4d43c9de6500..13cd58e1fe69ffb4ed477b10ee6bbbe6d58d9926 100644 (file)
@@ -108,9 +108,9 @@ int dm_bm_unlock(struct dm_block *b);
 int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
                           struct dm_block *superblock);
 
- /*
 * Request data be prefetched into the cache.
 */
+/*
* Request data is prefetched into the cache.
+ */
 void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
 
 /*
@@ -125,6 +125,7 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
  * be returned if you do.
  */
 void dm_bm_set_read_only(struct dm_block_manager *bm);
+void dm_bm_set_read_write(struct dm_block_manager *bm);
 
 u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
 
index 6058569fe86c3dcf862ddc933e234e721dbdc3e6..466a60bbd716f6470d1e4004ac217c3f546f5c81 100644 (file)
@@ -381,7 +381,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
 }
 
 static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
-                       uint32_t (*mutator)(void *context, uint32_t old),
+                       int (*mutator)(void *context, uint32_t old, uint32_t *new),
                        void *context, enum allocation_event *ev)
 {
        int r;
@@ -410,11 +410,17 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
 
        if (old > 2) {
                r = sm_ll_lookup_big_ref_count(ll, b, &old);
-               if (r < 0)
+               if (r < 0) {
+                       dm_tm_unlock(ll->tm, nb);
                        return r;
+               }
        }
 
-       ref_count = mutator(context, old);
+       r = mutator(context, old, &ref_count);
+       if (r) {
+               dm_tm_unlock(ll->tm, nb);
+               return r;
+       }
 
        if (ref_count <= 2) {
                sm_set_bitmap(bm_le, bit, ref_count);
@@ -465,9 +471,10 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
        return ll->save_ie(ll, index, &ie_disk);
 }
 
-static uint32_t set_ref_count(void *context, uint32_t old)
+static int set_ref_count(void *context, uint32_t old, uint32_t *new)
 {
-       return *((uint32_t *) context);
+       *new = *((uint32_t *) context);
+       return 0;
 }
 
 int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
@@ -476,9 +483,10 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
        return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
 }
 
-static uint32_t inc_ref_count(void *context, uint32_t old)
+static int inc_ref_count(void *context, uint32_t old, uint32_t *new)
 {
-       return old + 1;
+       *new = old + 1;
+       return 0;
 }
 
 int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
@@ -486,9 +494,15 @@ int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
        return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
 }
 
-static uint32_t dec_ref_count(void *context, uint32_t old)
+static int dec_ref_count(void *context, uint32_t old, uint32_t *new)
 {
-       return old - 1;
+       if (!old) {
+               DMERR_LIMIT("unable to decrement a reference count below 0");
+               return -EINVAL;
+       }
+
+       *new = old - 1;
+       return 0;
 }
 
 int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
index 1c959684caef7512fafd3c1a5505c29c798a9c11..58fc1eef7499e1923ef00095502c1e1b49f50ffb 100644 (file)
@@ -384,12 +384,16 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
        int r = sm_metadata_new_block_(sm, b);
-       if (r)
+       if (r) {
                DMERR("unable to allocate new metadata block");
+               return r;
+       }
 
        r = sm_metadata_get_nr_free(sm, &count);
-       if (r)
+       if (r) {
                DMERR("couldn't get free block count");
+               return r;
+       }
 
        check_threshold(&smm->threshold, count);
 
index 47da0af6322be1bd7930f902c96c57875799a358..cc055da02e2a300706548041dc4d9cf63957978c 100644 (file)
@@ -678,26 +678,23 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
                        } else
                                init_stripe(sh, sector, previous);
                } else {
+                       spin_lock(&conf->device_lock);
                        if (atomic_read(&sh->count)) {
                                BUG_ON(!list_empty(&sh->lru)
                                    && !test_bit(STRIPE_EXPANDING, &sh->state)
                                    && !test_bit(STRIPE_ON_UNPLUG_LIST, &sh->state)
-                                   && !test_bit(STRIPE_ON_RELEASE_LIST, &sh->state));
+                                       );
                        } else {
-                               spin_lock(&conf->device_lock);
                                if (!test_bit(STRIPE_HANDLE, &sh->state))
                                        atomic_inc(&conf->active_stripes);
-                               if (list_empty(&sh->lru) &&
-                                   !test_bit(STRIPE_ON_RELEASE_LIST, &sh->state) &&
-                                   !test_bit(STRIPE_EXPANDING, &sh->state))
-                                       BUG();
+                               BUG_ON(list_empty(&sh->lru));
                                list_del_init(&sh->lru);
                                if (sh->group) {
                                        sh->group->stripes_cnt--;
                                        sh->group = NULL;
                                }
-                               spin_unlock(&conf->device_lock);
                        }
+                       spin_unlock(&conf->device_lock);
                }
        } while (sh == NULL);
 
@@ -5471,7 +5468,7 @@ static int alloc_thread_groups(struct r5conf *conf, int cnt,
        for (i = 0; i < *group_cnt; i++) {
                struct r5worker_group *group;
 
-               group = worker_groups[i];
+               group = &(*worker_groups)[i];
                INIT_LIST_HEAD(&group->handle_list);
                group->conf = conf;
                group->workers = workers + i * cnt;
index d0799e32336450d967114938fc610b66d4134070..9c9063cd3208909d5840a7c2cc745d1bf124f542 100644 (file)
@@ -955,7 +955,7 @@ struct sms_rx_stats {
        u32 modem_state;                /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
        s32 SNR;                /* dB */
        u32 ber;                /* Post Viterbi ber [1E-5] */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
        u32 ber_bit_count;      /* Total number of SYNC bits. */
        u32 ts_per;             /* Transport stream PER,
        0xFFFFFFFF indicate N/A */
@@ -981,7 +981,7 @@ struct sms_rx_stats_ex {
        u32 modem_state;                /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
        s32 SNR;                /* dB */
        u32 ber;                /* Post Viterbi ber [1E-5] */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
        u32 ber_bit_count;      /* Total number of SYNC bits. */
        u32 ts_per;             /* Transport stream PER,
        0xFFFFFFFF indicate N/A */
index 92c413ba0c7971386f052e2f4c4c00876062a31d..ae36d0ae0fb1991ae0ee2e16e392796ca12d271f 100644 (file)
@@ -95,7 +95,7 @@ struct RECEPTION_STATISTICS_PER_SLICES_S {
        u32 is_demod_locked;    /* 0 - not locked, 1 - locked */
 
        u32 ber_bit_count;      /* Total number of SYNC bits. */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
 
        s32 MRC_SNR;            /* dB */
        s32 mrc_in_band_pwr;    /* In band power in dBM */
index 58de4410c5258a7d6009ae47b5becd7e20fa6208..6c7ff0cdcd32ddd44cae9dcf85e98054a7601052 100644 (file)
@@ -435,7 +435,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                dprintk_tscheck("TEI detected. "
                                "PID=0x%x data1=0x%x\n",
                                pid, buf[1]);
-               /* data in this packet cant be trusted - drop it unless
+               /* data in this packet can't be trusted - drop it unless
                 * module option dvb_demux_feed_err_pkts is set */
                if (!dvb_demux_feed_err_pkts)
                        return;
@@ -1032,8 +1032,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
                return -EINVAL;
        }
 
-       if (feed->is_filtering)
+       if (feed->is_filtering) {
+               /* release dvbdmx->mutex as far as it is
+                  acquired by stop_filtering() itself */
+               mutex_unlock(&dvbdmx->mutex);
                feed->stop_filtering(feed);
+               mutex_lock(&dvbdmx->mutex);
+       }
 
        spin_lock_irq(&dvbdmx->lock);
        f = dvbdmxfeed->filter;
index 30ee59052157815edd50669afe2293ed4e2e8867..65728c25ea05adcd50bd658c96a6c54dd6fb569b 100644 (file)
@@ -170,18 +170,18 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
 static int af9033_wr_reg_val_tab(struct af9033_state *state,
                const struct reg_val *tab, int tab_len)
 {
+#define MAX_TAB_LEN 212
        int ret, i, j;
-       u8 buf[MAX_XFER_SIZE];
+       u8 buf[1 + MAX_TAB_LEN];
+
+       dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
 
        if (tab_len > sizeof(buf)) {
-               dev_warn(&state->i2c->dev,
-                        "%s: i2c wr len=%d is too big!\n",
-                        KBUILD_MODNAME, tab_len);
+               dev_warn(&state->i2c->dev, "%s: tab len %d is too big\n",
+                               KBUILD_MODNAME, tab_len);
                return -EINVAL;
        }
 
-       dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
-
        for (i = 0, j = 0; i < tab_len; i++) {
                buf[j] = tab[i].val;
 
index 125a44041011ca0ed17f99999a2bffaa5c1999a1..5c6ab4921bf11d2004ed77e9240b2452fbbb3974 100644 (file)
@@ -78,7 +78,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x4000;
-       if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+       if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000);
        buf[0] = (if_ctl >> 8) & 0x3f;
        buf[1] = (if_ctl >> 0) & 0xff;
 
index 90536147bf0458c444a59e176b79ddff09471f4f..6dbbee453ee15adb0c4d6b97196beefe6e7d9523 100644 (file)
@@ -3048,7 +3048,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
                        dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
 
                        locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
-                       /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */
+                       /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
                        *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
                        *tune_state = CT_DEMOD_STEP_5;
                        break;
@@ -3115,7 +3115,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
 
        case CT_DEMOD_STEP_9: /* 39 */
                        if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
-                               /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */
+                               /* defines timeout for mpeg lock depending on interleaver length of longest layer */
                                for (i = 0; i < 3; i++) {
                                        if (c->layer[i].interleaving >= deeper_interleaver) {
                                                dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
index d416c15691dadd69b49eda6f26c70892c3a02652..bf29a3f0e6f0ca440990f7b8b61e71e9bd02674a 100644 (file)
@@ -1191,7 +1191,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
                        goto error;
 
                if (state->m_enable_parallel == true) {
-                       /* paralel -> enable MD1 to MD7 */
+                       /* parallel -> enable MD1 to MD7 */
                        status = write16(state, SIO_PDR_MD1_CFG__A,
                                         sio_pdr_mdx_cfg);
                        if (status < 0)
@@ -1428,7 +1428,7 @@ static int mpegts_stop(struct drxk_state *state)
 
        dprintk(1, "\n");
 
-       /* Gracefull shutdown (byte boundaries) */
+       /* Graceful shutdown (byte boundaries) */
        status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
        if (status < 0)
                goto error;
@@ -2021,7 +2021,7 @@ static int mpegts_dto_setup(struct drxk_state *state,
                fec_oc_dto_burst_len = 204;
        }
 
-       /* Check serial or parrallel output */
+       /* Check serial or parallel output */
        fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
        if (state->m_enable_parallel == false) {
                /* MPEG data output is serial -> set ipr_mode[0] */
@@ -2908,7 +2908,7 @@ static int adc_synchronization(struct drxk_state *state)
                goto error;
 
        if (count == 1) {
-               /* Try sampling on a diffrent edge */
+               /* Try sampling on a different edge */
                u16 clk_neg = 0;
 
                status = read16(state, IQM_AF_CLKNEG__A, &clk_neg);
@@ -3306,7 +3306,7 @@ static int dvbt_sc_command(struct drxk_state *state,
        if (status < 0)
                goto error;
 
-       /* Retreive results parameters from SC */
+       /* Retrieve results parameters from SC */
        switch (cmd) {
                /* All commands yielding 5 results */
                /* All commands yielding 4 results */
@@ -3849,7 +3849,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
                break;
        }
 #if 0
-       /* No hierachical channels support in BDA */
+       /* No hierarchical channels support in BDA */
        /* Priority (only for hierarchical channels) */
        switch (channel->priority) {
        case DRX_PRIORITY_LOW:
@@ -4081,7 +4081,7 @@ error:
 /*============================================================================*/
 
 /**
-* \brief Retreive lock status .
+* \brief Retrieve lock status .
 * \param demod    Pointer to demodulator instance.
 * \param lockStat Pointer to lock status structure.
 * \return DRXStatus_t.
@@ -6174,7 +6174,7 @@ static int init_drxk(struct drxk_state *state)
                        goto error;
 
                /* Stamp driver version number in SCU data RAM in BCD code
-                       Done to enable field application engineers to retreive drxdriver version
+                       Done to enable field application engineers to retrieve drxdriver version
                        via I2C from SCU RAM.
                        Not using SCU command interface for SCU register access since no
                        microcode may be present.
@@ -6399,7 +6399,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
        fe->ops.tuner_ops.get_if_frequency(fe, &IF);
        start(state, 0, IF);
 
-       /* After set_frontend, stats aren't avaliable */
+       /* After set_frontend, stats aren't available */
        p->strength.stat[0].scale = FE_SCALE_RELATIVE;
        p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
        p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
index 7efb796c472c475bed62f1a0bb783f5b991a5b1e..50e8b63e5169bad938b1fc8b79e0871a619364d3 100644 (file)
@@ -710,6 +710,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
                sizeof(priv->tuner_i2c_adapter.name));
        priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
        priv->tuner_i2c_adapter.algo_data = NULL;
+       priv->tuner_i2c_adapter.dev.parent = &i2c->dev;
        i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
        if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
                dev_err(&i2c->dev,
index 4a5b7d211d2f14e3810111a7f6399405e5000935..b253d400e8176a8baa3d1ba6928a1911d74bdb9d 100644 (file)
@@ -52,9 +52,9 @@
 #define ADV7183_VS_FIELD_CTRL_1    0x31 /* Vsync field control 1 */
 #define ADV7183_VS_FIELD_CTRL_2    0x32 /* Vsync field control 2 */
 #define ADV7183_VS_FIELD_CTRL_3    0x33 /* Vsync field control 3 */
-#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync positon control 1 */
-#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync positon control 2 */
-#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync positon control 3 */
+#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync position control 1 */
+#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync position control 2 */
+#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync position control 3 */
 #define ADV7183_POLARITY           0x37 /* Polarity */
 #define ADV7183_NTSC_COMB_CTRL     0x38 /* NTSC comb control */
 #define ADV7183_PAL_COMB_CTRL      0x39 /* PAL comb control */
index fbfdd2fc2a367f5b48c67fc41785395508fc473d..a324106b9f11e985c0637c16578cd3922ee6f58b 100644 (file)
@@ -877,7 +877,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                break;
        case ADV7604_MODE_HDMI:
                /* set default prim_mode/vid_std for HDMI
-                  accoring to [REF_03, c. 4.2] */
+                  according to [REF_03, c. 4.2] */
                io_write(sd, 0x00, 0x02); /* video std */
                io_write(sd, 0x01, 0x06); /* prim mode */
                break;
index 22f729d66a9696522e18d42932ae383594cbca5f..b154f36740b49151e2b1e0daeaf307c53032f3e7 100644 (file)
@@ -1013,7 +1013,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                break;
        case ADV7842_MODE_HDMI:
                /* set default prim_mode/vid_std for HDMI
-                  accoring to [REF_03, c. 4.2] */
+                  according to [REF_03, c. 4.2] */
                io_write(sd, 0x00, 0x02); /* video std */
                io_write(sd, 0x01, 0x06); /* prim mode */
                break;
index 82bf5679da3064d5a8ffd9da91c3d9e085d8d8bb..99ee456700f4972ef53888d692aa5f4b19930bce 100644 (file)
@@ -394,7 +394,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        if (!rc) {
                /*
-                * If platform_data doesn't specify rc_dev, initilize it
+                * If platform_data doesn't specify rc_dev, initialize it
                 * internally
                 */
                rc = rc_allocate_device();
index f34429e452abf4e01dfd71d38ceb690d3c5ab021..a60931e66312e1ff3818ff363c0edd920c0d6c04 100644 (file)
@@ -544,7 +544,7 @@ int m5mols_init_controls(struct v4l2_subdev *sd)
        u16 zoom_step;
        int ret;
 
-       /* Determine the firmware dependant control range and step values */
+       /* Determine the firmware dependent control range and step values */
        ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max);
        if (ret < 0)
                return ret;
index 4734836fe5a410c8cf4249d9c455f5ceaf4b627c..1c2303d18bf49db242c00ac0cab8a474843c6db1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/log2.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
index 6fec9384d86e4877d5b750a9f9a9ceec53e06bde..e7f555cc827abb4ddc1eba44bb1526e1d32576e4 100644 (file)
@@ -1460,7 +1460,7 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
        mutex_unlock(&state->lock);
 
        v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n",
-                __func__, ret ? "failed" : "succeded", ret);
+                __func__, ret ? "failed" : "succeeded", ret);
 
        return ret;
 }
index 9d2c0865224609504ab1a9b9302cb99d53086e85..9dfa516f694471660f9de431c948ae279ed07bb9 100644 (file)
@@ -393,7 +393,7 @@ struct s5c73m3 {
 
        /* External master clock frequency */
        u32 mclk_frequency;
-       /* Video bus type - MIPI-CSI2/paralell */
+       /* Video bus type - MIPI-CSI2/parallel */
        enum v4l2_mbus_type bus_type;
 
        const struct s5c73m3_frame_size *sensor_pix_size[2];
index 637d026345271c154f4af2da7a53bde6adbcae94..afdbcb045ceece64685db171dac9699d8a7dfc49 100644 (file)
@@ -1699,7 +1699,7 @@ static void saa711x_write_platform_data(struct saa711x_state *state,
  * the analog demod.
  * If the tuner is not found, it returns -ENODEV.
  * If auto-detection is disabled and the tuner doesn't match what it was
- *     requred, it returns -EINVAL and fills 'name'.
+ *     required, it returns -EINVAL and fills 'name'.
  * If the chip is found, it returns the chip ID and fills 'name'.
  */
 static int saa711x_detect_chip(struct i2c_client *client,
index 0a5c5d4fedd6e375b34a1848f3b646a6577bd97d..d2daa6a8f27245b88f69d832b2f2537ab716b0f9 100644 (file)
@@ -642,7 +642,7 @@ static const struct ov5642_datafmt
 static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
 {
        int ret;
-       /* We have 16-bit i2c addresses - care for endianess */
+       /* We have 16-bit i2c addresses - care for endianness */
        unsigned char data[2] = { reg >> 8, reg & 0xff };
 
        ret = i2c_master_send(client, data, 2);
index 42276d93624cada191b30eb7e3ca7ad40fb923fa..ed9ae8875348b6abdd226e3026e4b1d6f117c12f 100644 (file)
@@ -83,7 +83,8 @@ static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 }
 
 /* following function is used to set ths7303 */
-int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
+static int ths7303_setval(struct v4l2_subdev *sd,
+                         enum ths7303_filter_mode mode)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ths7303_state *state = to_state(sd);
index 3f584a7d0781b9860aad6b6bb9f6ddef4ad2b449..bee7946faa7cc2ba28a690e219cd0c5dcf89ff3b 100644 (file)
@@ -130,12 +130,10 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
                return -EINVAL;
        }
        state->input = input;
-       if (!v4l2_ctrl_g_ctrl(state->mute))
+       if (v4l2_ctrl_g_ctrl(state->mute))
                return 0;
        if (!v4l2_ctrl_g_ctrl(state->vol))
                return 0;
-       if (!v4l2_ctrl_g_ctrl(state->bal))
-               return 0;
        wm8775_set_audio(sd, 1);
        return 0;
 }
index a3b1ee9c00d7152405e9ea0e71549f350194692e..92a06fd858652acddff2dd65ce07dee560445df1 100644 (file)
@@ -4182,7 +4182,8 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
        }
        btv->std = V4L2_STD_PAL;
        init_irqreg(btv);
-       v4l2_ctrl_handler_setup(hdl);
+       if (!bttv_tvcards[btv->c.type].no_video)
+               v4l2_ctrl_handler_setup(hdl);
        if (hdl->error) {
                result = hdl->error;
                goto fail2;
index 2767c64df0c87f9c044aca755a63fbfd0c75adf3..57f4688ea55bdf2488eb14dc523d4a4c542a2609 100644 (file)
@@ -262,7 +262,7 @@ struct cx18_options {
 };
 
 /* per-mdl bit flags */
-#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianess swapped */
+#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianness swapped */
 
 /* per-stream, s_flags */
 #define CX18_F_S_CLAIMED       3       /* this stream is claimed */
index e3fc2c71808abbd0746cc7d9faabdfc14b9c583f..95666eee7b277026f3c1154a78361212653130b9 100644 (file)
@@ -427,7 +427,7 @@ int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
        cx_write(MC417_RWD, regval);
 
        /* Transition RD to effect read transaction across bus.
-        * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+        * Transition 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
         * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
         * input only...)
         */
index 8164d74b46a4590af0db79f56bd8c41bacead624..655d6854a8d7fa165502c711bf6c83a017cc16be 100644 (file)
@@ -401,7 +401,7 @@ static int pluto_hw_init(struct pluto *pluto)
        /* set automatic LED control by FPGA */
        pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
 
-       /* set data endianess */
+       /* set data endianness */
 #ifdef __LITTLE_ENDIAN
        pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
 #else
index 57ef5456f1e87e9cc042ec8dc05cdb07192bc15d..1bf06970ca3e8e180cb6a2f20d732c983af820b2 100644 (file)
@@ -1354,9 +1354,11 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
                if (fw_debug) {
                        dev->kthread = kthread_run(saa7164_thread_function, dev,
                                "saa7164 debug");
-                       if (!dev->kthread)
+                       if (IS_ERR(dev->kthread)) {
+                               dev->kthread = NULL;
                                printk(KERN_ERR "%s() Failed to create "
                                        "debug kernel thread\n", __func__);
+                       }
                }
 
        } /* != BOARD_UNKNOWN */
index bd72fb97fea5ab05924c4eeb4f5452534f3c3f46..61f3dbcc259f40f8a0f6f2b4bfa9b52ed6bf24ee 100644 (file)
@@ -1434,7 +1434,7 @@ static void coda_buf_queue(struct vb2_buffer *vb)
        if (q_data->fourcc == V4L2_PIX_FMT_H264 &&
            vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /*
-                * For backwards compatiblity, queuing an empty buffer marks
+                * For backwards compatibility, queuing an empty buffer marks
                 * the stream end
                 */
                if (vb2_get_plane_payload(vb, 0) == 0)
index 3d66d88ea3a191911ce72a22a8198602d7640e35..f7915695c9073d37ca10da947c29891b8d0e45d5 100644 (file)
@@ -1039,7 +1039,7 @@ static int fimc_runtime_resume(struct device *dev)
 
        dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
 
-       /* Enable clocks and perform basic initalization */
+       /* Enable clocks and perform basic initialization */
        clk_enable(fimc->clock[CLK_GATE]);
        fimc_hw_reset(fimc);
 
index 7a4ee4c0449deea95dc86e82a85af8412a1d5aad..c1bce170df6fbce44d519a498bf6d19694389306 100644 (file)
@@ -759,7 +759,7 @@ static int fimc_md_register_platform_entity(struct fimc_md *fmd,
                goto dev_unlock;
 
        drvdata = dev_get_drvdata(dev);
-       /* Some subdev didn't probe succesfully id drvdata is NULL */
+       /* Some subdev didn't probe successfully id drvdata is NULL */
        if (drvdata) {
                switch (plat_entity) {
                case IDX_FIMC:
index 3458fa0e2fd537916270fd9fbb0908d2b1610821..054507f16734de8c04c67fbda15d9afff60d6f11 100644 (file)
@@ -142,12 +142,6 @@ static int mmpcam_power_up(struct mcam_camera *mcam)
        struct mmp_camera *cam = mcam_to_cam(mcam);
        struct mmp_camera_platform_data *pdata;
 
-       if (mcam->bus_type == V4L2_MBUS_CSI2) {
-               cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
-               if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
-                       return PTR_ERR(cam->mipi_clk);
-       }
-
 /*
  * Turn on power and clocks to the controller.
  */
@@ -186,12 +180,6 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
        gpio_set_value(pdata->sensor_power_gpio, 0);
        gpio_set_value(pdata->sensor_reset_gpio, 0);
 
-       if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) {
-               if (cam->mipi_clk)
-                       devm_clk_put(mcam->dev, cam->mipi_clk);
-               cam->mipi_clk = NULL;
-       }
-
        mcam_clk_disable(mcam);
 }
 
@@ -292,8 +280,9 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
                return;
 
        /* get the escape clk, this is hard coded */
+       clk_prepare_enable(cam->mipi_clk);
        tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12;
-
+       clk_disable_unprepare(cam->mipi_clk);
        /*
         * dphy[2] - CSI2_DPHY6:
         * bit 0 ~ bit 7: CK Term Enable
@@ -325,19 +314,6 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
        return IRQ_RETVAL(handled);
 }
 
-static void mcam_deinit_clk(struct mcam_camera *mcam)
-{
-       unsigned int i;
-
-       for (i = 0; i < NR_MCAM_CLK; i++) {
-               if (!IS_ERR(mcam->clk[i])) {
-                       if (mcam->clk[i])
-                               devm_clk_put(mcam->dev, mcam->clk[i]);
-               }
-               mcam->clk[i] = NULL;
-       }
-}
-
 static void mcam_init_clk(struct mcam_camera *mcam)
 {
        unsigned int i;
@@ -371,7 +347,6 @@ static int mmpcam_probe(struct platform_device *pdev)
        if (cam == NULL)
                return -ENOMEM;
        cam->pdev = pdev;
-       cam->mipi_clk = NULL;
        INIT_LIST_HEAD(&cam->devlist);
 
        mcam = &cam->mcam;
@@ -387,6 +362,11 @@ static int mmpcam_probe(struct platform_device *pdev)
        mcam->mclk_div = pdata->mclk_div;
        mcam->bus_type = pdata->bus_type;
        mcam->dphy = pdata->dphy;
+       if (mcam->bus_type == V4L2_MBUS_CSI2) {
+               cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
+               if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
+                       return PTR_ERR(cam->mipi_clk);
+       }
        mcam->mipi_enabled = false;
        mcam->lane = pdata->lane;
        mcam->chip_id = MCAM_ARMADA610;
@@ -444,7 +424,7 @@ static int mmpcam_probe(struct platform_device *pdev)
         */
        ret = mmpcam_power_up(mcam);
        if (ret)
-               goto out_deinit_clk;
+               return ret;
        ret = mccic_register(mcam);
        if (ret)
                goto out_power_down;
@@ -469,8 +449,6 @@ out_unregister:
        mccic_shutdown(mcam);
 out_power_down:
        mmpcam_power_down(mcam);
-out_deinit_clk:
-       mcam_deinit_clk(mcam);
        return ret;
 }
 
@@ -478,18 +456,10 @@ out_deinit_clk:
 static int mmpcam_remove(struct mmp_camera *cam)
 {
        struct mcam_camera *mcam = &cam->mcam;
-       struct mmp_camera_platform_data *pdata;
 
        mmpcam_remove_device(cam);
        mccic_shutdown(mcam);
        mmpcam_power_down(mcam);
-       pdata = cam->pdev->dev.platform_data;
-       gpio_free(pdata->sensor_reset_gpio);
-       gpio_free(pdata->sensor_power_gpio);
-       mcam_deinit_clk(mcam);
-       iounmap(cam->power_regs);
-       iounmap(mcam->regs);
-       kfree(cam);
        return 0;
 }
 
index 1c3608039663e281d23541f17aedcbce044c87fb..561bce8ffb1b57c87dd1b45bbae6cbf7c2b479c1 100644 (file)
@@ -1673,7 +1673,7 @@ void omap3isp_print_status(struct isp_device *isp)
  * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
  * resume(), and the the pipelines are restarted in complete().
  *
- * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
+ * TODO: PM dependencies between the ISP and sensors are not modelled explicitly
  * yet.
  */
 static int isp_pm_prepare(struct device *dev)
index a908d006f5277c2abe9adebcbb757ea699495fbf..f6304bb074f5edaa598f959515394448d30a3cc9 100644 (file)
@@ -339,14 +339,11 @@ __isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
        if (subdev == NULL)
                return -EINVAL;
 
-       mutex_lock(&video->mutex);
-
        fmt.pad = pad;
        fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
-       if (ret == -ENOIOCTLCMD)
-               ret = -EINVAL;
 
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        mutex_unlock(&video->mutex);
 
        if (ret)
index 9319e93599ae5731241b58535583bc1a04b77e73..6ccc3f8c122add705d7338d0656ac744331823fb 100644 (file)
 #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
 #define S5P_FIMV_R2H_CMD_ERR_RET               32
 
-/* Dummy definition for MFCv6 compatibilty */
+/* Dummy definition for MFCv6 compatibility */
 #define S5P_FIMV_CODEC_H264_MVC_DEC            -1
 #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
 #define S5P_FIMV_MFC_RESET                     -1
index 5f2c4ad6c2cb3427835ed2f40ec9ba5432ae3221..e46067a5785307ac7a1381bd8a8babd8e4ec4fc2 100644 (file)
@@ -239,7 +239,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
        frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
 
        /* Copy timestamp / timecode from decoded src to dst and set
-          appropraite flags */
+          appropriate flags */
        src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
        list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
                if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
@@ -428,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
                case MFCINST_FINISHING:
                case MFCINST_FINISHED:
                case MFCINST_RUNNING:
-                       /* It is higly probable that an error occured
+                       /* It is highly probable that an error occurred
                         * while decoding a frame */
                        clear_work_bit(ctx);
                        ctx->state = MFCINST_ERROR;
@@ -611,7 +611,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
        mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
        switch (reason) {
        case S5P_MFC_R2H_CMD_ERR_RET:
-               /* An error has occured */
+               /* An error has occurred */
                if (ctx->state == MFCINST_RUNNING &&
                        s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
                                dev->warn_start)
@@ -840,7 +840,7 @@ static int s5p_mfc_open(struct file *file)
        mutex_unlock(&dev->mfc_mutex);
        mfc_debug_leave();
        return ret;
-       /* Deinit when failure occured */
+       /* Deinit when failure occurred */
 err_queue_init:
        if (dev->num_inst == 1)
                s5p_mfc_deinit_hw(dev);
@@ -881,14 +881,14 @@ static int s5p_mfc_release(struct file *file)
        /* Mark context as idle */
        clear_work_bit_irqsave(ctx);
        /* If instance was initialised then
-        * return instance and free reosurces */
+        * return instance and free resources */
        if (ctx->inst_no != MFC_NO_INSTANCE_SET) {
                mfc_debug(2, "Has to free instance\n");
                ctx->state = MFCINST_RETURN_INST;
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               /* Wait until instance is returned or timeout occured */
+               /* Wait until instance is returned or timeout occurred */
                if (s5p_mfc_wait_for_done_ctx
                    (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
                        s5p_mfc_clock_off();
index 7cab6849fb5b73d9463c591b4b24eaffcae48bae..2475a3c9a0a62ab27330a347865530466d209e0d 100644 (file)
@@ -69,7 +69,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 
        } else {
                /* In this case bank2 can point to the same address as bank1.
-                * Firmware will always occupy the beggining of this area so it is
+                * Firmware will always occupy the beginning of this area so it is
                 * impossible having a video frame buffer with zero address. */
                dev->bank2 = dev->bank1;
        }
index 04e6490a45befbae453d55ef0a86be0bb32497d2..fb2acc53112a47201be7ec785057cdb491eabffc 100644 (file)
@@ -65,7 +65,7 @@ struct mxr_format {
        int num_subframes;
        /** specifies to which subframe belong given plane */
        int plane2subframe[MXR_MAX_PLANES];
-       /** internal code, driver dependant */
+       /** internal code, driver dependent */
        unsigned long cookie;
 };
 
index 641b1f071e06a2b74796f030ddfdcdc80644179b..81b97db111d8506a1c28df84a86ce4181f6ddccb 100644 (file)
@@ -528,7 +528,7 @@ static int mxr_s_dv_timings(struct file *file, void *fh,
        mutex_lock(&mdev->mutex);
 
        /* timings change cannot be done while there is an entity
-        * dependant on output configuration
+        * dependent on output configuration
         */
        if (mdev->n_output > 0) {
                mutex_unlock(&mdev->mutex);
@@ -585,7 +585,7 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id norm)
        mutex_lock(&mdev->mutex);
 
        /* standard change cannot be done while there is an entity
-        * dependant on output configuration
+        * dependent on output configuration
         */
        if (mdev->n_output > 0) {
                mutex_unlock(&mdev->mutex);
index 6769193c7c7bbeef27f723e98760f73ece8d0219..74ce8b6b79fa91c80644e0646996397befd325cc 100644 (file)
@@ -1495,7 +1495,7 @@ static int omap1_cam_set_bus_param(struct soc_camera_device *icd)
        if (ctrlclock & LCLK_EN)
                CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
 
-       /* select bus endianess */
+       /* select bus endianness */
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        fmt = xlate->host_fmt;
 
index 1d3f1196519669cca0509c1972bdb320d2d35ad1..2d4e73b45c5e3b05d7e4615f6f6fd0d46bd56656 100644 (file)
@@ -1108,7 +1108,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        return 0;
 }
 
-/* timeperframe is arbitrary and continous */
+/* timeperframe is arbitrary and continuous */
 static int vidioc_enum_frameintervals(struct file *file, void *priv,
                                             struct v4l2_frmivalenum *fival)
 {
@@ -1125,7 +1125,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
 
        fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
 
-       /* fill in stepwise (step=1.0 is requred by V4L2 spec) */
+       /* fill in stepwise (step=1.0 is required by V4L2 spec) */
        fival->stepwise.min  = tpf_min;
        fival->stepwise.max  = tpf_max;
        fival->stepwise.step = (struct v4l2_fract) {1, 1};
index 1c9e771aa15c7bb40b5a8a1de25d66b2b108c528..d16bf0f41e247bd69e3af1ebdc31e0309861e0fd 100644 (file)
@@ -323,7 +323,7 @@ static void vsp1_clocks_disable(struct vsp1_device *vsp1)
  * Increment the VSP1 reference count and initialize the device if the first
  * reference is taken.
  *
- * Return a pointer to the VSP1 device or NULL if an error occured.
+ * Return a pointer to the VSP1 device or NULL if an error occurred.
  */
 struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
 {
index 714c53ef6c11b19d48304405f363f750b26547d2..4b0ac07af662c2bca05c6534ecb52bfc15730c74 100644 (file)
@@ -1026,8 +1026,10 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf)
 
        /* ... and the buffers queue... */
        video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev);
-       if (IS_ERR(video->alloc_ctx))
+       if (IS_ERR(video->alloc_ctx)) {
+               ret = PTR_ERR(video->alloc_ctx);
                goto error;
+       }
 
        video->queue.type = video->type;
        video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
index 3db8a8cfe1a87f4eb80e9c22950bbcac93b7daed..050b3bb96fecc13a15f05d3f294147200954e8dd 100644 (file)
@@ -271,8 +271,7 @@ static void shark_unregister_leds(struct shark_device *shark)
        cancel_work_sync(&shark->led_work);
 }
 
-#ifdef CONFIG_PM
-static void shark_resume_leds(struct shark_device *shark)
+static inline void shark_resume_leds(struct shark_device *shark)
 {
        if (test_bit(BLUE_IS_PULSE, &shark->brightness_new))
                set_bit(BLUE_PULSE_LED, &shark->brightness_new);
@@ -281,7 +280,6 @@ static void shark_resume_leds(struct shark_device *shark)
        set_bit(RED_LED, &shark->brightness_new);
        schedule_work(&shark->led_work);
 }
-#endif
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
index d86d90dab8bf880666a05ca0463aa83fc62f77de..8654e0dc5c95376aa7140498e10af342b955d15a 100644 (file)
@@ -237,8 +237,7 @@ static void shark_unregister_leds(struct shark_device *shark)
        cancel_work_sync(&shark->led_work);
 }
 
-#ifdef CONFIG_PM
-static void shark_resume_leds(struct shark_device *shark)
+static inline void shark_resume_leds(struct shark_device *shark)
 {
        int i;
 
@@ -247,7 +246,6 @@ static void shark_resume_leds(struct shark_device *shark)
 
        schedule_work(&shark->led_work);
 }
-#endif
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
index 9c9084cb99f7dd1fde0800f0325c58584edd9e19..2fd9009f86633e74b4752472f5db2829daf6d9ce 100644 (file)
@@ -268,8 +268,8 @@ struct si476x_radio;
  *
  * @tune_freq: Tune chip to a specific frequency
  * @seek_start: Star station seeking
- * @rsq_status: Get Recieved Signal Quality(RSQ) status
- * @rds_blckcnt: Get recived RDS blocks count
+ * @rsq_status: Get Received Signal Quality(RSQ) status
+ * @rds_blckcnt: Get received RDS blocks count
  * @phase_diversity: Change phase diversity mode of the tuner
  * @phase_div_status: Get phase diversity mode status
  * @acf_status: Get the status of Automatically Controlled
index 036e2f54f4db4b1bc5c6f574e19ccde1960da9b5..3ed1f5669f791b9d3015bb91efd80ba2fa82d0c0 100644 (file)
@@ -356,7 +356,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                   So we keep it as-is. */
                return -EINVAL;
        }
-       clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
+       freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
        tea5764_power_up(radio);
        tea5764_tune(radio, (freq * 125) / 2);
        return 0;
index 69e3245a58a0cbfcc1d333d390a30aa45e4c70d8..a9319a24c7efe1290efbc5b309bb719584cf7b5f 100644 (file)
@@ -112,7 +112,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen
        if (f->tuner != 0)
                return -EINVAL;
 
-       clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
+       freq = clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
        pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL;
        i2cmsg[0] = (MSA_MODE_PRESET << MSA_MODE_SHIFT) | WM_SUB_PLLM;
        i2cmsg[1] = (pll >> 8) & 0xff;
index 72e3fa652481671cff04e2c06a1478d21fb0ffb6..f329485c6629b038ff2aee825edff86c82189328 100644 (file)
@@ -1370,7 +1370,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
         * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates
         * 0x688301b7 and the right one 0x688481b7. All other keys generate
         * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with
-        * reversed endianess. Extract direction from buffer, rotate endianess,
+        * reversed endianness. Extract direction from buffer, rotate endianness,
         * adjust sign and feed the values into stabilize(). The resulting codes
         * will be 0x01008000, 0x01007F00, which match the newer devices.
         */
index 094484fac94cdbe52f7832f140f87895e922e631..a5d4f883d053a7b0ebca0543ac82d29d216ec26a 100644 (file)
@@ -118,7 +118,7 @@ static int debug;
 #define RR3_IR_IO_LENGTH_FUZZ  0x04
 /* Timeout for end of signal detection */
 #define RR3_IR_IO_SIG_TIMEOUT  0x05
-/* Minumum value for pause recognition. */
+/* Minimum value for pause recognition. */
 #define RR3_IR_IO_MIN_PAUSE    0x06
 
 /* Clock freq. of EZ-USB chip */
index 2e1a02e360ff0cd7279fed8ca20b80a3ee0b8ad8..20cca405bf452c46195ebbbadb37c8a535e85d0b 100644 (file)
@@ -1195,7 +1195,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
  *   DNC Output is selected, the other is always off)
  *
  * @state:     ptr to mt2063_state structure
- * @Mode:      desired reciever delivery system
+ * @Mode:      desired receiver delivery system
  *
  * Note: Register cache must be valid for it to work
  */
@@ -2119,7 +2119,7 @@ static int mt2063_set_analog_params(struct dvb_frontend *fe,
 
 /*
  * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
- * So, the amount of the needed bandwith is given by:
+ * So, the amount of the needed bandwidth is given by:
  *     Bw = Symbol_rate * (1 + 0.15)
  * As such, the maximum symbol rate supported by 6 MHz is given by:
  *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
index 74dc46a71f64555c07bb67be9ee09facf822ad41..7e4798783db733cc139e557444f12d4bddb820b5 100644 (file)
 #define V4L2_STD_A2            (V4L2_STD_A2_A    | V4L2_STD_A2_B)
 #define V4L2_STD_NICAM         (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
 
-/* To preserve backward compatibilty,
+/* To preserve backward compatibility,
    (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
  */
 
index e9d017bea377069da087751404e75f86b081c7cd..528cce958a82c4a67c91ea0c52841364db36f7d4 100644 (file)
@@ -1412,8 +1412,8 @@ err_v4l2:
        usb_set_intfdata(interface, NULL);
 err_if:
        usb_put_dev(udev);
-       kfree(dev);
        clear_bit(dev->devno, &cx231xx_devused);
+       kfree(dev);
        return retval;
 }
 
index c8fcd78425bd228ca4374daf94fdbf4ed1c0c17a..8f9b2cea88f009ec316fb1b97cbbfa67984fcda0 100644 (file)
@@ -131,7 +131,7 @@ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
 {
        u8 wbuf[MAX_XFER_SIZE];
        u8 mbox = (reg >> 16) & 0xff;
-       struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL };
+       struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL };
 
        if (6 + len > sizeof(wbuf)) {
                dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n",
@@ -238,14 +238,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        /* I2C */
                        u8 buf[MAX_XFER_SIZE];
-                       struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
+                       struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len,
                                        buf, msg[1].len, msg[1].buf };
 
                        if (5 + msg[0].len > sizeof(buf)) {
                                dev_warn(&d->udev->dev,
                                         "%s: i2c xfer: len=%d is too big!\n",
                                         KBUILD_MODNAME, msg[0].len);
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto unlock;
                        }
                        req.mbox |= ((msg[0].addr & 0x80)  >>  3);
                        buf[0] = msg[1].len;
@@ -274,14 +275,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        /* I2C */
                        u8 buf[MAX_XFER_SIZE];
-                       struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf,
-                                       0, NULL };
+                       struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len,
+                                       buf, 0, NULL };
 
                        if (5 + msg[0].len > sizeof(buf)) {
                                dev_warn(&d->udev->dev,
                                         "%s: i2c xfer: len=%d is too big!\n",
                                         KBUILD_MODNAME, msg[0].len);
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto unlock;
                        }
                        req.mbox |= ((msg[0].addr & 0x80)  >>  3);
                        buf[0] = msg[0].len;
@@ -319,6 +321,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                ret = -EOPNOTSUPP;
        }
 
+unlock:
        mutex_unlock(&d->i2c_mutex);
 
        if (ret < 0)
@@ -1534,6 +1537,8 @@ static const struct usb_device_id af9035_id_table[] = {
        /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
                &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05,
+               &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
index 2627553f7de1f90c262f2d234d1d1faa9288f45f..08240e498451a55810e4bd00a75df73d0c1a607e 100644 (file)
@@ -266,7 +266,7 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
        struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
        int err;
 
-       /* exit if we didnt initialize the driver yet */
+       /* exit if we didn't initialize the driver yet */
        if (!state->chip_id) {
                mxl_debug("driver not yet initialized, exit.");
                goto fail;
@@ -322,7 +322,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
        struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
        int err;
 
-       /* exit if we didnt initialize the driver yet */
+       /* exit if we didn't initialize the driver yet */
        if (!state->chip_id) {
                mxl_debug("driver not yet initialized, exit.");
                goto fail;
index 40832a1aef6c71c0df2eaf51ffdea327bafe18da..98d24aefb640f80e12d6dd720f872273c71e6276 100644 (file)
@@ -102,7 +102,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
        if (rxlen > 62) {
                err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
                                device_addr);
-               txlen = 62;
+               rxlen = 62;
        }
 
        b[0] = I2C_SPEED_100KHZ_BIT;
index fc5d60efd4abe99f19acbafff7b83879da5ff3ac..dd19c9ff76e0f9a159c6630320814c89e9e83d5a 100644 (file)
@@ -1664,8 +1664,8 @@ static int em28xx_v4l2_close(struct file *filp)
 
        em28xx_videodbg("users=%d\n", dev->users);
 
-       mutex_lock(&dev->lock);
        vb2_fop_release(filp);
+       mutex_lock(&dev->lock);
 
        if (dev->users == 1) {
                /* the device is already disconnect,
index cb1e64ca59c9259b59ca1aaaaea036b6bd2c5fa0..cea8d7f51c3cc9430af956066d87b045b453c062 100644 (file)
@@ -438,7 +438,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        s32 nToSkip =
                sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
 
-       /* Test only against 0202h, so endianess does not matter */
+       /* Test only against 0202h, so endianness does not matter */
        switch (*(s16 *) data) {
        case 0x0202:            /* End of frame, start a new one */
                gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
index cd79c180f67b87e84689a8a162b4962bf5691cde..07529e5a0c5605186b3aa619b6b89d06cf98bc45 100644 (file)
@@ -416,7 +416,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        int ret = -EINVAL;
 
index a9150964356329d93ea136e151c0d7f0aebf8590..2fd1c5e31a0f2692a1d59dd88c72cbee74e61054 100644 (file)
@@ -874,7 +874,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        int ret = -EINVAL;
        u8 data0, data1;
index 1fc80af2a18907e57d54eac3f58481ada0f3cda7..48234c9a8b6c3e4b4b927eb654ddb0009aa3d8ba 100644 (file)
@@ -361,6 +361,9 @@ static void stk1135_configure_clock(struct gspca_dev *gspca_dev)
 
        /* set serial interface clock divider (30MHz/0x1f*16+2) = 60240 kHz) */
        reg_w(gspca_dev, STK1135_REG_SICTL + 2, 0x1f);
+
+       /* wait a while for sensor to catch up */
+       udelay(1000);
 }
 
 static void stk1135_camera_disable(struct gspca_dev *gspca_dev)
index 9c0827631b9c105658575ed52e754fd1efa0c740..7f94ec74282e3ea42b0c423130419b038a5e3edd 100644 (file)
@@ -139,7 +139,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam = &gspca_dev->cam;
 
-       /* Give the camera some time to settle, otherwise initalization will
+       /* Give the camera some time to settle, otherwise initialization will
           fail on hotplug, and yes it really needs a full second. */
        msleep(1000);
 
index a517d185febed4590bbb5f58306aa4e4a2c4f0f1..46c9f2229a18675c6a1ca39528dab2196937c0c5 100644 (file)
@@ -1027,6 +1027,7 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
+       {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
index 7b95d8e88a20240305a8817b72c3459d80a5adc6..d3e1b6d8bf494f79d449c38c96be5d022ab61043 100644 (file)
@@ -6905,7 +6905,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        if (len == 8 && data[4] == 1) {
                input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
index 77bbf788965953bbc67f8fa8b3ab18ccbe5806d8..78c9bc8e7f561744364a6de94f4aeaae382dd077 100644 (file)
@@ -1039,7 +1039,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        /* Set the leds off */
        pwc_set_leds(pdev, 0, 0);
 
-       /* Setup intial videomode */
+       /* Setup initial videomode */
        rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
                                V4L2_PIX_FMT_YUV420, 30, &compression, 1);
        if (rc)
index 8a505a90d3189a59876a916507ae50b6e11a0ed9..6222a4ab1e00bfff2d58d7816145bdae58fe4059 100644 (file)
 #define USBTV_ISOC_TRANSFERS   16
 #define USBTV_ISOC_PACKETS     8
 
-#define USBTV_WIDTH            720
-#define USBTV_HEIGHT           480
-
 #define USBTV_CHUNK_SIZE       256
 #define USBTV_CHUNK            240
-#define USBTV_CHUNKS           (USBTV_WIDTH * USBTV_HEIGHT \
-                                       / 4 / USBTV_CHUNK)
 
 /* Chunk header. */
 #define USBTV_MAGIC_OK(chunk)  ((be32_to_cpu(chunk[0]) & 0xff000000) \
 #define USBTV_ODD(chunk)       ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15)
 #define USBTV_CHUNK_NO(chunk)  (be32_to_cpu(chunk[0]) & 0x00000fff)
 
+#define USBTV_TV_STD  (V4L2_STD_525_60 | V4L2_STD_PAL)
+
+/* parameters for supported TV norms */
+struct usbtv_norm_params {
+       v4l2_std_id norm;
+       int cap_width, cap_height;
+};
+
+static struct usbtv_norm_params norm_params[] = {
+       {
+               .norm = V4L2_STD_525_60,
+               .cap_width = 720,
+               .cap_height = 480,
+       },
+       {
+               .norm = V4L2_STD_PAL,
+               .cap_width = 720,
+               .cap_height = 576,
+       }
+};
+
 /* A single videobuf2 frame buffer. */
 struct usbtv_buf {
        struct vb2_buffer vb;
@@ -94,11 +110,38 @@ struct usbtv {
                USBTV_COMPOSITE_INPUT,
                USBTV_SVIDEO_INPUT,
        } input;
+       v4l2_std_id norm;
+       int width, height;
+       int n_chunks;
        int iso_size;
        unsigned int sequence;
        struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS];
 };
 
+static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm)
+{
+       int i, ret = 0;
+       struct usbtv_norm_params *params = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(norm_params); i++) {
+               if (norm_params[i].norm & norm) {
+                       params = &norm_params[i];
+                       break;
+               }
+       }
+
+       if (params) {
+               usbtv->width = params->cap_width;
+               usbtv->height = params->cap_height;
+               usbtv->n_chunks = usbtv->width * usbtv->height
+                                               / 4 / USBTV_CHUNK;
+               usbtv->norm = params->norm;
+       } else
+               ret = -EINVAL;
+
+       return ret;
+}
+
 static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
 {
        int ret;
@@ -158,6 +201,57 @@ static int usbtv_select_input(struct usbtv *usbtv, int input)
        return ret;
 }
 
+static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm)
+{
+       int ret;
+       static const u16 pal[][2] = {
+               { USBTV_BASE + 0x001a, 0x0068 },
+               { USBTV_BASE + 0x010e, 0x0072 },
+               { USBTV_BASE + 0x010f, 0x00a2 },
+               { USBTV_BASE + 0x0112, 0x00b0 },
+               { USBTV_BASE + 0x0117, 0x0001 },
+               { USBTV_BASE + 0x0118, 0x002c },
+               { USBTV_BASE + 0x012d, 0x0010 },
+               { USBTV_BASE + 0x012f, 0x0020 },
+               { USBTV_BASE + 0x024f, 0x0002 },
+               { USBTV_BASE + 0x0254, 0x0059 },
+               { USBTV_BASE + 0x025a, 0x0016 },
+               { USBTV_BASE + 0x025b, 0x0035 },
+               { USBTV_BASE + 0x0263, 0x0017 },
+               { USBTV_BASE + 0x0266, 0x0016 },
+               { USBTV_BASE + 0x0267, 0x0036 }
+       };
+
+       static const u16 ntsc[][2] = {
+               { USBTV_BASE + 0x001a, 0x0079 },
+               { USBTV_BASE + 0x010e, 0x0068 },
+               { USBTV_BASE + 0x010f, 0x009c },
+               { USBTV_BASE + 0x0112, 0x00f0 },
+               { USBTV_BASE + 0x0117, 0x0000 },
+               { USBTV_BASE + 0x0118, 0x00fc },
+               { USBTV_BASE + 0x012d, 0x0004 },
+               { USBTV_BASE + 0x012f, 0x0008 },
+               { USBTV_BASE + 0x024f, 0x0001 },
+               { USBTV_BASE + 0x0254, 0x005f },
+               { USBTV_BASE + 0x025a, 0x0012 },
+               { USBTV_BASE + 0x025b, 0x0001 },
+               { USBTV_BASE + 0x0263, 0x001c },
+               { USBTV_BASE + 0x0266, 0x0011 },
+               { USBTV_BASE + 0x0267, 0x0005 }
+       };
+
+       ret = usbtv_configure_for_norm(usbtv, norm);
+
+       if (!ret) {
+               if (norm & V4L2_STD_525_60)
+                       ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc));
+               else if (norm & V4L2_STD_PAL)
+                       ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal));
+       }
+
+       return ret;
+}
+
 static int usbtv_setup_capture(struct usbtv *usbtv)
 {
        int ret;
@@ -225,26 +319,11 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
 
                { USBTV_BASE + 0x0284, 0x0088 },
                { USBTV_BASE + 0x0003, 0x0004 },
-               { USBTV_BASE + 0x001a, 0x0079 },
                { USBTV_BASE + 0x0100, 0x00d3 },
-               { USBTV_BASE + 0x010e, 0x0068 },
-               { USBTV_BASE + 0x010f, 0x009c },
-               { USBTV_BASE + 0x0112, 0x00f0 },
                { USBTV_BASE + 0x0115, 0x0015 },
-               { USBTV_BASE + 0x0117, 0x0000 },
-               { USBTV_BASE + 0x0118, 0x00fc },
-               { USBTV_BASE + 0x012d, 0x0004 },
-               { USBTV_BASE + 0x012f, 0x0008 },
                { USBTV_BASE + 0x0220, 0x002e },
                { USBTV_BASE + 0x0225, 0x0008 },
                { USBTV_BASE + 0x024e, 0x0002 },
-               { USBTV_BASE + 0x024f, 0x0001 },
-               { USBTV_BASE + 0x0254, 0x005f },
-               { USBTV_BASE + 0x025a, 0x0012 },
-               { USBTV_BASE + 0x025b, 0x0001 },
-               { USBTV_BASE + 0x0263, 0x001c },
-               { USBTV_BASE + 0x0266, 0x0011 },
-               { USBTV_BASE + 0x0267, 0x0005 },
                { USBTV_BASE + 0x024e, 0x0002 },
                { USBTV_BASE + 0x024f, 0x0002 },
        };
@@ -253,6 +332,10 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
        if (ret)
                return ret;
 
+       ret = usbtv_select_norm(usbtv, usbtv->norm);
+       if (ret)
+               return ret;
+
        ret = usbtv_select_input(usbtv, usbtv->input);
        if (ret)
                return ret;
@@ -296,7 +379,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
        frame_id = USBTV_FRAME_ID(chunk);
        odd = USBTV_ODD(chunk);
        chunk_no = USBTV_CHUNK_NO(chunk);
-       if (chunk_no >= USBTV_CHUNKS)
+       if (chunk_no >= usbtv->n_chunks)
                return;
 
        /* Beginning of a frame. */
@@ -324,10 +407,10 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
        usbtv->chunks_done++;
 
        /* Last chunk in a frame, signalling an end */
-       if (odd && chunk_no == USBTV_CHUNKS-1) {
+       if (odd && chunk_no == usbtv->n_chunks-1) {
                int size = vb2_plane_size(&buf->vb, 0);
                enum vb2_buffer_state state = usbtv->chunks_done ==
-                                               USBTV_CHUNKS ?
+                                               usbtv->n_chunks ?
                                                VB2_BUF_STATE_DONE :
                                                VB2_BUF_STATE_ERROR;
 
@@ -500,6 +583,8 @@ static int usbtv_querycap(struct file *file, void *priv,
 static int usbtv_enum_input(struct file *file, void *priv,
                                        struct v4l2_input *i)
 {
+       struct usbtv *dev = video_drvdata(file);
+
        switch (i->index) {
        case USBTV_COMPOSITE_INPUT:
                strlcpy(i->name, "Composite", sizeof(i->name));
@@ -512,7 +597,7 @@ static int usbtv_enum_input(struct file *file, void *priv,
        }
 
        i->type = V4L2_INPUT_TYPE_CAMERA;
-       i->std = V4L2_STD_525_60;
+       i->std = dev->vdev.tvnorms;
        return 0;
 }
 
@@ -531,23 +616,37 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void  *priv,
 static int usbtv_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
-       f->fmt.pix.width = USBTV_WIDTH;
-       f->fmt.pix.height = USBTV_HEIGHT;
+       struct usbtv *usbtv = video_drvdata(file);
+
+       f->fmt.pix.width = usbtv->width;
+       f->fmt.pix.height = usbtv->height;
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.bytesperline = USBTV_WIDTH * 2;
+       f->fmt.pix.bytesperline = usbtv->width * 2;
        f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height);
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
+
        return 0;
 }
 
 static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-       *norm = V4L2_STD_525_60;
+       struct usbtv *usbtv = video_drvdata(file);
+       *norm = usbtv->norm;
        return 0;
 }
 
+static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
+{
+       int ret = -EINVAL;
+       struct usbtv *usbtv = video_drvdata(file);
+
+       if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL))
+               ret = usbtv_select_norm(usbtv, norm);
+
+       return ret;
+}
+
 static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
 {
        struct usbtv *usbtv = video_drvdata(file);
@@ -561,13 +660,6 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
        return usbtv_select_input(usbtv, i);
 }
 
-static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
-{
-       if (norm & V4L2_STD_525_60)
-               return 0;
-       return -EINVAL;
-}
-
 struct v4l2_ioctl_ops usbtv_ioctl_ops = {
        .vidioc_querycap = usbtv_querycap,
        .vidioc_enum_input = usbtv_enum_input,
@@ -604,10 +696,12 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
        const struct v4l2_format *v4l_fmt, unsigned int *nbuffers,
        unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
+       struct usbtv *usbtv = vb2_get_drv_priv(vq);
+
        if (*nbuffers < 2)
                *nbuffers = 2;
        *nplanes = 1;
-       sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
+       sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
 
        return 0;
 }
@@ -690,7 +784,11 @@ static int usbtv_probe(struct usb_interface *intf,
                return -ENOMEM;
        usbtv->dev = dev;
        usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
+
        usbtv->iso_size = size;
+
+       (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60);
+
        spin_lock_init(&usbtv->buflock);
        mutex_init(&usbtv->v4l2_lock);
        mutex_init(&usbtv->vb2q_lock);
@@ -727,7 +825,7 @@ static int usbtv_probe(struct usb_interface *intf,
        usbtv->vdev.release = video_device_release_empty;
        usbtv->vdev.fops = &usbtv_fops;
        usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops;
-       usbtv->vdev.tvnorms = V4L2_STD_525_60;
+       usbtv->vdev.tvnorms = USBTV_TV_STD;
        usbtv->vdev.queue = &usbtv->vb2q;
        usbtv->vdev.lock = &usbtv->v4l2_lock;
        set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
index 899cb6d1c4a4a74a68cae01dbea51de5befc821e..898c208889cd2d55dd5a22522a2d06340eb0891d 100644 (file)
@@ -556,7 +556,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
  *
  * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)   (1)
  *
- * to avoid loosing precision in the division. Similarly, the host timestamp is
+ * to avoid losing precision in the division. Similarly, the host timestamp is
  * computed with
  *
  * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1)       (2)
index 60dcc0f3b32e7b445352b455d377f5b2b794b4fb..fb46790d0eca795d5e411c54bf7129d96e61d3e9 100644 (file)
@@ -420,7 +420,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Advanced Simple",
                "Core",
                "Simple Scalable",
-               "Advanced Coding Efficency",
+               "Advanced Coding Efficiency",
                NULL,
        };
 
index b19b306c8f7f533d3112db441f692e57bd76638d..0edc165f418d9449f46e5696e4e093e7b3288fd1 100644 (file)
@@ -144,6 +144,25 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
                __vb2_plane_dmabuf_put(q, &vb->planes[plane]);
 }
 
+/**
+ * __setup_lengths() - setup initial lengths for every plane in
+ * every buffer on the queue
+ */
+static void __setup_lengths(struct vb2_queue *q, unsigned int n)
+{
+       unsigned int buffer, plane;
+       struct vb2_buffer *vb;
+
+       for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) {
+               vb = q->bufs[buffer];
+               if (!vb)
+                       continue;
+
+               for (plane = 0; plane < vb->num_planes; ++plane)
+                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+       }
+}
+
 /**
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
@@ -169,7 +188,6 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
                        continue;
 
                for (plane = 0; plane < vb->num_planes; ++plane) {
-                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
                        vb->v4l2_planes[plane].m.mem_offset = off;
 
                        dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
@@ -241,6 +259,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
                q->bufs[q->num_buffers + buffer] = vb;
        }
 
+       __setup_lengths(q, buffer);
        if (memory == V4L2_MEMORY_MMAP)
                __setup_offsets(q, buffer);
 
@@ -1824,8 +1843,8 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
                return -EINVAL;
        }
 
-       if (eb->flags & ~O_CLOEXEC) {
-               dprintk(1, "Queue does support only O_CLOEXEC flag\n");
+       if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
+               dprintk(1, "Queue does support only O_CLOEXEC and access mode flags\n");
                return -EINVAL;
        }
 
@@ -1848,14 +1867,14 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
 
        vb_plane = &vb->planes[eb->plane];
 
-       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
        if (IS_ERR_OR_NULL(dbuf)) {
                dprintk(1, "Failed to export buffer %d, plane %d\n",
                        eb->index, eb->plane);
                return -EINVAL;
        }
 
-       ret = dma_buf_fd(dbuf, eb->flags);
+       ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
        if (ret < 0) {
                dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
                        eb->index, eb->plane, ret);
index 646f08f4f504c05ae37dd95cbc1fe8333705e658..33d3871d1e131dce9a2f1d8392020dce5b8ff799 100644 (file)
@@ -393,7 +393,7 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
        return sgt;
 }
 
-static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
        struct vb2_dc_buf *buf = buf_priv;
        struct dma_buf *dbuf;
@@ -404,7 +404,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
        if (WARN_ON(!buf->sgt_base))
                return NULL;
 
-       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags);
        if (IS_ERR(dbuf))
                return NULL;
 
index 2f860543912cd1c3f5dd4f286705b2c8b208dc37..0d3a8ffe47a3c15efc27faef3712f682e6a7f620 100644 (file)
@@ -178,7 +178,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
        buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
                             GFP_KERNEL);
        if (!buf->pages)
-               return NULL;
+               goto userptr_fail_alloc_pages;
 
        num_pages_from_user = get_user_pages(current, current->mm,
                                             vaddr & PAGE_MASK,
@@ -204,6 +204,7 @@ userptr_fail_get_user_pages:
        while (--num_pages_from_user >= 0)
                put_page(buf->pages[num_pages_from_user]);
        kfree(buf->pages);
+userptr_fail_alloc_pages:
        kfree(buf);
        return NULL;
 }
index 62a60caa5d1fe7eb583cb208fef9b96a5b0dd8f0..dd671582c9a1b2dcf8286b2a798a65e6621752ba 100644 (file)
@@ -32,7 +32,7 @@ config MFD_AS3722
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
-       depends on I2C && OF
+       depends on I2C=y && OF
        help
          The ams AS3722 is a compact system PMU suitable for mobile phones,
          tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down
index da1c6566d93d2f755878d358a018835bd7cd1454..37edf9e989b066cbb1a8a667001ce4e655ac7c1c 100644 (file)
@@ -506,7 +506,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
                .iTCO_version = 2,
        },
        [LPC_WPT_LP] = {
-               .name = "Lynx Point_LP",
+               .name = "Wildcat Point_LP",
                .iTCO_version = 2,
        },
 };
index 34c18fb8c0896b46f49de48b4d5631a5d780a811..54cc25546592c7c7a1ba113104ca96fa5cacab83 100644 (file)
@@ -81,31 +81,31 @@ static struct of_device_id sec_dt_match[] = {
 
 int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest)
 {
-       return regmap_read(sec_pmic->regmap, reg, dest);
+       return regmap_read(sec_pmic->regmap_pmic, reg, dest);
 }
 EXPORT_SYMBOL_GPL(sec_reg_read);
 
 int sec_bulk_read(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf)
 {
-       return regmap_bulk_read(sec_pmic->regmap, reg, buf, count);
+       return regmap_bulk_read(sec_pmic->regmap_pmic, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(sec_bulk_read);
 
 int sec_reg_write(struct sec_pmic_dev *sec_pmic, u8 reg, u8 value)
 {
-       return regmap_write(sec_pmic->regmap, reg, value);
+       return regmap_write(sec_pmic->regmap_pmic, reg, value);
 }
 EXPORT_SYMBOL_GPL(sec_reg_write);
 
 int sec_bulk_write(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf)
 {
-       return regmap_raw_write(sec_pmic->regmap, reg, buf, count);
+       return regmap_raw_write(sec_pmic->regmap_pmic, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(sec_bulk_write);
 
 int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask)
 {
-       return regmap_update_bits(sec_pmic->regmap, reg, mask, val);
+       return regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(sec_reg_update);
 
@@ -166,6 +166,11 @@ static struct regmap_config s5m8767_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_config sec_rtc_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
 #ifdef CONFIG_OF
 /*
  * Only the common platform data elements for s5m8767 are parsed here from the
@@ -266,9 +271,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                break;
        }
 
-       sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap);
-       if (IS_ERR(sec_pmic->regmap)) {
-               ret = PTR_ERR(sec_pmic->regmap);
+       sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);
+       if (IS_ERR(sec_pmic->regmap_pmic)) {
+               ret = PTR_ERR(sec_pmic->regmap_pmic);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
                        ret);
                return ret;
@@ -277,6 +282,15 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
        i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
 
+       sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc,
+                       &sec_rtc_regmap_config);
+       if (IS_ERR(sec_pmic->regmap_rtc)) {
+               ret = PTR_ERR(sec_pmic->regmap_rtc);
+               dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
+                       ret);
+               return ret;
+       }
+
        if (pdata && pdata->cfg_pmic_irq)
                pdata->cfg_pmic_irq();
 
index 0dd84e99081e9d30539ab96cccc255591a18be82..b441b1be27cbe9165bd66f94e26c9f750125e665 100644 (file)
@@ -280,19 +280,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 
        switch (type) {
        case S5M8763X:
-               ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
+               ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                  sec_pmic->irq_base, &s5m8763_irq_chip,
                                  &sec_pmic->irq_data);
                break;
        case S5M8767X:
-               ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
+               ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                  sec_pmic->irq_base, &s5m8767_irq_chip,
                                  &sec_pmic->irq_data);
                break;
        case S2MPS11X:
-               ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
+               ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                  sec_pmic->irq_base, &s2mps11_irq_chip,
                                  &sec_pmic->irq_data);
index 71e3e0c5bf730c7e8f3423619d9a2e2acc6fa27d..a5424579679cfcd7e0b835964557ea1188c58eaa 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/sched.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/ti_ssp.h>
 
@@ -409,7 +410,6 @@ static int ti_ssp_probe(struct platform_device *pdev)
                cells[id].id            = id;
                cells[id].name          = data->dev_name;
                cells[id].platform_data = data->pdata;
-               cells[id].data_size     = data->pdata_size;
        }
 
        error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
index 29473c2c95ae0d92aa75184199486f70bdf5fc53..6ef7685a4cf8b346c129403c8155ada7f144d237 100644 (file)
@@ -47,6 +47,9 @@
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
 
+/* Register descriptions for audio */
+#include <linux/mfd/twl4030-audio.h>
+
 #include "twl-core.h"
 
 /*
@@ -200,6 +203,105 @@ static struct twl_mapping twl4030_map[] = {
        { 2, TWL5031_BASEADD_INTERRUPTS },
 };
 
+static struct reg_default twl4030_49_defaults[] = {
+       /* Audio Registers */
+       { 0x01, 0x00}, /* CODEC_MODE    */
+       { 0x02, 0x00}, /* OPTION        */
+       /* 0x03  Unused */
+       { 0x04, 0x00}, /* MICBIAS_CTL   */
+       { 0x05, 0x00}, /* ANAMICL       */
+       { 0x06, 0x00}, /* ANAMICR       */
+       { 0x07, 0x00}, /* AVADC_CTL     */
+       { 0x08, 0x00}, /* ADCMICSEL     */
+       { 0x09, 0x00}, /* DIGMIXING     */
+       { 0x0a, 0x0f}, /* ATXL1PGA      */
+       { 0x0b, 0x0f}, /* ATXR1PGA      */
+       { 0x0c, 0x0f}, /* AVTXL2PGA     */
+       { 0x0d, 0x0f}, /* AVTXR2PGA     */
+       { 0x0e, 0x00}, /* AUDIO_IF      */
+       { 0x0f, 0x00}, /* VOICE_IF      */
+       { 0x10, 0x3f}, /* ARXR1PGA      */
+       { 0x11, 0x3f}, /* ARXL1PGA      */
+       { 0x12, 0x3f}, /* ARXR2PGA      */
+       { 0x13, 0x3f}, /* ARXL2PGA      */
+       { 0x14, 0x25}, /* VRXPGA        */
+       { 0x15, 0x00}, /* VSTPGA        */
+       { 0x16, 0x00}, /* VRX2ARXPGA    */
+       { 0x17, 0x00}, /* AVDAC_CTL     */
+       { 0x18, 0x00}, /* ARX2VTXPGA    */
+       { 0x19, 0x32}, /* ARXL1_APGA_CTL*/
+       { 0x1a, 0x32}, /* ARXR1_APGA_CTL*/
+       { 0x1b, 0x32}, /* ARXL2_APGA_CTL*/
+       { 0x1c, 0x32}, /* ARXR2_APGA_CTL*/
+       { 0x1d, 0x00}, /* ATX2ARXPGA    */
+       { 0x1e, 0x00}, /* BT_IF         */
+       { 0x1f, 0x55}, /* BTPGA         */
+       { 0x20, 0x00}, /* BTSTPGA       */
+       { 0x21, 0x00}, /* EAR_CTL       */
+       { 0x22, 0x00}, /* HS_SEL        */
+       { 0x23, 0x00}, /* HS_GAIN_SET   */
+       { 0x24, 0x00}, /* HS_POPN_SET   */
+       { 0x25, 0x00}, /* PREDL_CTL     */
+       { 0x26, 0x00}, /* PREDR_CTL     */
+       { 0x27, 0x00}, /* PRECKL_CTL    */
+       { 0x28, 0x00}, /* PRECKR_CTL    */
+       { 0x29, 0x00}, /* HFL_CTL       */
+       { 0x2a, 0x00}, /* HFR_CTL       */
+       { 0x2b, 0x05}, /* ALC_CTL       */
+       { 0x2c, 0x00}, /* ALC_SET1      */
+       { 0x2d, 0x00}, /* ALC_SET2      */
+       { 0x2e, 0x00}, /* BOOST_CTL     */
+       { 0x2f, 0x00}, /* SOFTVOL_CTL   */
+       { 0x30, 0x13}, /* DTMF_FREQSEL  */
+       { 0x31, 0x00}, /* DTMF_TONEXT1H */
+       { 0x32, 0x00}, /* DTMF_TONEXT1L */
+       { 0x33, 0x00}, /* DTMF_TONEXT2H */
+       { 0x34, 0x00}, /* DTMF_TONEXT2L */
+       { 0x35, 0x79}, /* DTMF_TONOFF   */
+       { 0x36, 0x11}, /* DTMF_WANONOFF */
+       { 0x37, 0x00}, /* I2S_RX_SCRAMBLE_H */
+       { 0x38, 0x00}, /* I2S_RX_SCRAMBLE_M */
+       { 0x39, 0x00}, /* I2S_RX_SCRAMBLE_L */
+       { 0x3a, 0x06}, /* APLL_CTL */
+       { 0x3b, 0x00}, /* DTMF_CTL */
+       { 0x3c, 0x44}, /* DTMF_PGA_CTL2 (0x3C) */
+       { 0x3d, 0x69}, /* DTMF_PGA_CTL1 (0x3D) */
+       { 0x3e, 0x00}, /* MISC_SET_1 */
+       { 0x3f, 0x00}, /* PCMBTMUX */
+       /* 0x40 - 0x42  Unused */
+       { 0x43, 0x00}, /* RX_PATH_SEL */
+       { 0x44, 0x32}, /* VDL_APGA_CTL */
+       { 0x45, 0x00}, /* VIBRA_CTL */
+       { 0x46, 0x00}, /* VIBRA_SET */
+       { 0x47, 0x00}, /* VIBRA_PWM_SET */
+       { 0x48, 0x00}, /* ANAMIC_GAIN   */
+       { 0x49, 0x00}, /* MISC_SET_2    */
+       /* End of Audio Registers */
+};
+
+static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case 0:
+       case 3:
+       case 40:
+       case 41:
+       case 42:
+               return false;
+       default:
+               return true;
+       }
+}
+
+static const struct regmap_range twl4030_49_volatile_ranges[] = {
+       regmap_reg_range(TWL4030_BASEADD_TEST, 0xff),
+};
+
+static const struct regmap_access_table twl4030_49_volatile_table = {
+       .yes_ranges = twl4030_49_volatile_ranges,
+       .n_yes_ranges = ARRAY_SIZE(twl4030_49_volatile_ranges),
+};
+
 static struct regmap_config twl4030_regmap_config[4] = {
        {
                /* Address 0x48 */
@@ -212,6 +314,15 @@ static struct regmap_config twl4030_regmap_config[4] = {
                .reg_bits = 8,
                .val_bits = 8,
                .max_register = 0xff,
+
+               .readable_reg = twl4030_49_nop_reg,
+               .writeable_reg = twl4030_49_nop_reg,
+
+               .volatile_table = &twl4030_49_volatile_table,
+
+               .reg_defaults = twl4030_49_defaults,
+               .num_reg_defaults = ARRAY_SIZE(twl4030_49_defaults),
+               .cache_type = REGCACHE_RBTREE,
        },
        {
                /* Address 0x4a */
@@ -302,35 +413,50 @@ unsigned int twl_rev(void)
 EXPORT_SYMBOL(twl_rev);
 
 /**
- * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
+ * twl_get_regmap - Get the regmap associated with the given module
  * @mod_no: module number
- * @value: an array of num_bytes+1 containing data to write
- * @reg: register address (just offset will do)
- * @num_bytes: number of bytes to transfer
  *
- * Returns the result of operation - 0 is success
+ * Returns the regmap pointer or NULL in case of failure.
  */
-int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
+static struct regmap *twl_get_regmap(u8 mod_no)
 {
-       int ret;
        int sid;
        struct twl_client *twl;
 
        if (unlikely(!twl_priv || !twl_priv->ready)) {
                pr_err("%s: not initialized\n", DRIVER_NAME);
-               return -EPERM;
+               return NULL;
        }
        if (unlikely(mod_no >= twl_get_last_module())) {
                pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
-               return -EPERM;
+               return NULL;
        }
 
        sid = twl_priv->twl_map[mod_no].sid;
        twl = &twl_priv->twl_modules[sid];
 
-       ret = regmap_bulk_write(twl->regmap,
-                               twl_priv->twl_map[mod_no].base + reg, value,
-                               num_bytes);
+       return twl->regmap;
+}
+
+/**
+ * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0
+ * @mod_no: module number
+ * @value: an array of num_bytes+1 containing data to write
+ * @reg: register address (just offset will do)
+ * @num_bytes: number of bytes to transfer
+ *
+ * Returns the result of operation - 0 is success
+ */
+int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
+{
+       struct regmap *regmap = twl_get_regmap(mod_no);
+       int ret;
+
+       if (!regmap)
+               return -EPERM;
+
+       ret = regmap_bulk_write(regmap, twl_priv->twl_map[mod_no].base + reg,
+                               value, num_bytes);
 
        if (ret)
                pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
@@ -351,25 +477,14 @@ EXPORT_SYMBOL(twl_i2c_write);
  */
 int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
 {
+       struct regmap *regmap = twl_get_regmap(mod_no);
        int ret;
-       int sid;
-       struct twl_client *twl;
 
-       if (unlikely(!twl_priv || !twl_priv->ready)) {
-               pr_err("%s: not initialized\n", DRIVER_NAME);
-               return -EPERM;
-       }
-       if (unlikely(mod_no >= twl_get_last_module())) {
-               pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
+       if (!regmap)
                return -EPERM;
-       }
-
-       sid = twl_priv->twl_map[mod_no].sid;
-       twl = &twl_priv->twl_modules[sid];
 
-       ret = regmap_bulk_read(twl->regmap,
-                              twl_priv->twl_map[mod_no].base + reg, value,
-                              num_bytes);
+       ret = regmap_bulk_read(regmap, twl_priv->twl_map[mod_no].base + reg,
+                              value, num_bytes);
 
        if (ret)
                pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n",
@@ -379,6 +494,27 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
 }
 EXPORT_SYMBOL(twl_i2c_read);
 
+/**
+ * twl_regcache_bypass - Configure the regcache bypass for the regmap associated
+ *                      with the module
+ * @mod_no: module number
+ * @enable: Regcache bypass state
+ *
+ * Returns 0 else failure.
+ */
+int twl_set_regcache_bypass(u8 mod_no, bool enable)
+{
+       struct regmap *regmap = twl_get_regmap(mod_no);
+
+       if (!regmap)
+               return -EPERM;
+
+       regcache_cache_bypass(regmap, enable);
+
+       return 0;
+}
+EXPORT_SYMBOL(twl_set_regcache_bypass);
+
 /*----------------------------------------------------------------------*/
 
 /**
index 0779d5ab9ab1538631981aff4994743a5b96b008..51b6df1a794974664f03471aa94bc00e9837b330 100644 (file)
 #define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
 #define TWL6040_NUM_SUPPLIES   (2)
 
+static struct reg_default twl6040_defaults[] = {
+       { 0x01, 0x4B }, /* REG_ASICID   (ro) */
+       { 0x02, 0x00 }, /* REG_ASICREV  (ro) */
+       { 0x03, 0x00 }, /* REG_INTID    */
+       { 0x04, 0x00 }, /* REG_INTMR    */
+       { 0x05, 0x00 }, /* REG_NCPCTRL  */
+       { 0x06, 0x00 }, /* REG_LDOCTL   */
+       { 0x07, 0x60 }, /* REG_HPPLLCTL */
+       { 0x08, 0x00 }, /* REG_LPPLLCTL */
+       { 0x09, 0x4A }, /* REG_LPPLLDIV */
+       { 0x0A, 0x00 }, /* REG_AMICBCTL */
+       { 0x0B, 0x00 }, /* REG_DMICBCTL */
+       { 0x0C, 0x00 }, /* REG_MICLCTL  */
+       { 0x0D, 0x00 }, /* REG_MICRCTL  */
+       { 0x0E, 0x00 }, /* REG_MICGAIN  */
+       { 0x0F, 0x1B }, /* REG_LINEGAIN */
+       { 0x10, 0x00 }, /* REG_HSLCTL   */
+       { 0x11, 0x00 }, /* REG_HSRCTL   */
+       { 0x12, 0x00 }, /* REG_HSGAIN   */
+       { 0x13, 0x00 }, /* REG_EARCTL   */
+       { 0x14, 0x00 }, /* REG_HFLCTL   */
+       { 0x15, 0x00 }, /* REG_HFLGAIN  */
+       { 0x16, 0x00 }, /* REG_HFRCTL   */
+       { 0x17, 0x00 }, /* REG_HFRGAIN  */
+       { 0x18, 0x00 }, /* REG_VIBCTLL  */
+       { 0x19, 0x00 }, /* REG_VIBDATL  */
+       { 0x1A, 0x00 }, /* REG_VIBCTLR  */
+       { 0x1B, 0x00 }, /* REG_VIBDATR  */
+       { 0x1C, 0x00 }, /* REG_HKCTL1   */
+       { 0x1D, 0x00 }, /* REG_HKCTL2   */
+       { 0x1E, 0x00 }, /* REG_GPOCTL   */
+       { 0x1F, 0x00 }, /* REG_ALB      */
+       { 0x20, 0x00 }, /* REG_DLB      */
+       /* 0x28, REG_TRIM1 */
+       /* 0x29, REG_TRIM2 */
+       /* 0x2A, REG_TRIM3 */
+       /* 0x2B, REG_HSOTRIM */
+       /* 0x2C, REG_HFOTRIM */
+       { 0x2D, 0x08 }, /* REG_ACCCTL   */
+       { 0x2E, 0x00 }, /* REG_STATUS   (ro) */
+};
+
+struct reg_default twl6040_patch[] = {
+       /* Select I2C bus access to dual access registers */
+       { TWL6040_REG_ACCCTL, 0x09 },
+};
+
+
 static bool twl6040_has_vibra(struct device_node *node)
 {
 #ifdef CONFIG_OF
@@ -238,6 +286,9 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                if (twl6040->power_count++)
                        goto out;
 
+               /* Allow writes to the chip */
+               regcache_cache_only(twl6040->regmap, false);
+
                if (gpio_is_valid(twl6040->audpwron)) {
                        /* use automatic power-up sequence */
                        ret = twl6040_power_up_automatic(twl6040);
@@ -253,6 +304,10 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                                goto out;
                        }
                }
+
+               /* Sync with the HW */
+               regcache_sync(twl6040->regmap);
+
                /* Default PLL configuration after power up */
                twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
                twl6040->sysclk = 19200000;
@@ -279,6 +334,11 @@ int twl6040_power(struct twl6040 *twl6040, int on)
                        /* use manual power-down sequence */
                        twl6040_power_down_manual(twl6040);
                }
+
+               /* Set regmap to cache only and mark it as dirty */
+               regcache_cache_only(twl6040->regmap, true);
+               regcache_mark_dirty(twl6040->regmap);
+
                twl6040->sysclk = 0;
                twl6040->mclk = 0;
        }
@@ -490,9 +550,24 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
 static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
-       case TWL6040_REG_VIBCTLL:
-       case TWL6040_REG_VIBCTLR:
-       case TWL6040_REG_INTMR:
+       case TWL6040_REG_ASICID:
+       case TWL6040_REG_ASICREV:
+       case TWL6040_REG_INTID:
+       case TWL6040_REG_LPPLLCTL:
+       case TWL6040_REG_HPPLLCTL:
+       case TWL6040_REG_STATUS:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool twl6040_writeable_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case TWL6040_REG_ASICID:
+       case TWL6040_REG_ASICREV:
+       case TWL6040_REG_STATUS:
                return false;
        default:
                return true;
@@ -502,10 +577,15 @@ static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
 static struct regmap_config twl6040_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
+
+       .reg_defaults = twl6040_defaults,
+       .num_reg_defaults = ARRAY_SIZE(twl6040_defaults),
+
        .max_register = TWL6040_REG_STATUS, /* 0x2e */
 
        .readable_reg = twl6040_readable_reg,
        .volatile_reg = twl6040_volatile_reg,
+       .writeable_reg = twl6040_writeable_reg,
 
        .cache_type = REGCACHE_RBTREE,
 };
@@ -624,6 +704,8 @@ static int twl6040_probe(struct i2c_client *client,
 
        /* dual-access registers controlled by I2C only */
        twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
+       regmap_register_patch(twl6040->regmap, twl6040_patch,
+                             ARRAY_SIZE(twl6040_patch));
 
        /*
         * The main functionality of twl6040 to provide audio on OMAP4+ systems.
@@ -656,6 +738,10 @@ static int twl6040_probe(struct i2c_client *client,
        cell->name = "twl6040-gpo";
        children++;
 
+       /* The chip is powered down so mark regmap to cache only and dirty */
+       regcache_cache_only(twl6040->regmap, true);
+       regcache_mark_dirty(twl6040->regmap);
+
        ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
                              NULL, 0, NULL);
        if (ret)
index bf8b3b5ad1fe65d03eb067881599c5cbc1418a32..4a4432eb499cac6debaf6c09685ffc670dda90dd 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/mfd/arizona/core.h>
 #include <linux/mfd/arizona/registers.h>
+#include <linux/device.h>
 
 #include "arizona.h"
 
@@ -524,6 +525,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000300, 0x0000 },    /* R768   - Input Enables */
        { 0x00000308, 0x0000 },    /* R776   - Input Rate */
        { 0x00000309, 0x0022 },    /* R777   - Input Volume Ramp */
+       { 0x0000030C, 0x0002 },    /* R780   - HPF Control */
        { 0x00000310, 0x2080 },    /* R784   - IN1L Control */
        { 0x00000311, 0x0180 },    /* R785   - ADC Digital Volume 1L */
        { 0x00000312, 0x0000 },    /* R786   - DMIC1L Control */
@@ -545,6 +547,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000328, 0x2000 },    /* R808   - IN4L Control */
        { 0x00000329, 0x0180 },    /* R809   - ADC Digital Volume 4L */
        { 0x0000032A, 0x0000 },    /* R810   - DMIC4L Control */
+       { 0x0000032C, 0x0000 },    /* R812   - IN4R Control */
        { 0x0000032D, 0x0180 },    /* R813   - ADC Digital Volume 4R */
        { 0x0000032E, 0x0000 },    /* R814   - DMIC4R Control */
        { 0x00000400, 0x0000 },    /* R1024  - Output Enables 1 */
@@ -598,6 +601,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x0000043D, 0x0180 },    /* R1085  - DAC Digital Volume 6R */
        { 0x0000043E, 0x0080 },    /* R1086  - DAC Volume Limit 6R */
        { 0x0000043F, 0x0800 },    /* R1087  - Noise Gate Select 6R */
+       { 0x00000440, 0x8FFF },    /* R1088  - DRE Enable */
        { 0x00000450, 0x0000 },    /* R1104  - DAC AEC Control 1 */
        { 0x00000458, 0x0000 },    /* R1112  - Noise Gate Control */
        { 0x00000480, 0x0040 },    /* R1152  - Class W ANC Threshold 1 */
@@ -606,6 +610,9 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000491, 0x0000 },    /* R1169  - PDM SPK1 CTRL 2 */
        { 0x00000492, 0x0069 },    /* R1170  - PDM SPK2 CTRL 1 */
        { 0x00000493, 0x0000 },    /* R1171  - PDM SPK2 CTRL 2 */
+       { 0x000004A0, 0x3480 },    /* R1184  - HP1 Short Circuit Ctrl */
+       { 0x000004A1, 0x3480 },    /* R1185  - HP2 Short Circuit Ctrl */
+       { 0x000004A2, 0x3480 },    /* R1186  - HP3 Short Circuit Ctrl */
        { 0x00000500, 0x000C },    /* R1280  - AIF1 BCLK Ctrl */
        { 0x00000501, 0x0008 },    /* R1281  - AIF1 Tx Pin Ctrl */
        { 0x00000502, 0x0000 },    /* R1282  - AIF1 Rx Pin Ctrl */
@@ -882,6 +889,38 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x0000074D, 0x0080 },    /* R1869  - AIF2TX2MIX Input 3 Volume */
        { 0x0000074E, 0x0000 },    /* R1870  - AIF2TX2MIX Input 4 Source */
        { 0x0000074F, 0x0080 },    /* R1871  - AIF2TX2MIX Input 4 Volume */
+       { 0x00000750, 0x0000 },    /* R1872  - AIF2TX3MIX Input 1 Source */
+       { 0x00000751, 0x0080 },    /* R1873  - AIF2TX3MIX Input 1 Volume */
+       { 0x00000752, 0x0000 },    /* R1874  - AIF2TX3MIX Input 2 Source */
+       { 0x00000753, 0x0080 },    /* R1875  - AIF2TX3MIX Input 2 Volume */
+       { 0x00000754, 0x0000 },    /* R1876  - AIF2TX3MIX Input 3 Source */
+       { 0x00000755, 0x0080 },    /* R1877  - AIF2TX3MIX Input 3 Volume */
+       { 0x00000756, 0x0000 },    /* R1878  - AIF2TX3MIX Input 4 Source */
+       { 0x00000757, 0x0080 },    /* R1879  - AIF2TX3MIX Input 4 Volume */
+       { 0x00000758, 0x0000 },    /* R1880  - AIF2TX4MIX Input 1 Source */
+       { 0x00000759, 0x0080 },    /* R1881  - AIF2TX4MIX Input 1 Volume */
+       { 0x0000075A, 0x0000 },    /* R1882  - AIF2TX4MIX Input 2 Source */
+       { 0x0000075B, 0x0080 },    /* R1883  - AIF2TX4MIX Input 2 Volume */
+       { 0x0000075C, 0x0000 },    /* R1884  - AIF2TX4MIX Input 3 Source */
+       { 0x0000075D, 0x0080 },    /* R1885  - AIF2TX4MIX Input 3 Volume */
+       { 0x0000075E, 0x0000 },    /* R1886  - AIF2TX4MIX Input 4 Source */
+       { 0x0000075F, 0x0080 },    /* R1887  - AIF2TX4MIX Input 4 Volume */
+       { 0x00000760, 0x0000 },    /* R1888  - AIF2TX5MIX Input 1 Source */
+       { 0x00000761, 0x0080 },    /* R1889  - AIF2TX5MIX Input 1 Volume */
+       { 0x00000762, 0x0000 },    /* R1890  - AIF2TX5MIX Input 2 Source */
+       { 0x00000763, 0x0080 },    /* R1891  - AIF2TX5MIX Input 2 Volume */
+       { 0x00000764, 0x0000 },    /* R1892  - AIF2TX5MIX Input 3 Source */
+       { 0x00000765, 0x0080 },    /* R1893  - AIF2TX5MIX Input 3 Volume */
+       { 0x00000766, 0x0000 },    /* R1894  - AIF2TX5MIX Input 4 Source */
+       { 0x00000767, 0x0080 },    /* R1895  - AIF2TX5MIX Input 4 Volume */
+       { 0x00000768, 0x0000 },    /* R1896  - AIF2TX6MIX Input 1 Source */
+       { 0x00000769, 0x0080 },    /* R1897  - AIF2TX6MIX Input 1 Volume */
+       { 0x0000076A, 0x0000 },    /* R1898  - AIF2TX6MIX Input 2 Source */
+       { 0x0000076B, 0x0080 },    /* R1899  - AIF2TX6MIX Input 2 Volume */
+       { 0x0000076C, 0x0000 },    /* R1900  - AIF2TX6MIX Input 3 Source */
+       { 0x0000076D, 0x0080 },    /* R1901  - AIF2TX6MIX Input 3 Volume */
+       { 0x0000076E, 0x0000 },    /* R1902  - AIF2TX6MIX Input 4 Source */
+       { 0x0000076F, 0x0080 },    /* R1903  - AIF2TX6MIX Input 4 Volume */
        { 0x00000780, 0x0000 },    /* R1920  - AIF3TX1MIX Input 1 Source */
        { 0x00000781, 0x0080 },    /* R1921  - AIF3TX1MIX Input 1 Volume */
        { 0x00000782, 0x0000 },    /* R1922  - AIF3TX1MIX Input 2 Source */
@@ -1342,6 +1381,64 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00001404, 0x0000 },    /* R5124  - DSP4 Status 1 */
 };
 
+static bool wm5110_is_rev_b_adsp_memory(unsigned int reg)
+{
+       if ((reg >= 0x100000 && reg < 0x103000) ||
+           (reg >= 0x180000 && reg < 0x181000) ||
+           (reg >= 0x190000 && reg < 0x192000) ||
+           (reg >= 0x1a8000 && reg < 0x1a9000) ||
+           (reg >= 0x200000 && reg < 0x209000) ||
+           (reg >= 0x280000 && reg < 0x281000) ||
+           (reg >= 0x290000 && reg < 0x29a000) ||
+           (reg >= 0x2a8000 && reg < 0x2aa000) ||
+           (reg >= 0x300000 && reg < 0x30f000) ||
+           (reg >= 0x380000 && reg < 0x382000) ||
+           (reg >= 0x390000 && reg < 0x39e000) ||
+           (reg >= 0x3a8000 && reg < 0x3b6000) ||
+           (reg >= 0x400000 && reg < 0x403000) ||
+           (reg >= 0x480000 && reg < 0x481000) ||
+           (reg >= 0x490000 && reg < 0x492000) ||
+           (reg >= 0x4a8000 && reg < 0x4a9000))
+               return true;
+       else
+               return false;
+}
+
+static bool wm5110_is_rev_d_adsp_memory(unsigned int reg)
+{
+       if ((reg >= 0x100000 && reg < 0x106000) ||
+           (reg >= 0x180000 && reg < 0x182000) ||
+           (reg >= 0x190000 && reg < 0x198000) ||
+           (reg >= 0x1a8000 && reg < 0x1aa000) ||
+           (reg >= 0x200000 && reg < 0x20f000) ||
+           (reg >= 0x280000 && reg < 0x282000) ||
+           (reg >= 0x290000 && reg < 0x29c000) ||
+           (reg >= 0x2a6000 && reg < 0x2b4000) ||
+           (reg >= 0x300000 && reg < 0x30f000) ||
+           (reg >= 0x380000 && reg < 0x382000) ||
+           (reg >= 0x390000 && reg < 0x3a2000) ||
+           (reg >= 0x3a6000 && reg < 0x3b4000) ||
+           (reg >= 0x400000 && reg < 0x406000) ||
+           (reg >= 0x480000 && reg < 0x482000) ||
+           (reg >= 0x490000 && reg < 0x498000) ||
+           (reg >= 0x4a8000 && reg < 0x4aa000))
+               return true;
+       else
+               return false;
+}
+
+static bool wm5110_is_adsp_memory(struct device *dev, unsigned int reg)
+{
+       struct arizona *arizona = dev_get_drvdata(dev);
+
+       switch (arizona->rev) {
+       case 0 ... 2:
+               return wm5110_is_rev_b_adsp_memory(reg);
+       default:
+               return wm5110_is_rev_d_adsp_memory(reg);
+       }
+}
+
 static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -1460,6 +1557,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_INPUT_ENABLES_STATUS:
        case ARIZONA_INPUT_RATE:
        case ARIZONA_INPUT_VOLUME_RAMP:
+       case ARIZONA_HPF_CONTROL:
        case ARIZONA_IN1L_CONTROL:
        case ARIZONA_ADC_DIGITAL_VOLUME_1L:
        case ARIZONA_DMIC1L_CONTROL:
@@ -1481,6 +1579,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_IN4L_CONTROL:
        case ARIZONA_ADC_DIGITAL_VOLUME_4L:
        case ARIZONA_DMIC4L_CONTROL:
+       case ARIZONA_IN4R_CONTROL:
        case ARIZONA_ADC_DIGITAL_VOLUME_4R:
        case ARIZONA_DMIC4R_CONTROL:
        case ARIZONA_OUTPUT_ENABLES_1:
@@ -1536,12 +1635,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DAC_DIGITAL_VOLUME_6R:
        case ARIZONA_DAC_VOLUME_LIMIT_6R:
        case ARIZONA_NOISE_GATE_SELECT_6R:
+       case ARIZONA_DRE_ENABLE:
        case ARIZONA_DAC_AEC_CONTROL_1:
        case ARIZONA_NOISE_GATE_CONTROL:
        case ARIZONA_PDM_SPK1_CTRL_1:
        case ARIZONA_PDM_SPK1_CTRL_2:
        case ARIZONA_PDM_SPK2_CTRL_1:
        case ARIZONA_PDM_SPK2_CTRL_2:
+       case ARIZONA_HP1_SHORT_CIRCUIT_CTRL:
+       case ARIZONA_HP2_SHORT_CIRCUIT_CTRL:
+       case ARIZONA_HP3_SHORT_CIRCUIT_CTRL:
        case ARIZONA_AIF1_BCLK_CTRL:
        case ARIZONA_AIF1_TX_PIN_CTRL:
        case ARIZONA_AIF1_RX_PIN_CTRL:
@@ -1820,6 +1923,38 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME:
        case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE:
        case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME:
        case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE:
        case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME:
        case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE:
@@ -2331,7 +2466,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP4_SCRATCH_3:
                return true;
        default:
-               return false;
+               return wm5110_is_adsp_memory(dev, reg);
        }
 }
 
@@ -2407,16 +2542,18 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP4_SCRATCH_3:
                return true;
        default:
-               return false;
+               return wm5110_is_adsp_memory(dev, reg);
        }
 }
 
+#define WM5110_MAX_REGISTER 0x4a9fff
+
 const struct regmap_config wm5110_spi_regmap = {
        .reg_bits = 32,
        .pad_bits = 16,
        .val_bits = 16,
 
-       .max_register = ARIZONA_DSP1_STATUS_2,
+       .max_register = WM5110_MAX_REGISTER,
        .readable_reg = wm5110_readable_register,
        .volatile_reg = wm5110_volatile_register,
 
@@ -2430,7 +2567,7 @@ const struct regmap_config wm5110_i2c_regmap = {
        .reg_bits = 32,
        .val_bits = 16,
 
-       .max_register = ARIZONA_DSP1_STATUS_2,
+       .max_register = WM5110_MAX_REGISTER,
        .readable_reg = wm5110_readable_register,
        .volatile_reg = wm5110_volatile_register,
 
index 0e8df41aaf144c7a00818bb95959a58060c99efe..2cf2bbc0b927e7d46f381d507dd0729d3bdab23c 100644 (file)
@@ -198,6 +198,13 @@ static void enclosure_remove_links(struct enclosure_component *cdev)
 {
        char name[ENCLOSURE_NAME_SIZE];
 
+       /*
+        * 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;
+
        enclosure_link_name(cdev, name);
        sysfs_remove_link(&cdev->dev->kobj, name);
        sysfs_remove_link(&cdev->cdev.kobj, "device");
index 6c0fde55270d3681c6048c1516b6915c291e4c45..66f411a6e8ea502251ede2b92bca60c59e8843fe 100644 (file)
 #define MEI_DEV_ID_PPT_2      0x1CBA  /* Panther Point */
 #define MEI_DEV_ID_PPT_3      0x1DBA  /* Panther Point */
 
-#define MEI_DEV_ID_LPT        0x8C3A  /* Lynx Point */
+#define MEI_DEV_ID_LPT_H      0x8C3A  /* Lynx Point H */
 #define MEI_DEV_ID_LPT_W      0x8D3A  /* Lynx Point - Wellsburg */
 #define MEI_DEV_ID_LPT_LP     0x9C3A  /* Lynx Point LP */
+#define MEI_DEV_ID_LPT_HR     0x8CBA  /* Lynx Point H Refresh */
+
+#define MEI_DEV_ID_WPT_LP     0x9CBA  /* Wildcat Point LP */
 /*
  * MEI HW Section
  */
index b96205aece0c781d267ef9c2ac198cc154145080..2cab3c0a6805364393e69a5410905874c4103e87 100644 (file)
@@ -76,9 +76,11 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_H)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_W)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_HR)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_WPT_LP)},
 
        /* required last entry */
        {0, }
index 8aa42e738acc6dde99a716535f8b27efcd9d0988..653799b96bfae0dd709367fa20a3a74bc296033d 100644 (file)
@@ -154,14 +154,14 @@ static void mic_reset_inform_host(struct virtio_device *vdev)
 {
        struct mic_vdev *mvdev = to_micvdev(vdev);
        struct mic_device_ctrl __iomem *dc = mvdev->dc;
-       int retry = 100, i;
+       int retry;
 
        iowrite8(0, &dc->host_ack);
        iowrite8(1, &dc->vdev_reset);
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
 
        /* Wait till host completes all card accesses and acks the reset */
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                if (ioread8(&dc->host_ack))
                        break;
                msleep(100);
@@ -187,11 +187,12 @@ static void mic_reset(struct virtio_device *vdev)
 /*
  * The virtio_ring code calls this API when it wants to notify the Host.
  */
-static void mic_notify(struct virtqueue *vq)
+static bool mic_notify(struct virtqueue *vq)
 {
        struct mic_vdev *mvdev = vq->priv;
 
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+       return true;
 }
 
 static void mic_del_vq(struct virtqueue *vq, int n)
@@ -247,17 +248,17 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
        /* First assign the vring's allocated in host memory */
        vqconfig = mic_vq_config(mvdev->desc) + index;
        memcpy_fromio(&config, vqconfig, sizeof(config));
-       _vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN);
+       _vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN);
        vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
-       va = mic_card_map(mvdev->mdev, config.address, vr_size);
+       va = mic_card_map(mvdev->mdev, le64_to_cpu(config.address), vr_size);
        if (!va)
                return ERR_PTR(-ENOMEM);
        mvdev->vr[index] = va;
        memset_io(va, 0x0, _vr_size);
-       vq = vring_new_virtqueue(index,
-                               config.num, MIC_VIRTIO_RING_ALIGN, vdev,
-                               false,
-                               va, mic_notify, callback, name);
+       vq = vring_new_virtqueue(index, le16_to_cpu(config.num),
+                                MIC_VIRTIO_RING_ALIGN, vdev, false,
+                                (void __force *)va, mic_notify, callback,
+                                name);
        if (!vq) {
                err = -ENOMEM;
                goto unmap;
@@ -272,7 +273,8 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
 
        /* Allocate and reassign used ring now */
        mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
-                       sizeof(struct vring_used_elem) * config.num);
+                                            sizeof(struct vring_used_elem) *
+                                            le16_to_cpu(config.num));
        used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(mvdev->used_size[index]));
        if (!used) {
@@ -309,7 +311,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct mic_vdev *mvdev = to_micvdev(vdev);
        struct mic_device_ctrl __iomem *dc = mvdev->dc;
-       int i, err, retry = 100;
+       int i, err, retry;
 
        /* We must have this many virtqueues. */
        if (nvqs > ioread8(&mvdev->desc->num_vq))
@@ -331,7 +333,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
         * rings have been re-assigned.
         */
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                if (!ioread8(&dc->used_address_updated))
                        break;
                msleep(100);
@@ -519,8 +521,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
        struct device *dev;
        int ret;
 
-       for (i = mic_aligned_size(struct mic_bootparam);
-               i < MIC_DP_SIZE; i += mic_total_desc_size(d)) {
+       for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE;
+               i += mic_total_desc_size(d)) {
                d = mdrv->dp + i;
                dc = (void __iomem *)d + mic_aligned_desc_size(d);
                /*
@@ -539,7 +541,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
                        continue;
 
                /* device already exists */
-               dev = device_find_child(mdrv->dev, d, mic_match_desc);
+               dev = device_find_child(mdrv->dev, (void __force *)d,
+                                       mic_match_desc);
                if (dev) {
                        if (remove)
                                iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
index 2c5c22c93ba8e787a1666e74d1b2256c4f894a27..d0407ba53bb7e81b45ecc2b6cfeb6af60ef747b8 100644 (file)
@@ -42,8 +42,8 @@
 
 static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc)
 {
-       return mic_aligned_size(*desc)
-               + ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig)
+       return sizeof(*desc)
+               + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig)
                + ioread8(&desc->feature_len) * 2
                + ioread8(&desc->config_len);
 }
@@ -67,8 +67,7 @@ mic_vq_configspace(struct mic_device_desc __iomem *desc)
 }
 static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc)
 {
-       return mic_aligned_desc_size(desc) +
-               mic_aligned_size(struct mic_device_ctrl);
+       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
 }
 
 int mic_devices_init(struct mic_driver *mdrv);
index 7558d91864380ae849d90a24deee4e31985850eb..b75c6b5cc20fc7a908944291add52a5cada071ff 100644 (file)
@@ -62,7 +62,7 @@ void mic_bootparam_init(struct mic_device *mdev)
 {
        struct mic_bootparam *bootparam = mdev->dp;
 
-       bootparam->magic = MIC_MAGIC;
+       bootparam->magic = cpu_to_le32(MIC_MAGIC);
        bootparam->c2h_shutdown_db = mdev->shutdown_db;
        bootparam->h2c_shutdown_db = -1;
        bootparam->h2c_config_db = -1;
index 5b8494bd1e003ff9cb53d49fa7ffd22798893912..e04bb4fe68235a7de2ac7e5c09c7c027776cb39c 100644 (file)
@@ -41,7 +41,7 @@ static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
         * We are copying from IO below an should ideally use something
         * like copy_to_user_fromio(..) if it existed.
         */
-       if (copy_to_user(ubuf, dbuf, len)) {
+       if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
                err = -EFAULT;
                dev_err(mic_dev(mvdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
@@ -66,7 +66,7 @@ static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
         * We are copying to IO below and should ideally use something
         * like copy_from_user_toio(..) if it existed.
         */
-       if (copy_from_user(dbuf, ubuf, len)) {
+       if (copy_from_user((void __force *)dbuf, ubuf, len)) {
                err = -EFAULT;
                dev_err(mic_dev(mvdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
@@ -293,7 +293,7 @@ static void mic_virtio_init_post(struct mic_vdev *mvdev)
                        continue;
                }
                mvdev->mvr[i].vrh.vring.used =
-                       mvdev->mdev->aper.va +
+                       (void __force *)mvdev->mdev->aper.va +
                        le64_to_cpu(vqconfig[i].used_address);
        }
 
@@ -378,7 +378,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev,
                        void __user *argp)
 {
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int ret = 0, retry = 100, i;
+       int ret = 0, retry, i;
        struct mic_bootparam *bootparam = mvdev->mdev->dp;
        s8 db = bootparam->h2c_config_db;
 
@@ -401,7 +401,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev,
        mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
        mvdev->mdev->ops->send_intr(mvdev->mdev, db);
 
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                ret = wait_event_timeout(wake,
                        mvdev->dc->guest_ack, msecs_to_jiffies(100));
                if (ret)
@@ -467,7 +467,7 @@ static int mic_copy_dp_entry(struct mic_vdev *mvdev,
        }
 
        /* Find the first free device page entry */
-       for (i = mic_aligned_size(struct mic_bootparam);
+       for (i = sizeof(struct mic_bootparam);
                i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
                i += mic_total_desc_size(devp)) {
                devp = mdev->dp + i;
@@ -525,6 +525,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
        char irqname[10];
        struct mic_bootparam *bootparam = mdev->dp;
        u16 num;
+       dma_addr_t vr_addr;
 
        mutex_lock(&mdev->mic_mutex);
 
@@ -559,17 +560,16 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
                }
                vr->len = vr_size;
                vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
-               vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i;
-               vqconfig[i].address = mic_map_single(mdev,
-                       vr->va, vr_size);
-               if (mic_map_error(vqconfig[i].address)) {
+               vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i);
+               vr_addr = mic_map_single(mdev, vr->va, vr_size);
+               if (mic_map_error(vr_addr)) {
                        free_pages((unsigned long)vr->va, get_order(vr_size));
                        ret = -ENOMEM;
                        dev_err(mic_dev(mvdev), "%s %d err %d\n",
                                __func__, __LINE__, ret);
                        goto err;
                }
-               vqconfig[i].address = cpu_to_le64(vqconfig[i].address);
+               vqconfig[i].address = cpu_to_le64(vr_addr);
 
                vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
                ret = vringh_init_kern(&mvr->vrh,
@@ -639,7 +639,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
        struct mic_vdev *tmp_mvdev;
        struct mic_device *mdev = mvdev->mdev;
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int i, ret, retry = 100;
+       int i, ret, retry;
        struct mic_vqconfig *vqconfig;
        struct mic_bootparam *bootparam = mdev->dp;
        s8 db;
@@ -652,16 +652,16 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
                "Requesting hot remove id %d\n", mvdev->virtio_id);
        mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
        mdev->ops->send_intr(mdev, db);
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                ret = wait_event_timeout(wake,
                        mvdev->dc->guest_ack, msecs_to_jiffies(100));
                if (ret)
                        break;
        }
        dev_dbg(mdev->sdev->parent,
-               "Device id %d config_change %d guest_ack %d\n",
+               "Device id %d config_change %d guest_ack %d retry %d\n",
                mvdev->virtio_id, mvdev->dc->config_change,
-               mvdev->dc->guest_ack);
+               mvdev->dc->guest_ack, retry);
        mvdev->dc->config_change = 0;
        mvdev->dc->guest_ack = 0;
 skip_hot_remove:
index 81e9541b784c3a4d46bbd352c2aa26faf70c2877..0dfa8a81436e80ebd325d1722caa791d5193936e 100644 (file)
@@ -397,8 +397,8 @@ mic_x100_load_ramdisk(struct mic_device *mdev)
         * so copy over the ramdisk @ 128M.
         */
        memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size);
-       iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image);
-       iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size);
+       iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image);
+       iowrite32(fw->size, &bp->hdr.ramdisk_size);
        release_firmware(fw);
 error:
        return rc;
index 0b10a9030f4e2a85029ea4bab3afcdb8102899be..98b6b6ef7e5c9d737a749e9a3ddf631f5d92c1c0 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
+#include <linux/of.h>
 #include <linux/omap-dma.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #define OMAP_MMC_CMDTYPE_AC    2
 #define OMAP_MMC_CMDTYPE_ADTC  3
 
-#define OMAP_DMA_MMC_TX                21
-#define OMAP_DMA_MMC_RX                22
-#define OMAP_DMA_MMC2_TX       54
-#define OMAP_DMA_MMC2_RX       55
-
-#define OMAP24XX_DMA_MMC2_TX   47
-#define OMAP24XX_DMA_MMC2_RX   48
-#define OMAP24XX_DMA_MMC1_TX   61
-#define OMAP24XX_DMA_MMC1_RX   62
-
-
 #define DRIVER_NAME "mmci-omap"
 
 /* Specifies how often in millisecs to poll for card status changes
@@ -1330,7 +1320,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
        struct mmc_omap_host *host = NULL;
        struct resource *res;
        dma_cap_mask_t mask;
-       unsigned sig;
+       unsigned sig = 0;
        int i, ret = 0;
        int irq;
 
@@ -1340,7 +1330,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
        }
        if (pdata->nr_slots == 0) {
                dev_err(&pdev->dev, "no slots\n");
-               return -ENXIO;
+               return -EPROBE_DEFER;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1407,19 +1397,20 @@ static int mmc_omap_probe(struct platform_device *pdev)
        host->dma_tx_burst = -1;
        host->dma_rx_burst = -1;
 
-       if (mmc_omap2())
-               sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
-       else
-               sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
-       host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+       if (res)
+               sig = res->start;
+       host->dma_tx = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, &pdev->dev, "tx");
        if (!host->dma_tx)
                dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
                        sig);
-       if (mmc_omap2())
-               sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
-       else
-               sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
-       host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+       if (res)
+               sig = res->start;
+       host->dma_rx = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, &pdev->dev, "rx");
        if (!host->dma_rx)
                dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n",
                        sig);
@@ -1512,12 +1503,20 @@ static int mmc_omap_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id mmc_omap_match[] = {
+       { .compatible = "ti,omap2420-mmc", },
+       { },
+};
+#endif
+
 static struct platform_driver mmc_omap_driver = {
        .probe          = mmc_omap_probe,
        .remove         = mmc_omap_remove,
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(mmc_omap_match),
        },
 };
 
index 4cabdc9fda9076ceff440af42e028fb1073f9ed7..4b3aaa898a8b6b3a4975d2218370711981cb59c4 100644 (file)
@@ -962,7 +962,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 {
        struct platform_device *pdev = info->pdev;
-       if (use_dma) {
+       if (info->use_dma) {
                pxa_free_dma(info->data_dma_ch);
                dma_free_coherent(&pdev->dev, info->buf_size,
                                  info->data_buff, info->data_buff_phys);
@@ -1259,10 +1259,6 @@ static struct of_device_id pxa3xx_nand_dt_ids[] = {
                .compatible = "marvell,pxa3xx-nand",
                .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
        },
-       {
-               .compatible = "marvell,armada370-nand",
-               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
-       },
        {}
 };
 MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
index 4dd5ee2a34cc68c4222f4c4115beedaee8b187d2..398e299ee1bded33a57d7eb91318b00b24513658 100644 (file)
@@ -4110,7 +4110,7 @@ static int bond_check_params(struct bond_params *params)
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
                        pr_warning("Forcing miimon to 100msec\n");
-                       miimon = 100;
+                       miimon = BOND_DEFAULT_MIIMON;
                }
        }
 
@@ -4147,7 +4147,7 @@ static int bond_check_params(struct bond_params *params)
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure and link speed which are essential for TLB/ALB load balancing\n");
                        pr_warning("Forcing miimon to 100msec\n");
-                       miimon = 100;
+                       miimon = BOND_DEFAULT_MIIMON;
                }
        }
 
@@ -4199,9 +4199,9 @@ static int bond_check_params(struct bond_params *params)
             (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[i]; i++) {
                /* not complete check, but should be good enough to
                   catch mistakes */
-               __be32 ip = in_aton(arp_ip_target[i]);
-               if (!isdigit(arp_ip_target[i][0]) || ip == 0 ||
-                   ip == htonl(INADDR_BROADCAST)) {
+               __be32 ip;
+               if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) ||
+                   IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) {
                        pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
                                   arp_ip_target[i]);
                        arp_interval = 0;
index 9a5223c7b4d1a14f9b19354cfba6c4ea3dd933d0..ea6f640782b7456228787fa33ab8882b2bd8aa0b 100644 (file)
@@ -45,10 +45,15 @@ int bond_option_mode_set(struct bonding *bond, int mode)
                return -EPERM;
        }
 
-       if (BOND_MODE_IS_LB(mode) && bond->params.arp_interval) {
-               pr_err("%s: %s mode is incompatible with arp monitoring.\n",
-                      bond->dev->name, bond_mode_tbl[mode].modename);
-               return -EINVAL;
+       if (BOND_NO_USES_ARP(mode) && bond->params.arp_interval) {
+               pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n",
+                       bond->dev->name, bond_mode_tbl[mode].modename);
+               /* disable arp monitoring */
+               bond->params.arp_interval = 0;
+               /* set miimon to default value */
+               bond->params.miimon = BOND_DEFAULT_MIIMON;
+               pr_info("%s: Setting MII monitoring interval to %d.\n",
+                       bond->dev->name, bond->params.miimon);
        }
 
        /* don't cache arp_validate between modes */
index 0ec2a7e8c8a9588170c97715856e7b5f34cf7c60..0ae580bbc5db02ec4dbb3c5855ada7164f32c89a 100644 (file)
@@ -523,9 +523,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                ret = -EINVAL;
                goto out;
        }
-       if (bond->params.mode == BOND_MODE_ALB ||
-           bond->params.mode == BOND_MODE_TLB ||
-           bond->params.mode == BOND_MODE_8023AD) {
+       if (BOND_NO_USES_ARP(bond->params.mode)) {
                pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
                        bond->dev->name, bond->dev->name);
                ret = -EINVAL;
@@ -1637,12 +1635,12 @@ static ssize_t bonding_show_packets_per_slave(struct device *d,
                                              char *buf)
 {
        struct bonding *bond = to_bond(d);
-       int packets_per_slave = bond->params.packets_per_slave;
+       unsigned int packets_per_slave = bond->params.packets_per_slave;
 
        if (packets_per_slave > 1)
                packets_per_slave = reciprocal_value(packets_per_slave);
 
-       return sprintf(buf, "%d\n", packets_per_slave);
+       return sprintf(buf, "%u\n", packets_per_slave);
 }
 
 static ssize_t bonding_store_packets_per_slave(struct device *d,
index ca31286aa028158341a5847382b75afb74a6ea2f..a9f4f9f4d8ceea321061e94f35164829e1de2f7c 100644 (file)
@@ -35,6 +35,8 @@
 
 #define BOND_MAX_ARP_TARGETS   16
 
+#define BOND_DEFAULT_MIIMON    100
+
 #define IS_UP(dev)                                        \
              ((((dev)->flags & IFF_UP) == IFF_UP)      && \
               netif_running(dev)                       && \
                 ((mode) == BOND_MODE_TLB)          ||  \
                 ((mode) == BOND_MODE_ALB))
 
+#define BOND_NO_USES_ARP(mode)                         \
+               (((mode) == BOND_MODE_8023AD)   ||      \
+                ((mode) == BOND_MODE_TLB)      ||      \
+                ((mode) == BOND_MODE_ALB))
+
 #define TX_QUEUE_OVERRIDE(mode)                                \
                        (((mode) == BOND_MODE_ACTIVEBACKUP) ||  \
                         ((mode) == BOND_MODE_ROUNDROBIN))
index e3fc07cf2f6269e5ccf0ca5dbf42897c191cecd4..77061eebb034f4295258d9b0800fed28865d123a 100644 (file)
@@ -712,22 +712,31 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
        return 0;
 }
 
-static int c_can_get_berr_counter(const struct net_device *dev,
-                                       struct can_berr_counter *bec)
+static int __c_can_get_berr_counter(const struct net_device *dev,
+                                   struct can_berr_counter *bec)
 {
        unsigned int reg_err_counter;
        struct c_can_priv *priv = netdev_priv(dev);
 
-       c_can_pm_runtime_get_sync(priv);
-
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
                                ERR_CNT_REC_SHIFT;
        bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
 
+       return 0;
+}
+
+static int c_can_get_berr_counter(const struct net_device *dev,
+                                 struct can_berr_counter *bec)
+{
+       struct c_can_priv *priv = netdev_priv(dev);
+       int err;
+
+       c_can_pm_runtime_get_sync(priv);
+       err = __c_can_get_berr_counter(dev, bec);
        c_can_pm_runtime_put_sync(priv);
 
-       return 0;
+       return err;
 }
 
 /*
@@ -754,6 +763,7 @@ static void c_can_do_tx(struct net_device *dev)
                if (!(val & (1 << (msg_obj_no - 1)))) {
                        can_get_echo_skb(dev,
                                        msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+                       c_can_object_get(dev, 0, msg_obj_no, IF_COMM_ALL);
                        stats->tx_bytes += priv->read_reg(priv,
                                        C_CAN_IFACE(MSGCTRL_REG, 0))
                                        & IF_MCONT_DLC_MASK;
@@ -872,7 +882,7 @@ static int c_can_handle_state_change(struct net_device *dev,
        if (unlikely(!skb))
                return 0;
 
-       c_can_get_berr_counter(dev, &bec);
+       __c_can_get_berr_counter(dev, &bec);
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
                                ERR_CNT_RP_SHIFT;
index ae08cf129ebbb0bda31f4b74893574b9703253f0..aaed97bee4711d1cb2e8b1eb514fc3e343ad21e0 100644 (file)
@@ -1020,13 +1020,13 @@ static int flexcan_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "no ipg clock defined\n");
                        return PTR_ERR(clk_ipg);
                }
-               clock_freq = clk_get_rate(clk_ipg);
 
                clk_per = devm_clk_get(&pdev->dev, "per");
                if (IS_ERR(clk_per)) {
                        dev_err(&pdev->dev, "no per clock defined\n");
                        return PTR_ERR(clk_per);
                }
+               clock_freq = clk_get_rate(clk_per);
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 7164a999f50ff37e176f9995f21cd04451f17043..f17c3018b7c7ffb3f7d75785c3ddd2218b0f3f79 100644 (file)
@@ -494,20 +494,20 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
        uint8_t isrc, status;
        int n = 0;
 
-       /* Shared interrupts and IRQ off? */
-       if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
-               return IRQ_NONE;
-
        if (priv->pre_irq)
                priv->pre_irq(priv);
 
+       /* Shared interrupts and IRQ off? */
+       if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
+               goto out;
+
        while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&
               (n < SJA1000_MAX_IRQ)) {
-               n++;
+
                status = priv->read_reg(priv, SJA1000_SR);
                /* check for absent controller due to hw unplug */
                if (status == 0xFF && sja1000_is_absent(priv))
-                       return IRQ_NONE;
+                       goto out;
 
                if (isrc & IRQ_WUI)
                        netdev_warn(dev, "wakeup interrupt\n");
@@ -535,7 +535,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                                status = priv->read_reg(priv, SJA1000_SR);
                                /* check for absent controller */
                                if (status == 0xFF && sja1000_is_absent(priv))
-                                       return IRQ_NONE;
+                                       goto out;
                        }
                }
                if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
@@ -543,8 +543,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                        if (sja1000_err(dev, isrc, status))
                                break;
                }
+               n++;
        }
-
+out:
        if (priv->post_irq)
                priv->post_irq(priv);
 
index 5f9a7ad9b964da35190f01154492189965ba28ac..8aeec0b4601a2e8fe45290643a910a4fd8e4137b 100644 (file)
@@ -625,6 +625,7 @@ static int ems_usb_start(struct ems_usb *dev)
                        usb_unanchor_urb(urb);
                        usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
                                          urb->transfer_dma);
+                       usb_free_urb(urb);
                        break;
                }
 
@@ -798,8 +799,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
         * allowed (MAX_TX_URBS).
         */
        if (!context) {
-               usb_unanchor_urb(urb);
                usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
+               usb_free_urb(urb);
 
                netdev_warn(netdev, "couldn't find free context\n");
 
index 8ee9d1556e6e4eb3b8d32cfb988ba9870fccffaa..263dd921edc42342bba78ce9f2885862f0fc3087 100644 (file)
@@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
        /* set LED in default state (end of init phase) */
        pcan_usb_pro_set_led(dev, 0, 1);
 
+       kfree(bi);
+       kfree(fi);
+
        return 0;
 
  err_out:
index 50b853a79d7787c73d0ea8d0ac1f1e0853ac2adf..46dfb1378c17cac79064a5f3f809e94a1d75c584 100644 (file)
@@ -717,8 +717,7 @@ static int emac_open(struct net_device *dev)
        if (netif_msg_ifup(db))
                dev_dbg(db->dev, "enabling %s\n", dev->name);
 
-       if (devm_request_irq(db->dev, dev->irq, &emac_interrupt,
-                            0, dev->name, dev))
+       if (request_irq(dev->irq, &emac_interrupt, 0, dev->name, dev))
                return -EAGAIN;
 
        /* Initialize EMAC board */
@@ -774,6 +773,8 @@ static int emac_stop(struct net_device *ndev)
 
        emac_shutdown(ndev);
 
+       free_irq(ndev->irq, ndev);
+
        return 0;
 }
 
index 0216d592d0cee4b080a9d33d7776f632bf639453..2e46c28fc6019a892f7792c6017effe3f7db7063 100644 (file)
@@ -3114,6 +3114,11 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
        struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
 
+       if (!IS_SRIOV(bp)) {
+               BNX2X_ERR("failed to configure SR-IOV since vfdb was not allocated. Check dmesg for errors in probe stage\n");
+               return -EINVAL;
+       }
+
        DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n",
           num_vfs_param, BNX2X_NR_VIRTFN(bp));
 
index a9e068423ba0651414cc0c5b23f0eda6937a6c23..f3dd93b4aeaac1bc8cdff71c9113d6668e085fd2 100644 (file)
@@ -8932,6 +8932,9 @@ static int tg3_chip_reset(struct tg3 *tp)
        void (*write_op)(struct tg3 *, u32, u32);
        int i, err;
 
+       if (!pci_device_is_present(tp->pdev))
+               return -ENODEV;
+
        tg3_nvram_lock(tp);
 
        tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
@@ -10629,10 +10632,8 @@ static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir)
 static ssize_t tg3_show_temp(struct device *dev,
                             struct device_attribute *devattr, char *buf)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct net_device *netdev = pci_get_drvdata(pdev);
-       struct tg3 *tp = netdev_priv(netdev);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct tg3 *tp = dev_get_drvdata(dev);
        u32 temperature;
 
        spin_lock_bh(&tp->lock);
@@ -10650,29 +10651,25 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, tg3_show_temp, NULL,
 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, tg3_show_temp, NULL,
                          TG3_TEMP_MAX_OFFSET);
 
-static struct attribute *tg3_attributes[] = {
+static struct attribute *tg3_attrs[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_crit.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        NULL
 };
-
-static const struct attribute_group tg3_group = {
-       .attrs = tg3_attributes,
-};
+ATTRIBUTE_GROUPS(tg3);
 
 static void tg3_hwmon_close(struct tg3 *tp)
 {
        if (tp->hwmon_dev) {
                hwmon_device_unregister(tp->hwmon_dev);
                tp->hwmon_dev = NULL;
-               sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group);
        }
 }
 
 static void tg3_hwmon_open(struct tg3 *tp)
 {
-       int i, err;
+       int i;
        u32 size = 0;
        struct pci_dev *pdev = tp->pdev;
        struct tg3_ocir ocirs[TG3_SD_NUM_RECS];
@@ -10690,18 +10687,11 @@ static void tg3_hwmon_open(struct tg3 *tp)
        if (!size)
                return;
 
-       /* Register hwmon sysfs hooks */
-       err = sysfs_create_group(&pdev->dev.kobj, &tg3_group);
-       if (err) {
-               dev_err(&pdev->dev, "Cannot create sysfs group, aborting\n");
-               return;
-       }
-
-       tp->hwmon_dev = hwmon_device_register(&pdev->dev);
+       tp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, "tg3",
+                                                         tp, tg3_groups);
        if (IS_ERR(tp->hwmon_dev)) {
                tp->hwmon_dev = NULL;
                dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n");
-               sysfs_remove_group(&pdev->dev.kobj, &tg3_group);
        }
 }
 
@@ -11594,10 +11584,11 @@ static int tg3_close(struct net_device *dev)
        memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev));
        memset(&tp->estats_prev, 0, sizeof(tp->estats_prev));
 
-       tg3_power_down_prepare(tp);
-
-       tg3_carrier_off(tp);
+       if (pci_device_is_present(tp->pdev)) {
+               tg3_power_down_prepare(tp);
 
+               tg3_carrier_off(tp);
+       }
        return 0;
 }
 
@@ -16512,6 +16503,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
        /* Clear this out for sanity. */
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 
+       /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */
+       tw32(TG3PCI_REG_BASE_ADDR, 0);
+
        pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
                              &pci_state_reg);
        if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
@@ -17739,10 +17733,12 @@ static int tg3_suspend(struct device *device)
        struct pci_dev *pdev = to_pci_dev(device);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int err = 0;
+
+       rtnl_lock();
 
        if (!netif_running(dev))
-               return 0;
+               goto unlock;
 
        tg3_reset_task_cancel(tp);
        tg3_phy_stop(tp);
@@ -17784,6 +17780,8 @@ out:
                        tg3_phy_start(tp);
        }
 
+unlock:
+       rtnl_unlock();
        return err;
 }
 
@@ -17792,10 +17790,12 @@ static int tg3_resume(struct device *device)
        struct pci_dev *pdev = to_pci_dev(device);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int err = 0;
+
+       rtnl_lock();
 
        if (!netif_running(dev))
-               return 0;
+               goto unlock;
 
        netif_device_attach(dev);
 
@@ -17819,6 +17819,8 @@ out:
        if (!err)
                tg3_phy_start(tp);
 
+unlock:
+       rtnl_unlock();
        return err;
 }
 #endif /* CONFIG_PM_SLEEP */
index ecd2fb3ef69596146a7cf155323e624e397b6834..6c9308850453bf1ecd21173afa1d1cf11681c8c7 100644 (file)
 #include <asm/io.h>
 #include "cxgb4_uld.h"
 
-#define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 4
-#define FW_VERSION_MICRO 0
+#define T4FW_VERSION_MAJOR 0x01
+#define T4FW_VERSION_MINOR 0x06
+#define T4FW_VERSION_MICRO 0x18
+#define T4FW_VERSION_BUILD 0x00
 
-#define FW_VERSION_MAJOR_T5 0
-#define FW_VERSION_MINOR_T5 0
-#define FW_VERSION_MICRO_T5 0
+#define T5FW_VERSION_MAJOR 0x01
+#define T5FW_VERSION_MINOR 0x08
+#define T5FW_VERSION_MICRO 0x1C
+#define T5FW_VERSION_BUILD 0x00
 
 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
 
@@ -240,6 +242,26 @@ struct pci_params {
        unsigned char width;
 };
 
+#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+#define CHELSIO_CHIP_FPGA          0x100
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
+#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+
+#define CHELSIO_T4             0x4
+#define CHELSIO_T5             0x5
+
+enum chip_type {
+       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+       T4_FIRST_REV    = T4_A1,
+       T4_LAST_REV     = T4_A2,
+
+       T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+       T5_FIRST_REV    = T5_A0,
+       T5_LAST_REV     = T5_A1,
+};
+
 struct adapter_params {
        struct tp_params  tp;
        struct vpd_params vpd;
@@ -259,7 +281,7 @@ struct adapter_params {
 
        unsigned char nports;             /* # of ethernet ports */
        unsigned char portvec;
-       unsigned char rev;                /* chip revision */
+       enum chip_type chip;               /* chip code */
        unsigned char offload;
 
        unsigned char bypass;
@@ -267,6 +289,23 @@ struct adapter_params {
        unsigned int ofldq_wr_cred;
 };
 
+#include "t4fw_api.h"
+
+#define FW_VERSION(chip) ( \
+               FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \
+               FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \
+               FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \
+               FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD))
+#define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf)
+
+struct fw_info {
+       u8 chip;
+       char *fs_name;
+       char *fw_mod_name;
+       struct fw_hdr fw_hdr;
+};
+
+
 struct trace_params {
        u32 data[TRACE_LEN / 4];
        u32 mask[TRACE_LEN / 4];
@@ -512,25 +551,6 @@ struct sge {
 
 struct l2t_data;
 
-#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
-#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
-
-#define CHELSIO_T4             0x4
-#define CHELSIO_T5             0x5
-
-enum chip_type {
-       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
-       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
-       T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
-       T4_FIRST_REV    = T4_A1,
-       T4_LAST_REV     = T4_A3,
-
-       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
-       T5_FIRST_REV    = T5_A1,
-       T5_LAST_REV     = T5_A1,
-};
-
 #ifdef CONFIG_PCI_IOV
 
 /* T4 supports SRIOV on PF0-3 and T5 on PF0-7.  However, the Serial
@@ -715,12 +735,12 @@ enum {
 
 static inline int is_t5(enum chip_type chip)
 {
-       return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5;
 }
 
 static inline int is_t4(enum chip_type chip)
 {
-       return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
 }
 
 static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
@@ -900,7 +920,11 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
-int t4_check_fw_version(struct adapter *adapter);
+int t4_get_fw_version(struct adapter *adapter, u32 *vers);
+int t4_get_tp_version(struct adapter *adapter, u32 *vers);
+int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state, int *reset);
 int t4_prep_adapter(struct adapter *adapter);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
index 8b929eeecd2d37cd3b41e32d57bd1fa50402a230..d6b12e035a7d9f27d84d397dc2921713c7fed46f 100644 (file)
@@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
        { 0, }
 };
 
-#define FW_FNAME "cxgb4/t4fw.bin"
+#define FW4_FNAME "cxgb4/t4fw.bin"
 #define FW5_FNAME "cxgb4/t5fw.bin"
-#define FW_CFNAME "cxgb4/t4-config.txt"
+#define FW4_CFNAME "cxgb4/t4-config.txt"
 #define FW5_CFNAME "cxgb4/t5-config.txt"
 
 MODULE_DESCRIPTION(DRV_DESC);
@@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
-MODULE_FIRMWARE(FW_FNAME);
+MODULE_FIRMWARE(FW4_FNAME);
 MODULE_FIRMWARE(FW5_FNAME);
 
 /*
@@ -1070,72 +1070,6 @@ freeout: t4_free_sge_resources(adap);
        return 0;
 }
 
-/*
- * Returns 0 if new FW was successfully loaded, a positive errno if a load was
- * started but failed, and a negative errno if flash load couldn't start.
- */
-static int upgrade_fw(struct adapter *adap)
-{
-       int ret;
-       u32 vers, exp_major;
-       const struct fw_hdr *hdr;
-       const struct firmware *fw;
-       struct device *dev = adap->pdev_dev;
-       char *fw_file_name;
-
-       switch (CHELSIO_CHIP_VERSION(adap->chip)) {
-       case CHELSIO_T4:
-               fw_file_name = FW_FNAME;
-               exp_major = FW_VERSION_MAJOR;
-               break;
-       case CHELSIO_T5:
-               fw_file_name = FW5_FNAME;
-               exp_major = FW_VERSION_MAJOR_T5;
-               break;
-       default:
-               dev_err(dev, "Unsupported chip type, %x\n", adap->chip);
-               return -EINVAL;
-       }
-
-       ret = request_firmware(&fw, fw_file_name, dev);
-       if (ret < 0) {
-               dev_err(dev, "unable to load firmware image %s, error %d\n",
-                       fw_file_name, ret);
-               return ret;
-       }
-
-       hdr = (const struct fw_hdr *)fw->data;
-       vers = ntohl(hdr->fw_ver);
-       if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
-               ret = -EINVAL;              /* wrong major version, won't do */
-               goto out;
-       }
-
-       /*
-        * If the flash FW is unusable or we found something newer, load it.
-        */
-       if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
-           vers > adap->params.fw_vers) {
-               dev_info(dev, "upgrading firmware ...\n");
-               ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
-                                   /*force=*/false);
-               if (!ret)
-                       dev_info(dev,
-                                "firmware upgraded to version %pI4 from %s\n",
-                                &hdr->fw_ver, fw_file_name);
-               else
-                       dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
-       } else {
-               /*
-                * Tell our caller that we didn't upgrade the firmware.
-                */
-               ret = -EINVAL;
-       }
-
-out:   release_firmware(fw);
-       return ret;
-}
-
 /*
  * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
  * The allocated memory is cleared.
@@ -1415,7 +1349,7 @@ static int get_sset_count(struct net_device *dev, int sset)
 static int get_regs_len(struct net_device *dev)
 {
        struct adapter *adap = netdev2adap(dev);
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                return T4_REGMAP_SIZE;
        else
                return T5_REGMAP_SIZE;
@@ -1499,7 +1433,7 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
        data += sizeof(struct port_stats) / sizeof(u64);
        collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
        data += sizeof(struct queue_port_stats) / sizeof(u64);
-       if (!is_t4(adapter->chip)) {
+       if (!is_t4(adapter->params.chip)) {
                t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7));
                val1 = t4_read_reg(adapter, SGE_STAT_TOTAL);
                val2 = t4_read_reg(adapter, SGE_STAT_MATCH);
@@ -1521,8 +1455,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
  */
 static inline unsigned int mk_adap_vers(const struct adapter *ap)
 {
-       return CHELSIO_CHIP_VERSION(ap->chip) |
-               (CHELSIO_CHIP_RELEASE(ap->chip) << 10) | (1 << 16);
+       return CHELSIO_CHIP_VERSION(ap->params.chip) |
+               (CHELSIO_CHIP_RELEASE(ap->params.chip) << 10) | (1 << 16);
 }
 
 static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
@@ -2189,7 +2123,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
        static const unsigned int *reg_ranges;
        int arr_size = 0, buf_size = 0;
 
-       if (is_t4(ap->chip)) {
+       if (is_t4(ap->params.chip)) {
                reg_ranges = &t4_reg_ranges[0];
                arr_size = ARRAY_SIZE(t4_reg_ranges);
                buf_size = T4_REGMAP_SIZE;
@@ -2967,7 +2901,7 @@ static int setup_debugfs(struct adapter *adap)
                size = t4_read_reg(adap, MA_EDRAM1_BAR);
                add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size));
        }
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
                if (i & EXT_MEM_ENABLE)
                        add_debugfs_mem(adap, "mc", MEM_MC,
@@ -3419,7 +3353,7 @@ unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
 
        v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
        v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                lp_count = G_LP_COUNT(v1);
                hp_count = G_HP_COUNT(v1);
        } else {
@@ -3588,7 +3522,7 @@ static void drain_db_fifo(struct adapter *adap, int usecs)
        do {
                v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
                v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
-               if (is_t4(adap->chip)) {
+               if (is_t4(adap->params.chip)) {
                        lp_count = G_LP_COUNT(v1);
                        hp_count = G_HP_COUNT(v1);
                } else {
@@ -3708,7 +3642,7 @@ static void process_db_drop(struct work_struct *work)
 
        adap = container_of(work, struct adapter, db_drop_task);
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                disable_dbs(adap);
                notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
                drain_db_fifo(adap, 1);
@@ -3753,7 +3687,7 @@ static void process_db_drop(struct work_struct *work)
 
 void t4_db_full(struct adapter *adap)
 {
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                t4_set_reg_field(adap, SGE_INT_ENABLE3,
                                 DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
                queue_work(workq, &adap->db_full_task);
@@ -3762,7 +3696,7 @@ void t4_db_full(struct adapter *adap)
 
 void t4_db_dropped(struct adapter *adap)
 {
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                queue_work(workq, &adap->db_drop_task);
 }
 
@@ -3789,7 +3723,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.nchan = adap->params.nports;
        lli.nports = adap->params.nports;
        lli.wr_cred = adap->params.ofldq_wr_cred;
-       lli.adapter_type = adap->params.rev;
+       lli.adapter_type = adap->params.chip;
        lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
        lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
@@ -4483,7 +4417,7 @@ static void setup_memwin(struct adapter *adap)
        u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
 
        bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mem_win0_base = bar0 + MEMWIN0_BASE;
                mem_win1_base = bar0 + MEMWIN1_BASE;
                mem_win2_base = bar0 + MEMWIN2_BASE;
@@ -4668,8 +4602,10 @@ static int adap_init0_config(struct adapter *adapter, int reset)
        const struct firmware *cf;
        unsigned long mtype = 0, maddr = 0;
        u32 finiver, finicsum, cfcsum;
-       int ret, using_flash;
+       int ret;
+       int config_issued = 0;
        char *fw_config_file, fw_config_file_path[256];
+       char *config_name = NULL;
 
        /*
         * Reset device if necessary.
@@ -4686,9 +4622,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         * then use that.  Otherwise, use the configuration file stored
         * in the adapter flash ...
         */
-       switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
+       switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
        case CHELSIO_T4:
-               fw_config_file = FW_CFNAME;
+               fw_config_file = FW4_CFNAME;
                break;
        case CHELSIO_T5:
                fw_config_file = FW5_CFNAME;
@@ -4702,13 +4638,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 
        ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
        if (ret < 0) {
-               using_flash = 1;
+               config_name = "On FLASH";
                mtype = FW_MEMTYPE_CF_FLASH;
                maddr = t4_flash_cfg_addr(adapter);
        } else {
                u32 params[7], val[7];
 
-               using_flash = 0;
+               sprintf(fw_config_file_path,
+                       "/lib/firmware/%s", fw_config_file);
+               config_name = fw_config_file_path;
+
                if (cf->size >= FLASH_CFG_MAX_SIZE)
                        ret = -ENOMEM;
                else {
@@ -4776,6 +4715,26 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                      FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
+
+       /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware
+        * Configuration File in FLASH), our last gasp effort is to use the
+        * Firmware Configuration File which is embedded in the firmware.  A
+        * very few early versions of the firmware didn't have one embedded
+        * but we can ignore those.
+        */
+       if (ret == -ENOENT) {
+               memset(&caps_cmd, 0, sizeof(caps_cmd));
+               caps_cmd.op_to_write =
+                       htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+                                       FW_CMD_REQUEST |
+                                       FW_CMD_READ);
+               caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
+               ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
+                               sizeof(caps_cmd), &caps_cmd);
+               config_name = "Firmware Default";
+       }
+
+       config_issued = 1;
        if (ret < 0)
                goto bye;
 
@@ -4816,7 +4775,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-       sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
        /*
         * Return successfully and note that we're operating with parameters
         * not supplied by the driver, rather than from hard-wired
@@ -4824,11 +4782,8 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         */
        adapter->flags |= USING_SOFT_PARAMS;
        dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
-                "Configuration File %s, version %#x, computed checksum %#x\n",
-                (using_flash
-                 ? "in device FLASH"
-                 : fw_config_file_path),
-                finiver, cfcsum);
+                "Configuration File \"%s\", version %#x, computed checksum %#x\n",
+                config_name, finiver, cfcsum);
        return 0;
 
        /*
@@ -4837,9 +4792,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         * want to issue a warning since this is fairly common.)
         */
 bye:
-       if (ret != -ENOENT)
-               dev_warn(adapter->pdev_dev, "Configuration file error %d\n",
-                        -ret);
+       if (config_issued && ret != -ENOENT)
+               dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n",
+                        config_name, -ret);
        return ret;
 }
 
@@ -5086,6 +5041,47 @@ bye:
        return ret;
 }
 
+static struct fw_info fw_info_array[] = {
+       {
+               .chip = CHELSIO_T4,
+               .fs_name = FW4_CFNAME,
+               .fw_mod_name = FW4_FNAME,
+               .fw_hdr = {
+                       .chip = FW_HDR_CHIP_T4,
+                       .fw_ver = __cpu_to_be32(FW_VERSION(T4)),
+                       .intfver_nic = FW_INTFVER(T4, NIC),
+                       .intfver_vnic = FW_INTFVER(T4, VNIC),
+                       .intfver_ri = FW_INTFVER(T4, RI),
+                       .intfver_iscsi = FW_INTFVER(T4, ISCSI),
+                       .intfver_fcoe = FW_INTFVER(T4, FCOE),
+               },
+       }, {
+               .chip = CHELSIO_T5,
+               .fs_name = FW5_CFNAME,
+               .fw_mod_name = FW5_FNAME,
+               .fw_hdr = {
+                       .chip = FW_HDR_CHIP_T5,
+                       .fw_ver = __cpu_to_be32(FW_VERSION(T5)),
+                       .intfver_nic = FW_INTFVER(T5, NIC),
+                       .intfver_vnic = FW_INTFVER(T5, VNIC),
+                       .intfver_ri = FW_INTFVER(T5, RI),
+                       .intfver_iscsi = FW_INTFVER(T5, ISCSI),
+                       .intfver_fcoe = FW_INTFVER(T5, FCOE),
+               },
+       }
+};
+
+static struct fw_info *find_fw_info(int chip)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
+               if (fw_info_array[i].chip == chip)
+                       return &fw_info_array[i];
+       }
+       return NULL;
+}
+
 /*
  * Phase 0 of initialization: contact FW, obtain config, perform basic init.
  */
@@ -5123,44 +5119,54 @@ static int adap_init0(struct adapter *adap)
         * later reporting and B. to warn if the currently loaded firmware
         * is excessively mismatched relative to the driver.)
         */
-       ret = t4_check_fw_version(adap);
-
-       /* The error code -EFAULT is returned by t4_check_fw_version() if
-        * firmware on adapter < supported firmware. If firmware on adapter
-        * is too old (not supported by driver) and we're the MASTER_PF set
-        * adapter state to DEV_STATE_UNINIT to force firmware upgrade
-        * and reinitialization.
-        */
-       if ((adap->flags & MASTER_PF) && ret == -EFAULT)
-               state = DEV_STATE_UNINIT;
+       t4_get_fw_version(adap, &adap->params.fw_vers);
+       t4_get_tp_version(adap, &adap->params.tp_vers);
        if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
-               if (ret == -EINVAL || ret == -EFAULT || ret > 0) {
-                       if (upgrade_fw(adap) >= 0) {
-                               /*
-                                * Note that the chip was reset as part of the
-                                * firmware upgrade so we don't reset it again
-                                * below and grab the new firmware version.
-                                */
-                               reset = 0;
-                               ret = t4_check_fw_version(adap);
-                       } else
-                               if (ret == -EFAULT) {
-                                       /*
-                                        * Firmware is old but still might
-                                        * work if we force reinitialization
-                                        * of the adapter. Ignoring FW upgrade
-                                        * failure.
-                                        */
-                                       dev_warn(adap->pdev_dev,
-                                                "Ignoring firmware upgrade "
-                                                "failure, and forcing driver "
-                                                "to reinitialize the "
-                                                "adapter.\n");
-                                       ret = 0;
-                               }
+               struct fw_info *fw_info;
+               struct fw_hdr *card_fw;
+               const struct firmware *fw;
+               const u8 *fw_data = NULL;
+               unsigned int fw_size = 0;
+
+               /* This is the firmware whose headers the driver was compiled
+                * against
+                */
+               fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip));
+               if (fw_info == NULL) {
+                       dev_err(adap->pdev_dev,
+                               "unable to get firmware info for chip %d.\n",
+                               CHELSIO_CHIP_VERSION(adap->params.chip));
+                       return -EINVAL;
                }
+
+               /* allocate memory to read the header of the firmware on the
+                * card
+                */
+               card_fw = t4_alloc_mem(sizeof(*card_fw));
+
+               /* Get FW from from /lib/firmware/ */
+               ret = request_firmware(&fw, fw_info->fw_mod_name,
+                                      adap->pdev_dev);
+               if (ret < 0) {
+                       dev_err(adap->pdev_dev,
+                               "unable to load firmware image %s, error %d\n",
+                               fw_info->fw_mod_name, ret);
+               } else {
+                       fw_data = fw->data;
+                       fw_size = fw->size;
+               }
+
+               /* upgrade FW logic */
+               ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw,
+                                state, &reset);
+
+               /* Cleaning up */
+               if (fw != NULL)
+                       release_firmware(fw);
+               t4_free_mem(card_fw);
+
                if (ret < 0)
-                       return ret;
+                       goto bye;
        }
 
        /*
@@ -5245,7 +5251,7 @@ static int adap_init0(struct adapter *adap)
                                if (ret == -ENOENT) {
                                        dev_info(adap->pdev_dev,
                                            "No Configuration File present "
-                                           "on adapter.  Using hard-wired "
+                                           "on adapter. Using hard-wired "
                                            "configuration parameters.\n");
                                        ret = adap_init0_no_config(adap, reset);
                                }
@@ -5787,7 +5793,7 @@ static void print_port_info(const struct net_device *dev)
 
        netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
                    adap->params.vpd.id,
-                   CHELSIO_CHIP_RELEASE(adap->params.rev), buf,
+                   CHELSIO_CHIP_RELEASE(adap->params.chip), buf,
                    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
                    (adap->flags & USING_MSIX) ? " MSI-X" :
                    (adap->flags & USING_MSI) ? " MSI" : "");
@@ -5910,7 +5916,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto out_unmap_bar0;
 
-       if (!is_t4(adapter->chip)) {
+       if (!is_t4(adapter->params.chip)) {
                s_qpp = QUEUESPERPAGEPF1 * adapter->fn;
                qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter,
                      SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
@@ -6064,7 +6070,7 @@ sriov:
  out_free_dev:
        free_some_resources(adapter);
  out_unmap_bar:
-       if (!is_t4(adapter->chip))
+       if (!is_t4(adapter->params.chip))
                iounmap(adapter->bar2);
  out_unmap_bar0:
        iounmap(adapter->regs);
@@ -6116,7 +6122,7 @@ static void remove_one(struct pci_dev *pdev)
 
                free_some_resources(adapter);
                iounmap(adapter->regs);
-               if (!is_t4(adapter->chip))
+               if (!is_t4(adapter->params.chip))
                        iounmap(adapter->bar2);
                kfree(adapter);
                pci_disable_pcie_error_reporting(pdev);
index ac311f5f3eb9590d1d9b5fb3bb0a9c3f0fac5ce7..cc380c36e1a8687cd1c7f3b4c3dbf2d0b8c1bf47 100644 (file)
@@ -509,7 +509,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
        u32 val;
        if (q->pend_cred >= 8) {
                val = PIDX(q->pend_cred / 8);
-               if (!is_t4(adap->chip))
+               if (!is_t4(adap->params.chip))
                        val |= DBTYPE(1);
                wmb();
                t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
@@ -847,7 +847,7 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
        wmb();            /* write descriptors before telling HW */
        spin_lock(&q->db_lock);
        if (!q->db_disabled) {
-               if (is_t4(adap->chip)) {
+               if (is_t4(adap->params.chip)) {
                        t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
                                     QID(q->cntxt_id) | PIDX(n));
                } else {
@@ -1596,7 +1596,7 @@ static noinline int handle_trace_pkt(struct adapter *adap,
                return 0;
        }
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                __skb_pull(skb, sizeof(struct cpl_trace_pkt));
        else
                __skb_pull(skb, sizeof(struct cpl_t5_trace_pkt));
@@ -1661,7 +1661,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
        const struct cpl_rx_pkt *pkt;
        struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
        struct sge *s = &q->adap->sge;
-       int cpl_trace_pkt = is_t4(q->adap->chip) ?
+       int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
                            CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
 
        if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
@@ -2182,7 +2182,7 @@ err:
 static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
 {
        q->cntxt_id = id;
-       if (!is_t4(adap->chip)) {
+       if (!is_t4(adap->params.chip)) {
                unsigned int s_qpp;
                unsigned short udb_density;
                unsigned long qpshift;
@@ -2641,7 +2641,7 @@ static int t4_sge_init_hard(struct adapter *adap)
         * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
         * and generate an interrupt when this occurs so we can recover.
         */
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
                                 V_HP_INT_THRESH(M_HP_INT_THRESH) |
                                 V_LP_INT_THRESH(M_LP_INT_THRESH),
index 4cbb2f9850be554c9ec48afd7479b4fcd9e5ebc2..74a6fce5a15a6914faf74bbf903dcc76ec717775 100644 (file)
@@ -296,7 +296,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        u32 mc_bist_cmd, mc_bist_cmd_addr, mc_bist_cmd_len;
        u32 mc_bist_status_rdata, mc_bist_data_pattern;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mc_bist_cmd = MC_BIST_CMD;
                mc_bist_cmd_addr = MC_BIST_CMD_ADDR;
                mc_bist_cmd_len = MC_BIST_CMD_LEN;
@@ -349,7 +349,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        u32 edc_bist_cmd, edc_bist_cmd_addr, edc_bist_cmd_len;
        u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                edc_bist_cmd = EDC_REG(EDC_BIST_CMD, idx);
                edc_bist_cmd_addr = EDC_REG(EDC_BIST_CMD_ADDR, idx);
                edc_bist_cmd_len = EDC_REG(EDC_BIST_CMD_LEN, idx);
@@ -402,7 +402,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
 static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
 {
        int i;
-       u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
+       u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
        /*
         * Setup offset into PCIE memory window.  Address must be a
@@ -863,104 +863,169 @@ unlock:
 }
 
 /**
- *     get_fw_version - read the firmware version
+ *     t4_get_fw_version - read the firmware version
  *     @adapter: the adapter
  *     @vers: where to place the version
  *
  *     Reads the FW version from flash.
  */
-static int get_fw_version(struct adapter *adapter, u32 *vers)
+int t4_get_fw_version(struct adapter *adapter, u32 *vers)
 {
-       return t4_read_flash(adapter, adapter->params.sf_fw_start +
-                            offsetof(struct fw_hdr, fw_ver), 1, vers, 0);
+       return t4_read_flash(adapter, FLASH_FW_START +
+                            offsetof(struct fw_hdr, fw_ver), 1,
+                            vers, 0);
 }
 
 /**
- *     get_tp_version - read the TP microcode version
+ *     t4_get_tp_version - read the TP microcode version
  *     @adapter: the adapter
  *     @vers: where to place the version
  *
  *     Reads the TP microcode version from flash.
  */
-static int get_tp_version(struct adapter *adapter, u32 *vers)
+int t4_get_tp_version(struct adapter *adapter, u32 *vers)
 {
-       return t4_read_flash(adapter, adapter->params.sf_fw_start +
+       return t4_read_flash(adapter, FLASH_FW_START +
                             offsetof(struct fw_hdr, tp_microcode_ver),
                             1, vers, 0);
 }
 
-/**
- *     t4_check_fw_version - check if the FW is compatible with this driver
- *     @adapter: the adapter
- *
- *     Checks if an adapter's FW is compatible with the driver.  Returns 0
- *     if there's exact match, a negative error if the version could not be
- *     read or there's a major version mismatch, and a positive value if the
- *     expected major version is found but there's a minor version mismatch.
+/* Is the given firmware API compatible with the one the driver was compiled
+ * with?
  */
-int t4_check_fw_version(struct adapter *adapter)
+static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
 {
-       u32 api_vers[2];
-       int ret, major, minor, micro;
-       int exp_major, exp_minor, exp_micro;
 
-       ret = get_fw_version(adapter, &adapter->params.fw_vers);
-       if (!ret)
-               ret = get_tp_version(adapter, &adapter->params.tp_vers);
-       if (!ret)
-               ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
-                                   offsetof(struct fw_hdr, intfver_nic),
-                                   2, api_vers, 1);
-       if (ret)
-               return ret;
+       /* short circuit if it's the exact same firmware version */
+       if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
+               return 1;
 
-       major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers);
-       minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
-       micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
+#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
+       if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
+           SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe))
+               return 1;
+#undef SAME_INTF
 
-       switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
-       case CHELSIO_T4:
-               exp_major = FW_VERSION_MAJOR;
-               exp_minor = FW_VERSION_MINOR;
-               exp_micro = FW_VERSION_MICRO;
-               break;
-       case CHELSIO_T5:
-               exp_major = FW_VERSION_MAJOR_T5;
-               exp_minor = FW_VERSION_MINOR_T5;
-               exp_micro = FW_VERSION_MICRO_T5;
-               break;
-       default:
-               dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
-                       adapter->chip);
-               return -EINVAL;
-       }
+       return 0;
+}
 
-       memcpy(adapter->params.api_vers, api_vers,
-              sizeof(adapter->params.api_vers));
+/* The firmware in the filesystem is usable, but should it be installed?
+ * This routine explains itself in detail if it indicates the filesystem
+ * firmware should be installed.
+ */
+static int should_install_fs_fw(struct adapter *adap, int card_fw_usable,
+                               int k, int c)
+{
+       const char *reason;
 
-       if (major < exp_major || (major == exp_major && minor < exp_minor) ||
-           (major == exp_major && minor == exp_minor && micro < exp_micro)) {
-               dev_err(adapter->pdev_dev,
-                       "Card has firmware version %u.%u.%u, minimum "
-                       "supported firmware is %u.%u.%u.\n", major, minor,
-                       micro, exp_major, exp_minor, exp_micro);
-               return -EFAULT;
+       if (!card_fw_usable) {
+               reason = "incompatible or unusable";
+               goto install;
        }
 
-       if (major != exp_major) {            /* major mismatch - fail */
-               dev_err(adapter->pdev_dev,
-                       "card FW has major version %u, driver wants %u\n",
-                       major, exp_major);
-               return -EINVAL;
+       if (k > c) {
+               reason = "older than the version supported with this driver";
+               goto install;
        }
 
-       if (minor == exp_minor && micro == exp_micro)
-               return 0;                                   /* perfect match */
+       return 0;
+
+install:
+       dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, "
+               "installing firmware %u.%u.%u.%u on card.\n",
+               FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
+               FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason,
+               FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
+               FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
 
-       /* Minor/micro version mismatch.  Report it but often it's OK. */
        return 1;
 }
 
+int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state,
+              int *reset)
+{
+       int ret, card_fw_usable, fs_fw_usable;
+       const struct fw_hdr *fs_fw;
+       const struct fw_hdr *drv_fw;
+
+       drv_fw = &fw_info->fw_hdr;
+
+       /* Read the header of the firmware on the card */
+       ret = -t4_read_flash(adap, FLASH_FW_START,
+                           sizeof(*card_fw) / sizeof(uint32_t),
+                           (uint32_t *)card_fw, 1);
+       if (ret == 0) {
+               card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
+       } else {
+               dev_err(adap->pdev_dev,
+                       "Unable to read card's firmware header: %d\n", ret);
+               card_fw_usable = 0;
+       }
+
+       if (fw_data != NULL) {
+               fs_fw = (const void *)fw_data;
+               fs_fw_usable = fw_compatible(drv_fw, fs_fw);
+       } else {
+               fs_fw = NULL;
+               fs_fw_usable = 0;
+       }
+
+       if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
+           (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
+               /* Common case: the firmware on the card is an exact match and
+                * the filesystem one is an exact match too, or the filesystem
+                * one is absent/incompatible.
+                */
+       } else if (fs_fw_usable && state == DEV_STATE_UNINIT &&
+                  should_install_fs_fw(adap, card_fw_usable,
+                                       be32_to_cpu(fs_fw->fw_ver),
+                                       be32_to_cpu(card_fw->fw_ver))) {
+               ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
+                                    fw_size, 0);
+               if (ret != 0) {
+                       dev_err(adap->pdev_dev,
+                               "failed to install firmware: %d\n", ret);
+                       goto bye;
+               }
+
+               /* Installed successfully, update the cached header too. */
+               memcpy(card_fw, fs_fw, sizeof(*card_fw));
+               card_fw_usable = 1;
+               *reset = 0;     /* already reset as part of load_fw */
+       }
+
+       if (!card_fw_usable) {
+               uint32_t d, c, k;
+
+               d = be32_to_cpu(drv_fw->fw_ver);
+               c = be32_to_cpu(card_fw->fw_ver);
+               k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
+
+               dev_err(adap->pdev_dev, "Cannot find a usable firmware: "
+                       "chip state %d, "
+                       "driver compiled with %d.%d.%d.%d, "
+                       "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
+                       state,
+                       FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d),
+                       FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d),
+                       FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
+                       FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c),
+                       FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
+                       FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
+               ret = EINVAL;
+               goto bye;
+       }
+
+       /* We're using whatever's on the card and it's known to be good. */
+       adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver);
+       adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
+
+bye:
+       return ret;
+}
+
 /**
  *     t4_flash_erase_sectors - erase a range of flash sectors
  *     @adapter: the adapter
@@ -1368,7 +1433,7 @@ static void pcie_intr_handler(struct adapter *adapter)
                                    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
                                    pcie_port_intr_info) +
              t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
-                                   is_t4(adapter->chip) ?
+                                   is_t4(adapter->params.chip) ?
                                    pcie_intr_info : t5_pcie_intr_info);
 
        if (fat)
@@ -1782,7 +1847,7 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
 {
        u32 v, int_cause_reg;
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                int_cause_reg = PORT_REG(port, XGMAC_PORT_INT_CAUSE);
        else
                int_cause_reg = T5_PORT_REG(port, MAC_PORT_INT_CAUSE);
@@ -2250,7 +2315,7 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
 
 #define GET_STAT(name) \
        t4_read_reg64(adap, \
-       (is_t4(adap->chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
+       (is_t4(adap->params.chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
        T5_PORT_REG(idx, MPS_PORT_STAT_##name##_L)))
 #define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
 
@@ -2332,7 +2397,7 @@ void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
 {
        u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO);
                mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI);
                port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
@@ -2374,7 +2439,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
        int i;
        u32 port_cfg_reg;
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
        else
                port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2);
@@ -2387,7 +2452,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
                return -EINVAL;
 
 #define EPIO_REG(name) \
-       (is_t4(adap->chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
+       (is_t4(adap->params.chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
        T5_PORT_REG(port, MAC_PORT_EPIO_##name))
 
        t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
@@ -2474,7 +2539,7 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
 int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
 {
        int i, off;
-       u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
+       u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
        /* Align on a 2KB boundary.
         */
@@ -3306,7 +3371,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
        int i, ret;
        struct fw_vi_mac_cmd c;
        struct fw_vi_mac_exact *p;
-       unsigned int max_naddr = is_t4(adap->chip) ?
+       unsigned int max_naddr = is_t4(adap->params.chip) ?
                                       NUM_MPS_CLS_SRAM_L_INSTANCES :
                                       NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -3368,7 +3433,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
        int ret, mode;
        struct fw_vi_mac_cmd c;
        struct fw_vi_mac_exact *p = c.u.exact;
-       unsigned int max_mac_addr = is_t4(adap->chip) ?
+       unsigned int max_mac_addr = is_t4(adap->params.chip) ?
                                    NUM_MPS_CLS_SRAM_L_INSTANCES :
                                    NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -3699,13 +3764,14 @@ int t4_prep_adapter(struct adapter *adapter)
 {
        int ret, ver;
        uint16_t device_id;
+       u32 pl_rev;
 
        ret = t4_wait_dev_ready(adapter);
        if (ret < 0)
                return ret;
 
        get_pci_mode(adapter, &adapter->params.pci);
-       adapter->params.rev = t4_read_reg(adapter, PL_REV);
+       pl_rev = G_REV(t4_read_reg(adapter, PL_REV));
 
        ret = get_flash_params(adapter);
        if (ret < 0) {
@@ -3717,14 +3783,13 @@ int t4_prep_adapter(struct adapter *adapter)
         */
        pci_read_config_word(adapter->pdev, PCI_DEVICE_ID, &device_id);
        ver = device_id >> 12;
+       adapter->params.chip = 0;
        switch (ver) {
        case CHELSIO_T4:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4,
-                                                 adapter->params.rev);
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
                break;
        case CHELSIO_T5:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5,
-                                                 adapter->params.rev);
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
                break;
        default:
                dev_err(adapter->pdev_dev, "Device %d is not supported\n",
@@ -3732,9 +3797,6 @@ int t4_prep_adapter(struct adapter *adapter)
                return -EINVAL;
        }
 
-       /* Reassign the updated revision field */
-       adapter->params.rev = adapter->chip;
-
        init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
 
        /*
index ef146c0ba4814ef5abff64794075b9d5e806c62b..0a8205d69d2c290aae4dbec30245c9dc3e18bd39 100644 (file)
 
 #define PL_REV 0x1943c
 
+#define S_REV    0
+#define M_REV    0xfU
+#define V_REV(x) ((x) << S_REV)
+#define G_REV(x) (((x) >> S_REV) & M_REV)
+
 #define LE_DB_CONFIG 0x19c04
 #define  HASHEN 0x00100000U
 
 #define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
 #define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
 
+#define A_PL_VF_REV 0x4
+#define A_PL_VF_WHOAMI 0x0
+#define A_PL_VF_REVISION 0x8
+
+#define S_CHIPID    4
+#define M_CHIPID    0xfU
+#define V_CHIPID(x) ((x) << S_CHIPID)
+#define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
+
 #endif /* __T4_REGS_H */
index 6f77ac487743edfbe899f470805f58cc38d9c61b..74fea74ce0aa25a676045868fa0b48c4a3800860 100644 (file)
@@ -2157,7 +2157,7 @@ struct fw_debug_cmd {
 
 struct fw_hdr {
        u8 ver;
-       u8 reserved1;
+       u8 chip;                        /* terminator chip type */
        __be16  len512;                 /* bin length in units of 512-bytes */
        __be32  fw_ver;                 /* firmware version */
        __be32  tp_microcode_ver;
@@ -2176,6 +2176,11 @@ struct fw_hdr {
        __be32  reserved6[23];
 };
 
+enum fw_hdr_chip {
+       FW_HDR_CHIP_T4,
+       FW_HDR_CHIP_T5
+};
+
 #define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
 #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
 #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
index be5c7ef6ca939654365b6aec6dc108e03e0f74d9..68eaa9c88c7d8a77646bd217e00877a281254a59 100644 (file)
@@ -344,7 +344,6 @@ struct adapter {
        unsigned long registered_device_map;
        unsigned long open_device_map;
        unsigned long flags;
-       enum chip_type chip;
        struct adapter_params params;
 
        /* queue and interrupt resources */
index 5f90ec5f7519a4ac6e7916396cff31446f5c614b..0899c098359446346f7abe1939ac214705fd0acb 100644 (file)
@@ -1064,7 +1064,7 @@ static inline unsigned int mk_adap_vers(const struct adapter *adapter)
        /*
         * Chip version 4, revision 0x3f (cxgb4vf).
         */
-       return CHELSIO_CHIP_VERSION(adapter->chip) | (0x3f << 10);
+       return CHELSIO_CHIP_VERSION(adapter->params.chip) | (0x3f << 10);
 }
 
 /*
@@ -1551,9 +1551,13 @@ static void cxgb4vf_get_regs(struct net_device *dev,
        reg_block_dump(adapter, regbuf,
                       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_FIRST,
                       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_LAST);
+
+       /* T5 adds new registers in the PL Register map.
+        */
        reg_block_dump(adapter, regbuf,
                       T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_FIRST,
-                      T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_LAST);
+                      T4VF_PL_BASE_ADDR + (is_t4(adapter->params.chip)
+                      ? A_PL_VF_WHOAMI : A_PL_VF_REVISION));
        reg_block_dump(adapter, regbuf,
                       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_FIRST,
                       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_LAST);
@@ -2087,6 +2091,7 @@ static int adap_init0(struct adapter *adapter)
        unsigned int ethqsets;
        int err;
        u32 param, val = 0;
+       unsigned int chipid;
 
        /*
         * Wait for the device to become ready before proceeding ...
@@ -2114,12 +2119,14 @@ static int adap_init0(struct adapter *adapter)
                return err;
        }
 
+       adapter->params.chip = 0;
        switch (adapter->pdev->device >> 12) {
        case CHELSIO_T4:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
+               adapter->params.chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
                break;
        case CHELSIO_T5:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, 0);
+               chipid = G_REV(t4_read_reg(adapter, A_PL_VF_REV));
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, chipid);
                break;
        }
 
index 8475c4cda9e4ca72ef8a2b309788620e82fb67d3..0a89963c48ce78148d1abe6cd86151e850c24062 100644 (file)
@@ -537,7 +537,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
         */
        if (fl->pend_cred >= FL_PER_EQ_UNIT) {
                val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT);
-               if (!is_t4(adapter->chip))
+               if (!is_t4(adapter->params.chip))
                        val |= DBTYPE(1);
                wmb();
                t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
index 53cbfed21d0b9871fe257ee75836dc2dadbdc185..61362450d05b4f83daeacf9a0c54ebed35e2da4c 100644 (file)
 #include "../cxgb4/t4fw_api.h"
 
 #define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
 #define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
 
+/* All T4 and later chips have their PCI-E Device IDs encoded as 0xVFPP where:
+ *
+ *   V  = "4" for T4; "5" for T5, etc. or
+ *      = "a" for T4 FPGA; "b" for T4 FPGA, etc.
+ *   F  = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs
+ *   PP = adapter product designation
+ */
 #define CHELSIO_T4             0x4
 #define CHELSIO_T5             0x5
 
 enum chip_type {
-       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
-       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
-       T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
        T4_FIRST_REV    = T4_A1,
-       T4_LAST_REV     = T4_A3,
+       T4_LAST_REV     = T4_A2,
 
-       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
-       T5_FIRST_REV    = T5_A1,
+       T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+       T5_FIRST_REV    = T5_A0,
        T5_LAST_REV     = T5_A1,
 };
 
@@ -203,6 +210,7 @@ struct adapter_params {
        struct vpd_params vpd;          /* Vital Product Data */
        struct rss_params rss;          /* Receive Side Scaling */
        struct vf_resources vfres;      /* Virtual Function Resource limits */
+       enum chip_type chip;            /* chip code */
        u8 nports;                      /* # of Ethernet "ports" */
 };
 
@@ -253,7 +261,7 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
 
 static inline int is_t4(enum chip_type chip)
 {
-       return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
 }
 
 int t4vf_wait_dev_ready(struct adapter *);
index 9f96dc3bb11203e0781faa785d12ec31df4f76f3..d958c44341b5cb299d704600494de5be9d15bb72 100644 (file)
@@ -1027,7 +1027,7 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
        unsigned nfilters = 0;
        unsigned int rem = naddr;
        struct fw_vi_mac_cmd cmd, rpl;
-       unsigned int max_naddr = is_t4(adapter->chip) ?
+       unsigned int max_naddr = is_t4(adapter->params.chip) ?
                                 NUM_MPS_CLS_SRAM_L_INSTANCES :
                                 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -1121,7 +1121,7 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid,
        struct fw_vi_mac_exact *p = &cmd.u.exact[0];
        size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
                                             u.exact[1]), 16);
-       unsigned int max_naddr = is_t4(adapter->chip) ?
+       unsigned int max_naddr = is_t4(adapter->params.chip) ?
                                 NUM_MPS_CLS_SRAM_L_INSTANCES :
                                 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
index f4825db5d1792419924bab4f9d08e17abbfd6128..5878df619b531ad0b3ea96167f53e8909ff9fd21 100644 (file)
@@ -503,6 +503,7 @@ struct be_adapter {
 };
 
 #define be_physfn(adapter)             (!adapter->virtfn)
+#define be_virtfn(adapter)             (adapter->virtfn)
 #define        sriov_enabled(adapter)          (adapter->num_vfs > 0)
 #define sriov_want(adapter)             (be_physfn(adapter) && \
                                         (num_vfs || pci_num_vf(adapter->pdev)))
index dbcd5262c0167c1ae0dacf7dd578b5c3a2a43ce5..e0e8bc1ef14c47e93336df2c784d1ff14e6b4143 100644 (file)
@@ -1032,6 +1032,13 @@ int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
        } else {
                req->hdr.version = 2;
                req->page_size = 1; /* 1 for 4K */
+
+               /* coalesce-wm field in this cmd is not relevant to Lancer.
+                * Lancer uses COMMON_MODIFY_CQ to set this field
+                */
+               if (!lancer_chip(adapter))
+                       AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+                                     ctxt, coalesce_wm);
                AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
                                                                no_delay);
                AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
index 3e2162121601e79481428c4d7ca02c3523dc0e33..dc88782185f26f000e4e58cd793f90f6064bbfb6 100644 (file)
@@ -64,6 +64,9 @@
 #define SLIPORT_ERROR_NO_RESOURCE1     0x2
 #define SLIPORT_ERROR_NO_RESOURCE2     0x9
 
+#define SLIPORT_ERROR_FW_RESET1                0x2
+#define SLIPORT_ERROR_FW_RESET2                0x0
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET     0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
index abde97471636918a6b7e2381634cdc743678d24c..0fde69d5cb6afd610db5f2a57325e5d2e9f5ed94 100644 (file)
@@ -2464,8 +2464,16 @@ void be_detect_error(struct be_adapter *adapter)
         */
        if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
                adapter->hw_error = true;
-               dev_err(&adapter->pdev->dev,
-                       "Error detected in the card\n");
+               /* Do not log error messages if its a FW reset */
+               if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
+                   sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
+                       dev_info(&adapter->pdev->dev,
+                                "Firmware update in progress\n");
+                       return;
+               } else {
+                       dev_err(&adapter->pdev->dev,
+                               "Error detected in the card\n");
+               }
        }
 
        if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
@@ -2658,8 +2666,8 @@ static int be_close(struct net_device *netdev)
 
        be_roce_dev_close(adapter);
 
-       for_all_evt_queues(adapter, eqo, i) {
-               if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
+       if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
+               for_all_evt_queues(adapter, eqo, i) {
                        napi_disable(&eqo->napi);
                        be_disable_busy_poll(eqo);
                }
@@ -2932,28 +2940,35 @@ static void be_cancel_worker(struct be_adapter *adapter)
        }
 }
 
-static int be_clear(struct be_adapter *adapter)
+static void be_mac_clear(struct be_adapter *adapter)
 {
        int i;
 
+       if (adapter->pmac_id) {
+               for (i = 0; i < (adapter->uc_macs + 1); i++)
+                       be_cmd_pmac_del(adapter, adapter->if_handle,
+                                       adapter->pmac_id[i], 0);
+               adapter->uc_macs = 0;
+
+               kfree(adapter->pmac_id);
+               adapter->pmac_id = NULL;
+       }
+}
+
+static int be_clear(struct be_adapter *adapter)
+{
        be_cancel_worker(adapter);
 
        if (sriov_enabled(adapter))
                be_vf_clear(adapter);
 
        /* delete the primary mac along with the uc-mac list */
-       for (i = 0; i < (adapter->uc_macs + 1); i++)
-               be_cmd_pmac_del(adapter, adapter->if_handle,
-                               adapter->pmac_id[i], 0);
-       adapter->uc_macs = 0;
+       be_mac_clear(adapter);
 
        be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
        be_clear_queues(adapter);
 
-       kfree(adapter->pmac_id);
-       adapter->pmac_id = NULL;
-
        be_msix_disable(adapter);
        return 0;
 }
@@ -3253,12 +3268,10 @@ static int be_mac_setup(struct be_adapter *adapter)
                memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
        }
 
-       /* On BE3 VFs this cmd may fail due to lack of privilege.
-        * Ignore the failure as in this case pmac_id is fetched
-        * in the IFACE_CREATE cmd.
-        */
-       be_cmd_pmac_add(adapter, mac, adapter->if_handle,
-                       &adapter->pmac_id[0], 0);
+       /* For BE3-R VFs, the PF programs the initial MAC address */
+       if (!(BEx_chip(adapter) && be_virtfn(adapter)))
+               be_cmd_pmac_add(adapter, mac, adapter->if_handle,
+                               &adapter->pmac_id[0], 0);
        return 0;
 }
 
@@ -3814,6 +3827,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
        }
 
        if (change_status == LANCER_FW_RESET_NEEDED) {
+               dev_info(&adapter->pdev->dev,
+                        "Resetting adapter to activate new FW\n");
                status = lancer_physdev_ctrl(adapter,
                                             PHYSDEV_CONTROL_FW_RESET_MASK);
                if (status) {
@@ -4365,13 +4380,13 @@ static int lancer_recover_func(struct be_adapter *adapter)
                        goto err;
        }
 
-       dev_err(dev, "Error recovery successful\n");
+       dev_err(dev, "Adapter recovery successful\n");
        return 0;
 err:
        if (status == -EAGAIN)
                dev_err(dev, "Waiting for resource provisioning\n");
        else
-               dev_err(dev, "Error recovery failed\n");
+               dev_err(dev, "Adapter recovery failed\n");
 
        return status;
 }
@@ -4599,6 +4614,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
        if (adapter->wol)
                be_setup_wol(adapter, true);
 
+       be_intr_set(adapter, false);
        cancel_delayed_work_sync(&adapter->func_recovery_work);
 
        netif_device_detach(netdev);
@@ -4634,6 +4650,7 @@ static int be_resume(struct pci_dev *pdev)
        if (status)
                return status;
 
+       be_intr_set(adapter, true);
        /* tell fw we're ready to fire cmds */
        status = be_cmd_fw_init(adapter);
        if (status)
index 4cbebf3d80eb1492d847f1ad8a9888e2a6c17b97..e7c8b749c5a53f969096e3f442195d88f82597d7 100644 (file)
@@ -98,10 +98,6 @@ static void set_multicast_list(struct net_device *ndev);
  * detected as not set during a prior frame transmission, then the
  * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
  * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
- * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
- * detected as not set during a prior frame transmission, then the
- * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
- * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
  * frames not being transmitted until there is a 0-to-1 transition on
  * ENET_TDAR[TDAR].
  */
@@ -385,7 +381,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
         * data.
         */
        bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
-                       FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+                       skb->len, DMA_TO_DEVICE);
        if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
                bdp->cbd_bufaddr = 0;
                fep->tx_skbuff[index] = NULL;
@@ -779,11 +775,10 @@ fec_enet_tx(struct net_device *ndev)
                else
                        index = bdp - fep->tx_bd_base;
 
-               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-                               FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-               bdp->cbd_bufaddr = 0;
-
                skb = fep->tx_skbuff[index];
+               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
+                               DMA_TO_DEVICE);
+               bdp->cbd_bufaddr = 0;
 
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
index 2d1c6bdd36189f9f595ada15599301ce992330a9..7628e0fd84554fd56eca5f4181f2ff31c85eca0d 100644 (file)
@@ -3033,7 +3033,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 
        dev->hw_features = NETIF_F_SG | NETIF_F_TSO |
                      NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX;
-       dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO |
+       dev->features = NETIF_F_SG | NETIF_F_TSO |
                      NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
                      NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
                      NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM;
index 58c147271a362e68914d55d97b71b327b194e86b..f9313b36c88716068611b44d3c7a6b182d4277e9 100644 (file)
@@ -83,6 +83,11 @@ struct e1000_adapter;
 
 #define E1000_MAX_INTR                 10
 
+/*
+ * Count for polling __E1000_RESET condition every 10-20msec.
+ */
+#define E1000_CHECK_RESET_COUNT        50
+
 /* TX/RX descriptor defines */
 #define E1000_DEFAULT_TXD              256
 #define E1000_MAX_TXD                  256
@@ -312,8 +317,6 @@ struct e1000_adapter {
        struct delayed_work watchdog_task;
        struct delayed_work fifo_stall_task;
        struct delayed_work phy_info_task;
-
-       struct mutex mutex;
 };
 
 enum e1000_state_t {
index e38622825fa7336ae74f64229f3e5619cb668335..46e6544ed1b7f5c1ba9367dd1dfe444d725cd0e3 100644 (file)
@@ -494,13 +494,20 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
 {
        set_bit(__E1000_DOWN, &adapter->flags);
 
-       /* Only kill reset task if adapter is not resetting */
-       if (!test_bit(__E1000_RESETTING, &adapter->flags))
-               cancel_work_sync(&adapter->reset_task);
-
        cancel_delayed_work_sync(&adapter->watchdog_task);
+
+       /*
+        * Since the watchdog task can reschedule other tasks, we should cancel
+        * it first, otherwise we can run into the situation when a work is
+        * still running after the adapter has been turned down.
+        */
+
        cancel_delayed_work_sync(&adapter->phy_info_task);
        cancel_delayed_work_sync(&adapter->fifo_stall_task);
+
+       /* Only kill reset task if adapter is not resetting */
+       if (!test_bit(__E1000_RESETTING, &adapter->flags))
+               cancel_work_sync(&adapter->reset_task);
 }
 
 void e1000_down(struct e1000_adapter *adapter)
@@ -544,21 +551,8 @@ void e1000_down(struct e1000_adapter *adapter)
        e1000_clean_all_rx_rings(adapter);
 }
 
-static void e1000_reinit_safe(struct e1000_adapter *adapter)
-{
-       while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-               msleep(1);
-       mutex_lock(&adapter->mutex);
-       e1000_down(adapter);
-       e1000_up(adapter);
-       mutex_unlock(&adapter->mutex);
-       clear_bit(__E1000_RESETTING, &adapter->flags);
-}
-
 void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
-       /* if rtnl_lock is not held the call path is bogus */
-       ASSERT_RTNL();
        WARN_ON(in_interrupt());
        while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
                msleep(1);
@@ -1316,7 +1310,6 @@ static int e1000_sw_init(struct e1000_adapter *adapter)
        e1000_irq_disable(adapter);
 
        spin_lock_init(&adapter->stats_lock);
-       mutex_init(&adapter->mutex);
 
        set_bit(__E1000_DOWN, &adapter->flags);
 
@@ -1440,6 +1433,10 @@ static int e1000_close(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
+       int count = E1000_CHECK_RESET_COUNT;
+
+       while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+               usleep_range(10000, 20000);
 
        WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
        e1000_down(adapter);
@@ -2325,11 +2322,8 @@ static void e1000_update_phy_info_task(struct work_struct *work)
        struct e1000_adapter *adapter = container_of(work,
                                                     struct e1000_adapter,
                                                     phy_info_task.work);
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-       mutex_lock(&adapter->mutex);
+
        e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
-       mutex_unlock(&adapter->mutex);
 }
 
 /**
@@ -2345,9 +2339,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
        struct net_device *netdev = adapter->netdev;
        u32 tctl;
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-       mutex_lock(&adapter->mutex);
        if (atomic_read(&adapter->tx_fifo_stall)) {
                if ((er32(TDT) == er32(TDH)) &&
                   (er32(TDFT) == er32(TDFH)) &&
@@ -2368,7 +2359,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
                        schedule_delayed_work(&adapter->fifo_stall_task, 1);
                }
        }
-       mutex_unlock(&adapter->mutex);
 }
 
 bool e1000_has_link(struct e1000_adapter *adapter)
@@ -2422,10 +2412,6 @@ static void e1000_watchdog(struct work_struct *work)
        struct e1000_tx_ring *txdr = adapter->tx_ring;
        u32 link, tctl;
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-
-       mutex_lock(&adapter->mutex);
        link = e1000_has_link(adapter);
        if ((netif_carrier_ok(netdev)) && link)
                goto link_up;
@@ -2516,7 +2502,7 @@ link_up:
                        adapter->tx_timeout_count++;
                        schedule_work(&adapter->reset_task);
                        /* exit immediately since reset is imminent */
-                       goto unlock;
+                       return;
                }
        }
 
@@ -2544,9 +2530,6 @@ link_up:
        /* Reschedule the task */
        if (!test_bit(__E1000_DOWN, &adapter->flags))
                schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
-
-unlock:
-       mutex_unlock(&adapter->mutex);
 }
 
 enum latency_range {
@@ -3495,10 +3478,8 @@ static void e1000_reset_task(struct work_struct *work)
        struct e1000_adapter *adapter =
                container_of(work, struct e1000_adapter, reset_task);
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
        e_err(drv, "Reset adapter\n");
-       e1000_reinit_safe(adapter);
+       e1000_reinit_locked(adapter);
 }
 
 /**
@@ -4963,6 +4944,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        netif_device_detach(netdev);
 
        if (netif_running(netdev)) {
+               int count = E1000_CHECK_RESET_COUNT;
+
+               while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+                       usleep_range(10000, 20000);
+
                WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
                e1000_down(adapter);
        }
index be15938ba2130372192276670e1621c3e470505c..12b0932204ba8ce425109714053d4bebbddc65b6 100644 (file)
@@ -354,6 +354,9 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
        struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
        int i;
 
+       if (!vsi->tx_rings)
+               return stats;
+
        rcu_read_lock();
        for (i = 0; i < vsi->num_queue_pairs; i++) {
                struct i40e_ring *tx_ring, *rx_ring;
index c4c4fe332c7ee06af09696cc8e5ba027d6d9ba15..ad2b74d95138c1542bb78a55b7d620e5695f2abb 100644 (file)
@@ -1728,7 +1728,10 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               mdelay(usec_interval/1000);
+                       else
+                               udelay(usec_interval);
                }
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
index b0f3666b1d7f1c669181a9f62534aa8096baeccc..c3143da497c82be85c4f580776290872e647e317 100644 (file)
@@ -2062,14 +2062,15 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       wol->supported = WAKE_UCAST | WAKE_MCAST |
-                        WAKE_BCAST | WAKE_MAGIC |
-                        WAKE_PHY;
        wol->wolopts = 0;
 
        if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
                return;
 
+       wol->supported = WAKE_UCAST | WAKE_MCAST |
+                        WAKE_BCAST | WAKE_MAGIC |
+                        WAKE_PHY;
+
        /* apply any specific unsupported masks here */
        switch (adapter->hw.device_id) {
        default:
index 0c55079ebee37c03d0a5a9a5cbdc6681d78c19a9..cc06854296a379a6f5d1fac21ecf9412d94d477b 100644 (file)
@@ -4251,8 +4251,8 @@ static void ixgbe_disable_fwd_ring(struct ixgbe_fwd_adapter *vadapter,
        rx_ring->l2_accel_priv = NULL;
 }
 
-int ixgbe_fwd_ring_down(struct net_device *vdev,
-                       struct ixgbe_fwd_adapter *accel)
+static int ixgbe_fwd_ring_down(struct net_device *vdev,
+                              struct ixgbe_fwd_adapter *accel)
 {
        struct ixgbe_adapter *adapter = accel->real_adapter;
        unsigned int rxbase = accel->rx_base_queue;
@@ -7986,10 +7986,9 @@ skip_sriov:
                           NETIF_F_TSO |
                           NETIF_F_TSO6 |
                           NETIF_F_RXHASH |
-                          NETIF_F_RXCSUM |
-                          NETIF_F_HW_L2FW_DOFFLOAD;
+                          NETIF_F_RXCSUM;
 
-       netdev->hw_features = netdev->features;
+       netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
 
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82599EB:
index e4c676006be97db79d3208607f36bb503bdaecaa..39217e5ff7dcd74ddcfc49c7e33e43ec2633c515 100644 (file)
@@ -46,6 +46,7 @@ static bool ixgbe_get_i2c_data(u32 *i2cctl);
 static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
 static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
 static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
+static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 
 /**
  *  ixgbe_identify_phy_generic - Get physical layer module
@@ -1164,7 +1165,7 @@ err_read_i2c_eeprom:
  *
  * Searches for and identifies the QSFP module and assigns appropriate PHY type
  **/
-s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
+static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
 {
        struct ixgbe_adapter *adapter = hw->back;
        s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
index aae900a256da98601a501a121eed1f14347d3997..fffcbdd2bf0e49ab129abf04cd16a650a4d5cb91 100644 (file)
@@ -145,7 +145,6 @@ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
 s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
 s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
-s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                                         u16 *list_offset,
                                         u16 *data_offset);
index b8e232b4ea2da88aca164039f81f1852ba9f779e..d5f0d72e5e331792bb8a0078078627df66a83fb5 100644 (file)
@@ -1378,7 +1378,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
 
                dev_kfree_skb_any(skb);
                dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
-                                rx_desc->data_size, DMA_FROM_DEVICE);
+                                MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
        }
 
        if (rx_done)
@@ -1424,7 +1424,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
                }
 
                dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
-                                rx_desc->data_size, DMA_FROM_DEVICE);
+                                MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
 
                rx_bytes = rx_desc->data_size -
                        (ETH_FCS_LEN + MVNETA_MH_SIZE);
index 40626690e8a8679d9812d4edee4ede897ec55a2a..c11d063473e5f9aaa162aacd32b4cac386d53464 100644 (file)
@@ -140,7 +140,6 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
-       struct mlx4_en_tx_ring *tx_ring;
        int i, carrier_ok;
 
        memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
@@ -150,16 +149,10 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
                carrier_ok = netif_carrier_ok(dev);
 
                netif_carrier_off(dev);
-retry_tx:
                /* Wait until all tx queues are empty.
                 * there should not be any additional incoming traffic
                 * since we turned the carrier off */
                msleep(200);
-               for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
-                       tx_ring = priv->tx_ring[i];
-                       if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
-                               goto retry_tx;
-               }
 
                if (priv->mdev->dev->caps.flags &
                                        MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
index 5789ea2c934d4aaa15218bdaea2d565f42a82b41..01fc6515384db04fe03d548db8c16f8952f211e4 100644 (file)
@@ -2635,6 +2635,8 @@ static int __init mlx4_init(void)
                return -ENOMEM;
 
        ret = pci_register_driver(&mlx4_driver);
+       if (ret < 0)
+               destroy_workqueue(mlx4_wq);
        return ret < 0 ? ret : 0;
 }
 
index 2d045be4b5cf64a5921a6687b127609093df376e..1e8b9514718b8620859bc38025dbb878878dd0c0 100644 (file)
@@ -5150,8 +5150,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       int result;
-       memset(buffer, 0, nv_get_sset_count(dev, ETH_SS_TEST)*sizeof(u64));
+       int result, count;
+
+       count = nv_get_sset_count(dev, ETH_SS_TEST);
+       memset(buffer, 0, count * sizeof(u64));
 
        if (!nv_link_test(dev)) {
                test->flags |= ETH_TEST_FL_FAILED;
@@ -5195,7 +5197,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        return;
                }
 
-               if (!nv_loopback_test(dev)) {
+               if (count > NV_TEST_COUNT_BASE && !nv_loopback_test(dev)) {
                        test->flags |= ETH_TEST_FL_FAILED;
                        buffer[3] = 1;
                }
index b1cb0ffb15c70d1970f3cbebab28ff7f8e8530ce..6055d397a29edf70317299e83966aba18b6ff5dc 100644 (file)
@@ -447,8 +447,9 @@ irqreturn_t qlcnic_83xx_intr(int irq, void *data)
 
        qlcnic_83xx_poll_process_aen(adapter);
 
-       if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
-               ahw->diag_cnt++;
+       if (ahw->diag_test) {
+               if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
+                       ahw->diag_cnt++;
                qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
                return IRQ_HANDLED;
        }
@@ -1345,11 +1346,6 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
        }
 
        if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               /* disable and free mailbox interrupt */
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       qlcnic_83xx_enable_mbx_poll(adapter);
-                       qlcnic_83xx_free_mbx_intr(adapter);
-               }
                adapter->ahw->loopback_state = 0;
                adapter->ahw->hw_ops->setup_link_event(adapter, 1);
        }
@@ -1363,33 +1359,20 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
-       int ring, err;
+       int ring;
 
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_83xx_disable_intr(adapter, sds_ring);
-                       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-                               qlcnic_83xx_enable_mbx_poll(adapter);
+                       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+                               qlcnic_83xx_disable_intr(adapter, sds_ring);
                }
        }
 
        qlcnic_fw_destroy_ctx(adapter);
        qlcnic_detach(adapter);
 
-       if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       err = qlcnic_83xx_setup_mbx_intr(adapter);
-                       qlcnic_83xx_disable_mbx_poll(adapter);
-                       if (err) {
-                               dev_err(&adapter->pdev->dev,
-                                       "%s: failed to setup mbx interrupt\n",
-                                       __func__);
-                               goto out;
-                       }
-               }
-       }
        adapter->ahw->diag_test = 0;
        adapter->drv_sds_rings = drv_sds_rings;
 
@@ -1399,9 +1382,6 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
        if (netif_running(netdev))
                __qlcnic_up(adapter, netdev);
 
-       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
-           !(adapter->flags & QLCNIC_MSIX_ENABLED))
-               qlcnic_83xx_disable_mbx_poll(adapter);
 out:
        netif_device_attach(netdev);
 }
@@ -3754,6 +3734,19 @@ static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
        return;
 }
 
+static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 offset;
+
+       offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
+       dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
+                readl(ahw->pci_base0 + offset),
+                QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
+                QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
+                QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
+}
+
 static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
 {
        struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
@@ -3798,6 +3791,8 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
                                __func__, cmd->cmd_op, cmd->type, ahw->pci_func,
                                ahw->op_mode);
                        clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+                       qlcnic_dump_mailbox_registers(adapter);
+                       qlcnic_83xx_get_mbx_data(adapter, cmd);
                        qlcnic_dump_mbx(adapter, cmd);
                        qlcnic_83xx_idc_request_reset(adapter,
                                                      QLCNIC_FORCE_FW_DUMP_KEY);
index 4cae6caa6bfa42476ff79b881784dd2f42a36db6..a6a33508e40137b124541f07e3433361b086afec 100644 (file)
@@ -662,4 +662,5 @@ pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
                                               pci_channel_state_t);
 pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
 void qlcnic_83xx_io_resume(struct pci_dev *);
+void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
 #endif
index 89208e5b25d6a1bc5c829a52ea2d79edcb5d110e..918e18ddf0381acd2f8a3097603ec6bd914fc5a8 100644 (file)
@@ -740,6 +740,7 @@ static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)
        adapter->ahw->idc.err_code = -EIO;
        dev_err(&adapter->pdev->dev,
                "%s: Device in unknown state\n", __func__);
+       clear_bit(__QLCNIC_RESETTING, &adapter->state);
        return 0;
 }
 
@@ -818,7 +819,6 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_mailbox *mbx = ahw->mailbox;
        int ret = 0;
-       u32 owner;
        u32 val;
 
        /* Perform NIC configuration based ready state entry actions */
@@ -848,9 +848,9 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
                        set_bit(__QLCNIC_RESETTING, &adapter->state);
                        qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
                }  else {
-                       owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
-                       if (ahw->pci_func == owner)
-                               qlcnic_dump_fw(adapter);
+                       netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                                   __func__);
+                       qlcnic_83xx_idc_enter_failed_state(adapter, 1);
                }
                return -EIO;
        }
@@ -948,13 +948,26 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
        return 0;
 }
 
-static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
+static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
 {
-       dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 val, owner;
+
+       val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
+               if (ahw->pci_func == owner) {
+                       qlcnic_83xx_stop_hw(adapter);
+                       qlcnic_dump_fw(adapter);
+               }
+       }
+
+       netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
+                   __func__);
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       adapter->ahw->idc.err_code = -EIO;
+       ahw->idc.err_code = -EIO;
 
-       return 0;
+       return;
 }
 
 static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
@@ -1063,12 +1076,6 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
        adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
        qlcnic_83xx_periodic_tasks(adapter);
 
-       /* Do not reschedule if firmaware is in hanged state and auto
-        * recovery is disabled
-        */
-       if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
-               return;
-
        /* Re-schedule the function */
        if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
                qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
@@ -1219,10 +1226,10 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
        }
 
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
-       if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) ||
-           !qlcnic_auto_fw_reset) {
-               dev_err(&adapter->pdev->dev,
-                       "%s:failed, device in non reset mode\n", __func__);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 0);
                qlcnic_83xx_unlock_driver(adapter);
                return;
        }
@@ -1254,24 +1261,24 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
        if (size & 0xF)
                size = (size + 16) & ~0xF;
 
-       p_cache = kzalloc(size, GFP_KERNEL);
+       p_cache = vzalloc(size);
        if (p_cache == NULL)
                return -ENOMEM;
 
        ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
                                                size / sizeof(u32));
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
        /* 16 byte write to MS memory */
        ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache,
                                          size / 16);
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
-       kfree(p_cache);
+       vfree(p_cache);
 
        return ret;
 }
@@ -1939,7 +1946,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,
        p_dev->ahw->reset.seq_index = index;
 }
 
-static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
+void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
 {
        p_dev->ahw->reset.seq_index = 0;
 
@@ -1994,6 +2001,14 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
        if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
                qlcnic_dump_fw(adapter);
+
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+               return err;
+       }
+
        qlcnic_83xx_init_hw(adapter);
 
        if (qlcnic_83xx_copy_bootloader(adapter))
@@ -2073,8 +2088,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
                ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
-               adapter->max_sds_rings = ahw->max_rx_ques;
-               adapter->max_tx_rings = ahw->max_tx_ques;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
+               adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
        } else {
                return -EIO;
        }
index b36c02fafcfd1ebe6f6ce8da49e73f73364f64b5..e3be2760665cd9e0781dc967a813fd1976778c3e 100644 (file)
@@ -667,30 +667,25 @@ qlcnic_set_ringparam(struct net_device *dev,
 static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
                                      u8 rx_ring, u8 tx_ring)
 {
+       if (rx_ring == 0 || tx_ring == 0)
+               return -EINVAL;
+
        if (rx_ring != 0) {
                if (rx_ring > adapter->max_sds_rings) {
-                       netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
+                       netdev_err(adapter->netdev,
+                                  "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
                                   rx_ring, adapter->max_sds_rings);
                        return -EINVAL;
                }
        }
 
         if (tx_ring != 0) {
-               if (qlcnic_82xx_check(adapter) &&
-                   (tx_ring > adapter->max_tx_rings)) {
+               if (tx_ring > adapter->max_tx_rings) {
                        netdev_err(adapter->netdev,
                                   "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
                                   tx_ring, adapter->max_tx_rings);
                        return -EINVAL;
                }
-
-               if (qlcnic_83xx_check(adapter) &&
-                   (tx_ring > QLCNIC_SINGLE_RING)) {
-                       netdev_err(adapter->netdev,
-                                  "Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
-                                  tx_ring, QLCNIC_SINGLE_RING);
-                        return -EINVAL;
-               }
        }
 
        return 0;
@@ -948,6 +943,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_cmd_args cmd;
        int ret, drv_sds_rings = adapter->drv_sds_rings;
+       int drv_tx_rings = adapter->drv_tx_rings;
 
        if (qlcnic_83xx_check(adapter))
                return qlcnic_83xx_interrupt_test(netdev);
@@ -980,6 +976,7 @@ free_diag_res:
 
 clear_diag_irq:
        adapter->drv_sds_rings = drv_sds_rings;
+       adapter->drv_tx_rings = drv_tx_rings;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
        return ret;
index 0149c94953474e6ad0ffd56b93cc440c67e77687..eda6c691d8970418ae14eb67db450a87314aa882 100644 (file)
@@ -687,17 +687,11 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
        if (adapter->ahw->linkup && !linkup) {
                netdev_info(netdev, "NIC Link is down\n");
                adapter->ahw->linkup = 0;
-               if (netif_running(netdev)) {
-                       netif_carrier_off(netdev);
-                       netif_tx_stop_all_queues(netdev);
-               }
+               netif_carrier_off(netdev);
        } else if (!adapter->ahw->linkup && linkup) {
                netdev_info(netdev, "NIC Link is up\n");
                adapter->ahw->linkup = 1;
-               if (netif_running(netdev)) {
-                       netif_carrier_on(netdev);
-                       netif_wake_queue(netdev);
-               }
+               netif_carrier_on(netdev);
        }
 }
 
index 05c1eef8df1325359ef1bf73df8344492a95876d..2c8cac0c6a55a7e9a32541c4f88e7d0ddcd5a977 100644 (file)
@@ -1178,6 +1178,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        } else {
                adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
        }
 
@@ -1940,7 +1941,6 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
        qlcnic_detach(adapter);
 
        adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
-       adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
        adapter->ahw->diag_test = test;
        adapter->ahw->linkup = 0;
 
index 0c9c4e89559524d78aa789dfb65e5e32211b8bc1..03517478e589495dd763a13eaab31101a9ea0a08 100644 (file)
@@ -18,7 +18,7 @@
  */
 #define DRV_NAME       "qlge"
 #define DRV_STRING     "QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION    "1.00.00.33"
+#define DRV_VERSION    "1.00.00.34"
 
 #define WQ_ADDR_ALIGN  0x3     /* 4 byte alignment */
 
index 0780e039b2718d902805414daeb6844b7d2086e7..8dee1beb9854813c94c1de36264a241703f9d0be 100644 (file)
@@ -181,6 +181,7 @@ static const char ql_gstrings_test[][ETH_GSTRING_LEN] = {
 };
 #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN)
 #define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats)
+#define QLGE_RCV_MAC_ERR_STATS 7
 
 static int ql_update_ring_coalescing(struct ql_adapter *qdev)
 {
@@ -280,6 +281,9 @@ static void ql_update_stats(struct ql_adapter *qdev)
                iter++;
        }
 
+       /* Update receive mac error statistics */
+       iter += QLGE_RCV_MAC_ERR_STATS;
+
        /*
         * Get Per-priority TX pause frame counter statistics.
         */
index a245dc18d769241bcf23d607458e33538c7ee99c..449f506d2e8ff3e71abc22bba6ce8e67bcf45305 100644 (file)
@@ -2376,14 +2376,6 @@ static netdev_features_t qlge_fix_features(struct net_device *ndev,
        netdev_features_t features)
 {
        int err;
-       /*
-        * Since there is no support for separate rx/tx vlan accel
-        * enable/disable make sure tx flag is always in same state as rx.
-        */
-       if (features & NETIF_F_HW_VLAN_CTAG_RX)
-               features |= NETIF_F_HW_VLAN_CTAG_TX;
-       else
-               features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
        /* Update the behavior of vlan accel in the adapter */
        err = qlge_update_hw_vlan_features(ndev, features);
index f2a2128165dd98b4c41598fb481c4e4f40417614..737c1a881f781917061d8b39ad43762f62ee7a6e 100644 (file)
@@ -678,9 +678,6 @@ static void cp_tx (struct cp_private *cp)
                                 le32_to_cpu(txd->opts1) & 0xffff,
                                 PCI_DMA_TODEVICE);
 
-               bytes_compl += skb->len;
-               pkts_compl++;
-
                if (status & LastFrag) {
                        if (status & (TxError | TxFIFOUnder)) {
                                netif_dbg(cp, tx_err, cp->dev,
@@ -702,6 +699,8 @@ static void cp_tx (struct cp_private *cp)
                                netif_dbg(cp, tx_done, cp->dev,
                                          "tx done, slot %d\n", tx_tail);
                        }
+                       bytes_compl += skb->len;
+                       pkts_compl++;
                        dev_kfree_skb_irq(skb);
                }
 
index 799387570766b6642ad4fdbc13f917acd358887a..c737f0ea5de751b7de9b1cb710fb101dc170ee41 100644 (file)
@@ -3465,6 +3465,11 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x14, 0x9065);
        rtl_writephy(tp, 0x14, 0x1065);
 
+       /* Check ALDPS bit, disable it if enabled */
+       rtl_writephy(tp, 0x1f, 0x0a43);
+       if (rtl_readphy(tp, 0x10) & 0x0004)
+               rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
+
        rtl_writephy(tp, 0x1f, 0x0000);
 }
 
index 2e27837ce6a289dc033c806e613f8dbca42496b9..fd844b53e38565cffa3e267fe0229f01f522a0d6 100644 (file)
@@ -585,7 +585,7 @@ static void efx_start_datapath(struct efx_nic *efx)
                           EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
                           efx->type->rx_buffer_padding);
        rx_buf_len = (sizeof(struct efx_rx_page_state) +
-                     NET_IP_ALIGN + efx->rx_dma_len);
+                     efx->rx_ip_align + efx->rx_dma_len);
        if (rx_buf_len <= PAGE_SIZE) {
                efx->rx_scatter = efx->type->always_rx_scatter;
                efx->rx_buffer_order = 0;
@@ -645,6 +645,8 @@ static void efx_start_datapath(struct efx_nic *efx)
                WARN_ON(channel->rx_pkt_n_frags);
        }
 
+       efx_ptp_start_datapath(efx);
+
        if (netif_device_present(efx->net_dev))
                netif_tx_wake_all_queues(efx->net_dev);
 }
@@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx_nic *efx)
        EFX_ASSERT_RESET_SERIALISED(efx);
        BUG_ON(efx->port_enabled);
 
+       efx_ptp_stop_datapath(efx);
+
        /* Stop RX refill */
        efx_for_each_channel(channel, efx) {
                efx_for_each_channel_rx_queue(rx_queue, channel)
@@ -2540,6 +2544,8 @@ static int efx_init_struct(struct efx_nic *efx,
 
        efx->net_dev = net_dev;
        efx->rx_prefix_size = efx->type->rx_prefix_size;
+       efx->rx_ip_align =
+               NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0;
        efx->rx_packet_hash_offset =
                efx->type->rx_hash_offset - efx->type->rx_prefix_size;
        spin_lock_init(&efx->stats_lock);
index 366c8e3e37844c8e2d8840a4662467067e937b3b..4b0bd8a1514dbb7035c7c0562cefc072901e585c 100644 (file)
@@ -50,6 +50,7 @@ struct efx_mcdi_async_param {
 static void efx_mcdi_timeout_async(unsigned long context);
 static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
                               bool *was_attached_out);
+static bool efx_mcdi_poll_once(struct efx_nic *efx);
 
 static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
 {
@@ -237,6 +238,21 @@ static void efx_mcdi_read_response_header(struct efx_nic *efx)
        }
 }
 
+static bool efx_mcdi_poll_once(struct efx_nic *efx)
+{
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+       rmb();
+       if (!efx->type->mcdi_poll_response(efx))
+               return false;
+
+       spin_lock_bh(&mcdi->iface_lock);
+       efx_mcdi_read_response_header(efx);
+       spin_unlock_bh(&mcdi->iface_lock);
+
+       return true;
+}
+
 static int efx_mcdi_poll(struct efx_nic *efx)
 {
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
@@ -272,18 +288,13 @@ static int efx_mcdi_poll(struct efx_nic *efx)
 
                time = jiffies;
 
-               rmb();
-               if (efx->type->mcdi_poll_response(efx))
+               if (efx_mcdi_poll_once(efx))
                        break;
 
                if (time_after(time, finish))
                        return -ETIMEDOUT;
        }
 
-       spin_lock_bh(&mcdi->iface_lock);
-       efx_mcdi_read_response_header(efx);
-       spin_unlock_bh(&mcdi->iface_lock);
-
        /* Return rc=0 like wait_event_timeout() */
        return 0;
 }
@@ -619,6 +630,16 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
                rc = efx_mcdi_await_completion(efx);
 
        if (rc != 0) {
+               netif_err(efx, hw, efx->net_dev,
+                         "MC command 0x%x inlen %d mode %d timed out\n",
+                         cmd, (int)inlen, mcdi->mode);
+
+               if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) {
+                       netif_err(efx, hw, efx->net_dev,
+                                 "MCDI request was completed without an event\n");
+                       rc = 0;
+               }
+
                /* Close the race with efx_mcdi_ev_cpl() executing just too late
                 * and completing a request we've just cancelled, by ensuring
                 * that the seqno check therein fails.
@@ -627,11 +648,9 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
                ++mcdi->seqno;
                ++mcdi->credits;
                spin_unlock_bh(&mcdi->iface_lock);
+       }
 
-               netif_err(efx, hw, efx->net_dev,
-                         "MC command 0x%x inlen %d mode %d timed out\n",
-                         cmd, (int)inlen, mcdi->mode);
-       } else {
+       if (rc == 0) {
                size_t hdr_len, data_len;
 
                /* At the very least we need a memory barrier here to ensure
index 656a3277c2b210e69ffd028d059ce10b809e8db8..15816cacb548161bd4a7299909bb83ccd9c222be 100644 (file)
@@ -75,6 +75,8 @@ struct efx_mcdi_mon {
        unsigned long last_update;
        struct device *device;
        struct efx_mcdi_mon_attribute *attrs;
+       struct attribute_group group;
+       const struct attribute_group *groups[2];
        unsigned int n_attrs;
 };
 
index 4cc5d95b2a5a5ea36869625843bf4daba064e84f..d72ad4fc36172241d5aeccbe883f4a82c8ee2daf 100644 (file)
@@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx)
        return rc;
 }
 
-static ssize_t efx_mcdi_mon_show_name(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "%s\n", KBUILD_MODNAME);
-}
-
 static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index,
                                  efx_dword_t *entry)
 {
-       struct efx_nic *efx = dev_get_drvdata(dev);
+       struct efx_nic *efx = dev_get_drvdata(dev->parent);
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        int rc;
 
@@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev,
                       efx_mcdi_sensor_type[mon_attr->type].label);
 }
 
-static int
+static void
 efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
                      ssize_t (*reader)(struct device *,
                                        struct device_attribute *, char *),
@@ -272,7 +265,6 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
 {
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
-       int rc;
 
        strlcpy(attr->name, name, sizeof(attr->name));
        attr->index = index;
@@ -286,10 +278,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
        attr->dev_attr.attr.name = attr->name;
        attr->dev_attr.attr.mode = S_IRUGO;
        attr->dev_attr.show = reader;
-       rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr);
-       if (rc == 0)
-               ++hwmon->n_attrs;
-       return rc;
+       hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr;
 }
 
 int efx_mcdi_mon_probe(struct efx_nic *efx)
@@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
        efx_mcdi_mon_update(efx);
 
        /* Allocate space for the maximum possible number of
-        * attributes for this set of sensors: name of the driver plus
+        * attributes for this set of sensors:
         * value, min, max, crit, alarm and label for each sensor.
         */
-       n_attrs = 1 + 6 * n_sensors;
+       n_attrs = 6 * n_sensors;
        hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
        if (!hwmon->attrs) {
                rc = -ENOMEM;
                goto fail;
        }
-
-       hwmon->device = hwmon_device_register(&efx->pci_dev->dev);
-       if (IS_ERR(hwmon->device)) {
-               rc = PTR_ERR(hwmon->device);
+       hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
+                                    GFP_KERNEL);
+       if (!hwmon->group.attrs) {
+               rc = -ENOMEM;
                goto fail;
        }
 
-       rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0);
-       if (rc)
-               goto fail;
-
        for (i = 0, j = -1, type = -1; ; i++) {
                enum efx_hwmon_type hwmon_type;
                const char *hwmon_prefix;
@@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                                page = type / 32;
                                j = -1;
                                if (page == n_pages)
-                                       return 0;
+                                       goto hwmon_register;
 
                                MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE,
                                               page);
@@ -453,28 +438,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                if (min1 != max1) {
                        snprintf(name, sizeof(name), "%s%u_input",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_value, i, type, 0);
-                       if (rc)
-                               goto fail;
 
                        if (hwmon_type != EFX_HWMON_POWER) {
                                snprintf(name, sizeof(name), "%s%u_min",
                                         hwmon_prefix, hwmon_index);
-                               rc = efx_mcdi_mon_add_attr(
+                               efx_mcdi_mon_add_attr(
                                        efx, name, efx_mcdi_mon_show_limit,
                                        i, type, min1);
-                               if (rc)
-                                       goto fail;
                        }
 
                        snprintf(name, sizeof(name), "%s%u_max",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_limit,
                                i, type, max1);
-                       if (rc)
-                               goto fail;
 
                        if (min2 != max2) {
                                /* Assume max2 is critical value.
@@ -482,32 +461,38 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                                 */
                                snprintf(name, sizeof(name), "%s%u_crit",
                                         hwmon_prefix, hwmon_index);
-                               rc = efx_mcdi_mon_add_attr(
+                               efx_mcdi_mon_add_attr(
                                        efx, name, efx_mcdi_mon_show_limit,
                                        i, type, max2);
-                               if (rc)
-                                       goto fail;
                        }
                }
 
                snprintf(name, sizeof(name), "%s%u_alarm",
                         hwmon_prefix, hwmon_index);
-               rc = efx_mcdi_mon_add_attr(
+               efx_mcdi_mon_add_attr(
                        efx, name, efx_mcdi_mon_show_alarm, i, type, 0);
-               if (rc)
-                       goto fail;
 
                if (type < ARRAY_SIZE(efx_mcdi_sensor_type) &&
                    efx_mcdi_sensor_type[type].label) {
                        snprintf(name, sizeof(name), "%s%u_label",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_label, i, type, 0);
-                       if (rc)
-                               goto fail;
                }
        }
 
+hwmon_register:
+       hwmon->groups[0] = &hwmon->group;
+       hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev,
+                                                         KBUILD_MODNAME, NULL,
+                                                         hwmon->groups);
+       if (IS_ERR(hwmon->device)) {
+               rc = PTR_ERR(hwmon->device);
+               goto fail;
+       }
+
+       return 0;
+
 fail:
        efx_mcdi_mon_remove(efx);
        return rc;
@@ -516,14 +501,11 @@ fail:
 void efx_mcdi_mon_remove(struct efx_nic *efx)
 {
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
-       unsigned int i;
 
-       for (i = 0; i < hwmon->n_attrs; i++)
-               device_remove_file(&efx->pci_dev->dev,
-                                  &hwmon->attrs[i].dev_attr);
-       kfree(hwmon->attrs);
        if (hwmon->device)
                hwmon_device_unregister(hwmon->device);
+       kfree(hwmon->attrs);
+       kfree(hwmon->group.attrs);
        efx_nic_free_buffer(efx, &hwmon->dma_buf);
 }
 
index b14a717ac3e8d95099b5d2648be590e138bc9e61..542a0d252ae0c25f6c60167c1ec9dba3943ba3d8 100644 (file)
@@ -683,6 +683,8 @@ struct vfdi_status;
  * @n_channels: Number of channels in use
  * @n_rx_channels: Number of channels used for RX (= number of RX queues)
  * @n_tx_channels: Number of channels used for TX
+ * @rx_ip_align: RX DMA address offset to have IP header aligned in
+ *     in accordance with NET_IP_ALIGN
  * @rx_dma_len: Current maximum RX DMA length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
  * @rx_buffer_truesize: Amortised allocation size of an RX buffer,
@@ -816,6 +818,7 @@ struct efx_nic {
        unsigned rss_spread;
        unsigned tx_channel_offset;
        unsigned n_tx_channels;
+       unsigned int rx_ip_align;
        unsigned int rx_dma_len;
        unsigned int rx_buffer_order;
        unsigned int rx_buffer_truesize;
index 11b6112d9249a734701eebe66414bd039702bcdd..91c63ec79c5fcb21d96545c0a6bad98e58cce5b9 100644 (file)
@@ -560,6 +560,8 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info);
 bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
+void efx_ptp_start_datapath(struct efx_nic *efx);
+void efx_ptp_stop_datapath(struct efx_nic *efx);
 
 extern const struct efx_nic_type falcon_a1_nic_type;
 extern const struct efx_nic_type falcon_b0_nic_type;
index 03acf57df04579bed5d0986f735f807491248cfb..3dd39dcfe36b92f3221119171b1e0c26729d85e8 100644 (file)
@@ -220,6 +220,7 @@ struct efx_ptp_timeset {
  * @evt_list: List of MC receive events awaiting packets
  * @evt_free_list: List of free events
  * @evt_lock: Lock for manipulating evt_list and evt_free_list
+ * @evt_overflow: Boolean indicating that event list has overflowed
  * @rx_evts: Instantiated events (on evt_list and evt_free_list)
  * @workwq: Work queue for processing pending PTP operations
  * @work: Work task
@@ -270,6 +271,7 @@ struct efx_ptp_data {
        struct list_head evt_list;
        struct list_head evt_free_list;
        spinlock_t evt_lock;
+       bool evt_overflow;
        struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS];
        struct workqueue_struct *workwq;
        struct work_struct work;
@@ -635,6 +637,11 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx)
                        }
                }
        }
+       /* If the event overflow flag is set and the event list is now empty
+        * clear the flag to re-enable the overflow warning message.
+        */
+       if (ptp->evt_overflow && list_empty(&ptp->evt_list))
+               ptp->evt_overflow = false;
        spin_unlock_bh(&ptp->evt_lock);
 }
 
@@ -676,6 +683,11 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx,
                        break;
                }
        }
+       /* If the event overflow flag is set and the event list is now empty
+        * clear the flag to re-enable the overflow warning message.
+        */
+       if (ptp->evt_overflow && list_empty(&ptp->evt_list))
+               ptp->evt_overflow = false;
        spin_unlock_bh(&ptp->evt_lock);
 
        return rc;
@@ -705,8 +717,9 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q)
                        __skb_queue_tail(q, skb);
                } else if (time_after(jiffies, match->expiry)) {
                        match->state = PTP_PACKET_STATE_TIMED_OUT;
-                       netif_warn(efx, rx_err, efx->net_dev,
-                                  "PTP packet - no timestamp seen\n");
+                       if (net_ratelimit())
+                               netif_warn(efx, rx_err, efx->net_dev,
+                                          "PTP packet - no timestamp seen\n");
                        __skb_queue_tail(q, skb);
                } else {
                        /* Replace unprocessed entry and stop */
@@ -788,9 +801,14 @@ fail:
 static int efx_ptp_stop(struct efx_nic *efx)
 {
        struct efx_ptp_data *ptp = efx->ptp_data;
-       int rc = efx_ptp_disable(efx);
        struct list_head *cursor;
        struct list_head *next;
+       int rc;
+
+       if (ptp == NULL)
+               return 0;
+
+       rc = efx_ptp_disable(efx);
 
        if (ptp->rxfilter_installed) {
                efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
@@ -809,11 +827,19 @@ static int efx_ptp_stop(struct efx_nic *efx)
        list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) {
                list_move(cursor, &efx->ptp_data->evt_free_list);
        }
+       ptp->evt_overflow = false;
        spin_unlock_bh(&efx->ptp_data->evt_lock);
 
        return rc;
 }
 
+static int efx_ptp_restart(struct efx_nic *efx)
+{
+       if (efx->ptp_data && efx->ptp_data->enabled)
+               return efx_ptp_start(efx);
+       return 0;
+}
+
 static void efx_ptp_pps_worker(struct work_struct *work)
 {
        struct efx_ptp_data *ptp =
@@ -901,6 +927,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel)
        spin_lock_init(&ptp->evt_lock);
        for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++)
                list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list);
+       ptp->evt_overflow = false;
 
        ptp->phc_clock_info.owner = THIS_MODULE;
        snprintf(ptp->phc_clock_info.name,
@@ -989,7 +1016,11 @@ bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
                skb->len >= PTP_MIN_LENGTH &&
                skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM &&
                likely(skb->protocol == htons(ETH_P_IP)) &&
+               skb_transport_header_was_set(skb) &&
+               skb_network_header_len(skb) >= sizeof(struct iphdr) &&
                ip_hdr(skb)->protocol == IPPROTO_UDP &&
+               skb_headlen(skb) >=
+               skb_transport_offset(skb) + sizeof(struct udphdr) &&
                udp_hdr(skb)->dest == htons(PTP_EVENT_PORT);
 }
 
@@ -1106,7 +1137,7 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
 {
        if ((enable_wanted != efx->ptp_data->enabled) ||
            (enable_wanted && (efx->ptp_data->mode != new_mode))) {
-               int rc;
+               int rc = 0;
 
                if (enable_wanted) {
                        /* Change of mode requires disable */
@@ -1123,7 +1154,8 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
                         * succeed.
                         */
                        efx->ptp_data->mode = new_mode;
-                       rc = efx_ptp_start(efx);
+                       if (netif_running(efx->net_dev))
+                               rc = efx_ptp_start(efx);
                        if (rc == 0) {
                                rc = efx_ptp_synchronize(efx,
                                                         PTP_SYNC_ATTEMPTS * 2);
@@ -1295,8 +1327,13 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp)
                list_add_tail(&evt->link, &ptp->evt_list);
 
                queue_work(ptp->workwq, &ptp->work);
-       } else {
-               netif_err(efx, rx_err, efx->net_dev, "No free PTP event");
+       } else if (!ptp->evt_overflow) {
+               /* Log a warning message and set the event overflow flag.
+                * The message won't be logged again until the event queue
+                * becomes empty.
+                */
+               netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n");
+               ptp->evt_overflow = true;
        }
        spin_unlock_bh(&ptp->evt_lock);
 }
@@ -1389,7 +1426,7 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
        if (rc != 0)
                return rc;
 
-       ptp_data->current_adjfreq = delta;
+       ptp_data->current_adjfreq = adjustment_ns;
        return 0;
 }
 
@@ -1404,7 +1441,7 @@ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
 
        MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST);
        MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
-       MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, 0);
+       MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq);
        MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec);
        MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec);
        return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
@@ -1491,3 +1528,14 @@ void efx_ptp_probe(struct efx_nic *efx)
                efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] =
                        &efx_ptp_channel_type;
 }
+
+void efx_ptp_start_datapath(struct efx_nic *efx)
+{
+       if (efx_ptp_restart(efx))
+               netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n");
+}
+
+void efx_ptp_stop_datapath(struct efx_nic *efx)
+{
+       efx_ptp_stop(efx);
+}
index 8f09e686fc2392a80f56610c78a61c6374b4a410..42488df1f4ec2af02feb9a46c408168b6a7dabec 100644 (file)
@@ -94,7 +94,7 @@ static inline void efx_sync_rx_buffer(struct efx_nic *efx,
 
 void efx_rx_config_page_split(struct efx_nic *efx)
 {
-       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + NET_IP_ALIGN,
+       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align,
                                      EFX_RX_BUF_ALIGNMENT);
        efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
                ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) /
@@ -189,9 +189,9 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue)
                do {
                        index = rx_queue->added_count & rx_queue->ptr_mask;
                        rx_buf = efx_rx_buffer(rx_queue, index);
-                       rx_buf->dma_addr = dma_addr + NET_IP_ALIGN;
+                       rx_buf->dma_addr = dma_addr + efx->rx_ip_align;
                        rx_buf->page = page;
-                       rx_buf->page_offset = page_offset + NET_IP_ALIGN;
+                       rx_buf->page_offset = page_offset + efx->rx_ip_align;
                        rx_buf->len = efx->rx_dma_len;
                        rx_buf->flags = 0;
                        ++rx_queue->added_count;
index 0c9b5d94154f8d215ddaf40d3fb252764983d73b..8bf29eb4a5a003eacabb6ea1f93590f566bb1ede 100644 (file)
@@ -82,6 +82,7 @@ static const char version[] =
 #include <linux/mii.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2184,6 +2185,15 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
        }
 }
 
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id smc91x_match[] = {
+       { .compatible = "smsc,lan91c94", },
+       { .compatible = "smsc,lan91c111", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, smc91x_match);
+#endif
+
 /*
  * smc_init(void)
  *   Input parameters:
@@ -2198,6 +2208,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
 static int smc_drv_probe(struct platform_device *pdev)
 {
        struct smc91x_platdata *pd = dev_get_platdata(&pdev->dev);
+       const struct of_device_id *match = NULL;
        struct smc_local *lp;
        struct net_device *ndev;
        struct resource *res, *ires;
@@ -2217,11 +2228,34 @@ static int smc_drv_probe(struct platform_device *pdev)
         */
 
        lp = netdev_priv(ndev);
+       lp->cfg.flags = 0;
 
        if (pd) {
                memcpy(&lp->cfg, pd, sizeof(lp->cfg));
                lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
-       } else {
+       }
+
+#if IS_BUILTIN(CONFIG_OF)
+       match = of_match_device(of_match_ptr(smc91x_match), &pdev->dev);
+       if (match) {
+               struct device_node *np = pdev->dev.of_node;
+               u32 val;
+
+               /* Combination of IO widths supported, default to 16-bit */
+               if (!of_property_read_u32(np, "reg-io-width", &val)) {
+                       if (val & 1)
+                               lp->cfg.flags |= SMC91X_USE_8BIT;
+                       if ((val == 0) || (val & 2))
+                               lp->cfg.flags |= SMC91X_USE_16BIT;
+                       if (val & 4)
+                               lp->cfg.flags |= SMC91X_USE_32BIT;
+               } else {
+                       lp->cfg.flags |= SMC91X_USE_16BIT;
+               }
+       }
+#endif
+
+       if (!pd && !match) {
                lp->cfg.flags |= (SMC_CAN_USE_8BIT)  ? SMC91X_USE_8BIT  : 0;
                lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
                lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
@@ -2370,15 +2404,6 @@ static int smc_drv_resume(struct device *dev)
        return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id smc91x_match[] = {
-       { .compatible = "smsc,lan91c94", },
-       { .compatible = "smsc,lan91c111", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, smc91x_match);
-#endif
-
 static struct dev_pm_ops smc_drv_pm_ops = {
        .suspend        = smc_drv_suspend,
        .resume         = smc_drv_resume,
index c9d4c872e81da1888cf8678ceb2fd7df5381ac03..749654b976bcf85fd07558f175274b9f01551705 100644 (file)
@@ -46,7 +46,8 @@
     defined(CONFIG_MACH_LITTLETON) ||\
     defined(CONFIG_MACH_ZYLONITE2) ||\
     defined(CONFIG_ARCH_VIPER) ||\
-    defined(CONFIG_MACH_STARGATE2)
+    defined(CONFIG_MACH_STARGATE2) ||\
+    defined(CONFIG_ARCH_VERSATILE)
 
 #include <asm/mach-types.h>
 
@@ -154,6 +155,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_outl(v, a, r)      writel(v, (a) + (r))
 #define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
 #define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+#define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
 #define SMC_IRQ_FLAGS          (-1)    /* from resource */
 
 /* We actually can't write halfwords properly if not word aligned */
@@ -206,23 +209,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
 
-#elif  defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT       1
-#define SMC_CAN_USE_16BIT      1
-#define SMC_CAN_USE_32BIT      1
-#define SMC_NOWAIT             1
-
-#define SMC_inb(a, r)          readb((a) + (r))
-#define SMC_inw(a, r)          readw((a) + (r))
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)      writew(v, (a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
-#define SMC_IRQ_FLAGS          (-1)    /* from resource */
-
 #elif defined(CONFIG_MN10300)
 
 /*
index dd0dd6279b4eec8168c006457643568032ee358f..4f1d2549130e3396909f5287776663fa5bfb4e9e 100644 (file)
@@ -2019,7 +2019,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO
                    | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
                    NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM
-                   /*| NETIF_F_FRAGLIST */
                    ;
                ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
                        NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX;
index 7536a4c01293a9b3e97bf1171941b6724213ad6c..5120d9ce1dd4cdbdd8608550f87392d0a5f6bbb9 100644 (file)
@@ -1151,6 +1151,12 @@ static int cpsw_ndo_open(struct net_device *ndev)
                 * receive descs
                 */
                cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
+
+               if (cpts_register(&priv->pdev->dev, priv->cpts,
+                                 priv->data.cpts_clock_mult,
+                                 priv->data.cpts_clock_shift))
+                       dev_err(priv->dev, "error registering cpts device\n");
+
        }
 
        /* Enable Interrupt pacing if configured */
@@ -1197,6 +1203,7 @@ static int cpsw_ndo_stop(struct net_device *ndev)
        netif_carrier_off(priv->ndev);
 
        if (cpsw_common_res_usage_state(priv) <= 1) {
+               cpts_unregister(priv->cpts);
                cpsw_intr_disable(priv);
                cpdma_ctlr_int_ctrl(priv->dma, false);
                cpdma_ctlr_stop(priv->dma);
@@ -1816,6 +1823,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                }
 
                i++;
+               if (i == data->slaves)
+                       break;
        }
 
        return 0;
@@ -1983,9 +1992,15 @@ static int cpsw_probe(struct platform_device *pdev)
                goto clean_runtime_disable_ret;
        }
        priv->regs = ss_regs;
-       priv->version = __raw_readl(&priv->regs->id_ver);
        priv->host_port = HOST_PORT_NUM;
 
+       /* Need to enable clocks with runtime PM api to access module
+        * registers
+        */
+       pm_runtime_get_sync(&pdev->dev);
+       priv->version = readl(&priv->regs->id_ver);
+       pm_runtime_put_sync(&pdev->dev);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        priv->wr_regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->wr_regs)) {
@@ -2155,8 +2170,6 @@ static int cpsw_remove(struct platform_device *pdev)
                unregister_netdev(cpsw_get_slave_ndev(priv, 1));
        unregister_netdev(ndev);
 
-       cpts_unregister(priv->cpts);
-
        cpsw_ale_destroy(priv->ale);
        cpdma_chan_destroy(priv->txch);
        cpdma_chan_destroy(priv->rxch);
index 41ba974bf37cb9175c74ab40bba1817e890749e7..cd9b164a0434acb3a51066b5d0e17262a4bdc0dd 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/davinci_emac.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_net.h>
 
@@ -1752,10 +1753,14 @@ static const struct net_device_ops emac_netdev_ops = {
 #endif
 };
 
+static const struct of_device_id davinci_emac_of_match[];
+
 static struct emac_platform_data *
 davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
 {
        struct device_node *np;
+       const struct of_device_id *match;
+       const struct emac_platform_data *auxdata;
        struct emac_platform_data *pdata = NULL;
        const u8 *mac_addr;
 
@@ -1793,7 +1798,20 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
 
        priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
        if (!priv->phy_node)
-               pdata->phy_id = "";
+               pdata->phy_id = NULL;
+
+       auxdata = pdev->dev.platform_data;
+       if (auxdata) {
+               pdata->interrupt_enable = auxdata->interrupt_enable;
+               pdata->interrupt_disable = auxdata->interrupt_disable;
+       }
+
+       match = of_match_device(davinci_emac_of_match, &pdev->dev);
+       if (match && match->data) {
+               auxdata = match->data;
+               pdata->version = auxdata->version;
+               pdata->hw_ram_addr = auxdata->hw_ram_addr;
+       }
 
        pdev->dev.platform_data = pdata;
 
@@ -2020,8 +2038,14 @@ static const struct dev_pm_ops davinci_emac_pm_ops = {
 };
 
 #if IS_ENABLED(CONFIG_OF)
+static const struct emac_platform_data am3517_emac_data = {
+       .version                = EMAC_VERSION_2,
+       .hw_ram_addr            = 0x01e20000,
+};
+
 static const struct of_device_id davinci_emac_of_match[] = {
        {.compatible = "ti,davinci-dm6467-emac", },
+       {.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
        {},
 };
 MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
index d022bf936572ea857cbcb9f0fded1899077d5a95..ad61d26a44f31d26fc3b6d96f8430a5264e28e6f 100644 (file)
@@ -2172,16 +2172,13 @@ static int velocity_poll(struct napi_struct *napi, int budget)
        unsigned int rx_done;
        unsigned long flags;
 
-       spin_lock_irqsave(&vptr->lock, flags);
        /*
         * Do rx and tx twice for performance (taken from the VIA
         * out-of-tree driver).
         */
-       rx_done = velocity_rx_srv(vptr, budget / 2);
-       velocity_tx_srv(vptr);
-       rx_done += velocity_rx_srv(vptr, budget - rx_done);
+       rx_done = velocity_rx_srv(vptr, budget);
+       spin_lock_irqsave(&vptr->lock, flags);
        velocity_tx_srv(vptr);
-
        /* If budget not fully consumed, exit the polling mode */
        if (rx_done < budget) {
                napi_complete(napi);
@@ -2342,6 +2339,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
                if (ret < 0)
                        goto out_free_tmp_vptr_1;
 
+               napi_disable(&vptr->napi);
+
                spin_lock_irqsave(&vptr->lock, flags);
 
                netif_stop_queue(dev);
@@ -2362,6 +2361,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
 
                velocity_give_many_rx_descs(vptr);
 
+               napi_enable(&vptr->napi);
+
                mac_enable_int(vptr->mac_regs);
                netif_start_queue(dev);
 
index 1f23641263232fce0255d237976cbf5470e22a6c..2166e879a0961544af056802b1dbcff5a011d2aa 100644 (file)
@@ -1017,7 +1017,7 @@ static int temac_of_probe(struct platform_device *op)
        platform_set_drvdata(op, ndev);
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-       ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+       ndev->features = NETIF_F_SG;
        ndev->netdev_ops = &temac_netdev_ops;
        ndev->ethtool_ops = &temac_ethtool_ops;
 #if 0
index b2ff038d6d200abc5dbcd9315806e6791cec3335..f9293da19e260caa8e06829242150ccc72c0ded0 100644 (file)
@@ -1486,7 +1486,7 @@ static int axienet_of_probe(struct platform_device *op)
 
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-       ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+       ndev->features = NETIF_F_SG;
        ndev->netdev_ops = &axienet_netdev_ops;
        ndev->ethtool_ops = &axienet_ethtool_ops;
 
index 74234a51c851186c0c9bcfbc140b261724144e20..fefb8cd5eb65e1cb462f2a277c0bda422a89cd60 100644 (file)
@@ -163,26 +163,9 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
        __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
                     drvdata->base_addr + XEL_TSR_OFFSET);
 
-       /* Enable the Tx interrupts for the second Buffer if
-        * configured in HW */
-       if (drvdata->tx_ping_pong != 0) {
-               reg_data = __raw_readl(drvdata->base_addr +
-                                  XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
-               __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
-       }
-
        /* Enable the Rx interrupts for the first buffer */
        __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
 
-       /* Enable the Rx interrupts for the second Buffer if
-        * configured in HW */
-       if (drvdata->rx_ping_pong != 0) {
-               __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr +
-                            XEL_BUFFER_OFFSET + XEL_RSR_OFFSET);
-       }
-
        /* Enable the Global Interrupt Enable */
        __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 }
@@ -206,31 +189,10 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
        __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
                     drvdata->base_addr + XEL_TSR_OFFSET);
 
-       /* Disable the Tx interrupts for the second Buffer
-        * if configured in HW */
-       if (drvdata->tx_ping_pong != 0) {
-               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_TSR_OFFSET);
-               __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
-       }
-
        /* Disable the Rx interrupts for the first buffer */
        reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
        __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
                     drvdata->base_addr + XEL_RSR_OFFSET);
-
-       /* Disable the Rx interrupts for the second buffer
-        * if configured in HW */
-       if (drvdata->rx_ping_pong != 0) {
-
-               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_RSR_OFFSET);
-               __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_RSR_OFFSET);
-       }
 }
 
 /**
@@ -258,6 +220,13 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
                *to_u16_ptr++ = *from_u16_ptr++;
                *to_u16_ptr++ = *from_u16_ptr++;
 
+               /* This barrier resolves occasional issues seen around
+                * cases where the data is not properly flushed out
+                * from the processor store buffers to the destination
+                * memory locations.
+                */
+               wmb();
+
                /* Output a word */
                *to_u32_ptr++ = align_buffer;
        }
@@ -273,6 +242,12 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
                for (; length > 0; length--)
                        *to_u8_ptr++ = *from_u8_ptr++;
 
+               /* This barrier resolves occasional issues seen around
+                * cases where the data is not properly flushed out
+                * from the processor store buffers to the destination
+                * memory locations.
+                */
+               wmb();
                *to_u32_ptr = align_buffer;
        }
 }
index 524f713f60170b2d5632bbac6958ae0529a80b1c..f8135725bcf678c231cb833c3ab50487b1ec67e6 100644 (file)
@@ -327,7 +327,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
                return -EINVAL;
 
        nvdev->start_remove = true;
-       cancel_delayed_work_sync(&ndevctx->dwork);
        cancel_work_sync(&ndevctx->work);
        netif_tx_disable(ndev);
        rndis_filter_device_remove(hdev);
index dc76670c2f2a16c244d0ec58a779a8742d0e6c3e..2a89da0803177355ebae2f31ce92ceb2fae00599 100644 (file)
@@ -744,7 +744,7 @@ err:
        rcu_read_lock();
        vlan = rcu_dereference(q->vlan);
        if (vlan)
-               vlan->dev->stats.tx_dropped++;
+               this_cpu_inc(vlan->pcpu_stats->tx_dropped);
        rcu_read_unlock();
 
        return err;
@@ -767,11 +767,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                                const struct sk_buff *skb,
                                const struct iovec *iv, int len)
 {
-       struct macvlan_dev *vlan;
        int ret;
        int vnet_hdr_len = 0;
        int vlan_offset = 0;
-       int copied;
+       int copied, total;
 
        if (q->flags & IFF_VNET_HDR) {
                struct virtio_net_hdr vnet_hdr;
@@ -786,7 +785,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
                        return -EFAULT;
        }
-       copied = vnet_hdr_len;
+       total = copied = vnet_hdr_len;
+       total += skb->len;
 
        if (!vlan_tx_tag_present(skb))
                len = min_t(int, skb->len, len);
@@ -801,6 +801,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
                ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
@@ -818,19 +819,9 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
        }
 
        ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
-       copied += len;
 
 done:
-       rcu_read_lock();
-       vlan = rcu_dereference(q->vlan);
-       if (vlan) {
-               preempt_disable();
-               macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0);
-               preempt_enable();
-       }
-       rcu_read_unlock();
-
-       return ret ? ret : copied;
+       return ret ? ret : total;
 }
 
 static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
@@ -885,7 +876,9 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
        }
 
        ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK);
-       ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */
+       ret = min_t(ssize_t, ret, len);
+       if (ret > 0)
+               iocb->ki_pos = ret;
 out:
        return ret;
 }
index 3ae28f420868fc35af3b3ed4e652f96e43a8f35b..26fa05a472b467679071ee6d76642e87f8bc10cf 100644 (file)
@@ -335,6 +335,21 @@ static struct phy_driver ksphy_driver[] = {
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_KSZ8041RNLI,
+       .phy_id_mask    = 0x00fffff0,
+       .name           = "Micrel KSZ8041RNLI",
+       .features       = PHY_BASIC_FEATURES |
+                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = kszphy_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = kszphy_ack_interrupt,
+       .config_intr    = kszphy_config_intr,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
+       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_KSZ8051,
        .phy_id_mask    = 0x00fffff0,
index 508e4359338bc385dc2a0901e24a6351f735f780..14372c65a7e8209b5f97da6416ef80d1f41a522c 100644 (file)
@@ -64,6 +64,7 @@
 
 #define PHY_ID_VSC8234                 0x000fc620
 #define PHY_ID_VSC8244                 0x000fc6c0
+#define PHY_ID_VSC8514                 0x00070670
 #define PHY_ID_VSC8574                 0x000704a0
 #define PHY_ID_VSC8662                 0x00070660
 #define PHY_ID_VSC8221                 0x000fc550
@@ -131,6 +132,7 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
                err = phy_write(phydev, MII_VSC8244_IMASK,
                        (phydev->drv->phy_id == PHY_ID_VSC8234 ||
                         phydev->drv->phy_id == PHY_ID_VSC8244 ||
+                        phydev->drv->phy_id == PHY_ID_VSC8514 ||
                         phydev->drv->phy_id == PHY_ID_VSC8574) ?
                                MII_VSC8244_IMASK_MASK :
                                MII_VSC8221_IMASK_MASK);
@@ -245,6 +247,18 @@ static struct phy_driver vsc82xx_driver[] = {
        .ack_interrupt  = &vsc824x_ack_interrupt,
        .config_intr    = &vsc82xx_config_intr,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_VSC8514,
+       .name           = "Vitesse VSC8514",
+       .phy_id_mask    = 0x000ffff0,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &vsc824x_config_init,
+       .config_aneg    = &vsc82x4_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc824x_ack_interrupt,
+       .config_intr    = &vsc82xx_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_VSC8574,
        .name           = "Vitesse VSC8574",
@@ -315,6 +329,7 @@ module_exit(vsc82xx_exit);
 static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
        { PHY_ID_VSC8234, 0x000ffff0 },
        { PHY_ID_VSC8244, 0x000fffc0 },
+       { PHY_ID_VSC8514, 0x000ffff0 },
        { PHY_ID_VSC8574, 0x000ffff0 },
        { PHY_ID_VSC8662, 0x000ffff0 },
        { PHY_ID_VSC8221, 0x000ffff0 },
index 34b0de09d88190a04e30d867e31ad001f35f0e34..736050d6b4516b3de85eb2c214d0464ff690d99f 100644 (file)
@@ -1366,6 +1366,8 @@ static int team_user_linkup_option_get(struct team *team,
        return 0;
 }
 
+static void __team_carrier_check(struct team *team);
+
 static int team_user_linkup_option_set(struct team *team,
                                       struct team_gsetter_ctx *ctx)
 {
@@ -1373,6 +1375,7 @@ static int team_user_linkup_option_set(struct team *team,
 
        port->user.linkup = ctx->data.bool_val;
        team_refresh_port_linkup(port);
+       __team_carrier_check(port->team);
        return 0;
 }
 
@@ -1392,6 +1395,7 @@ static int team_user_linkup_en_option_set(struct team *team,
 
        port->user.linkup_enabled = ctx->data.bool_val;
        team_refresh_port_linkup(port);
+       __team_carrier_check(port->team);
        return 0;
 }
 
index 782e38bfc1eeea38215492aee5aaa587cc534525..7c8343a4f91823a579910cbcccc5827a2eb1d986 100644 (file)
@@ -1184,7 +1184,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 {
        struct tun_pi pi = { 0, skb->protocol };
        ssize_t total = 0;
-       int vlan_offset = 0;
+       int vlan_offset = 0, copied;
 
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) < 0)
@@ -1248,6 +1248,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                total += tun->vnet_hdr_sz;
        }
 
+       copied = total;
+       total += skb->len;
        if (!vlan_tx_tag_present(skb)) {
                len = min_t(int, skb->len, len);
        } else {
@@ -1262,24 +1264,24 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
-               ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
+               ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
 
                copy = min_t(int, sizeof(veth), len);
-               ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
+               ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
        }
 
-       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
-       total += len;
+       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
 
 done:
        tun->dev->stats.tx_packets++;
@@ -1356,6 +1358,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
        ret = tun_do_read(tun, tfile, iocb, iv, len,
                          file->f_flags & O_NONBLOCK);
        ret = min_t(ssize_t, ret, len);
+       if (ret > 0)
+               iocb->ki_pos = ret;
 out:
        tun_put(tun);
        return ret;
index 7bab4de658a91d9fb1231f5e45461a268efc8487..d208f860498106013913211183baa39a37f33982 100644 (file)
@@ -299,35 +299,76 @@ static struct sk_buff *page_to_skb(struct receive_queue *rq,
        return skb;
 }
 
-static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
+static struct sk_buff *receive_small(void *buf, unsigned int len)
 {
-       struct skb_vnet_hdr *hdr = skb_vnet_hdr(head_skb);
+       struct sk_buff * skb = buf;
+
+       len -= sizeof(struct virtio_net_hdr);
+       skb_trim(skb, len);
+
+       return skb;
+}
+
+static struct sk_buff *receive_big(struct net_device *dev,
+                                  struct receive_queue *rq,
+                                  void *buf,
+                                  unsigned int len)
+{
+       struct page *page = buf;
+       struct sk_buff *skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
+
+       if (unlikely(!skb))
+               goto err;
+
+       return skb;
+
+err:
+       dev->stats.rx_dropped++;
+       give_pages(rq, page);
+       return NULL;
+}
+
+static struct sk_buff *receive_mergeable(struct net_device *dev,
+                                        struct receive_queue *rq,
+                                        void *buf,
+                                        unsigned int len)
+{
+       struct skb_vnet_hdr *hdr = buf;
+       int num_buf = hdr->mhdr.num_buffers;
+       struct page *page = virt_to_head_page(buf);
+       int offset = buf - page_address(page);
+       struct sk_buff *head_skb = page_to_skb(rq, page, offset, len,
+                                              MERGE_BUFFER_LEN);
        struct sk_buff *curr_skb = head_skb;
-       char *buf;
-       struct page *page;
-       int num_buf, len, offset;
 
-       num_buf = hdr->mhdr.num_buffers;
+       if (unlikely(!curr_skb))
+               goto err_skb;
+
        while (--num_buf) {
-               int num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
+               int num_skb_frags;
+
                buf = virtqueue_get_buf(rq->vq, &len);
                if (unlikely(!buf)) {
-                       pr_debug("%s: rx error: %d buffers missing\n",
-                                head_skb->dev->name, hdr->mhdr.num_buffers);
-                       head_skb->dev->stats.rx_length_errors++;
-                       return -EINVAL;
+                       pr_debug("%s: rx error: %d buffers out of %d missing\n",
+                                dev->name, num_buf, hdr->mhdr.num_buffers);
+                       dev->stats.rx_length_errors++;
+                       goto err_buf;
                }
                if (unlikely(len > MERGE_BUFFER_LEN)) {
                        pr_debug("%s: rx error: merge buffer too long\n",
-                                head_skb->dev->name);
+                                dev->name);
                        len = MERGE_BUFFER_LEN;
                }
+
+               page = virt_to_head_page(buf);
+               --rq->num;
+
+               num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
                if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) {
                        struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC);
-                       if (unlikely(!nskb)) {
-                               head_skb->dev->stats.rx_dropped++;
-                               return -ENOMEM;
-                       }
+
+                       if (unlikely(!nskb))
+                               goto err_skb;
                        if (curr_skb == head_skb)
                                skb_shinfo(curr_skb)->frag_list = nskb;
                        else
@@ -341,8 +382,7 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
                        head_skb->len += len;
                        head_skb->truesize += MERGE_BUFFER_LEN;
                }
-               page = virt_to_head_page(buf);
-               offset = buf - (char *)page_address(page);
+               offset = buf - page_address(page);
                if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) {
                        put_page(page);
                        skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1,
@@ -351,9 +391,28 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
                        skb_add_rx_frag(curr_skb, num_skb_frags, page,
                                        offset, len, MERGE_BUFFER_LEN);
                }
+       }
+
+       return head_skb;
+
+err_skb:
+       put_page(page);
+       while (--num_buf) {
+               buf = virtqueue_get_buf(rq->vq, &len);
+               if (unlikely(!buf)) {
+                       pr_debug("%s: rx error: %d buffers missing\n",
+                                dev->name, num_buf);
+                       dev->stats.rx_length_errors++;
+                       break;
+               }
+               page = virt_to_head_page(buf);
+               put_page(page);
                --rq->num;
        }
-       return 0;
+err_buf:
+       dev->stats.rx_dropped++;
+       dev_kfree_skb(head_skb);
+       return NULL;
 }
 
 static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
@@ -362,48 +421,29 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
        struct net_device *dev = vi->dev;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
        struct sk_buff *skb;
-       struct page *page;
        struct skb_vnet_hdr *hdr;
 
        if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
                pr_debug("%s: short packet %i\n", dev->name, len);
                dev->stats.rx_length_errors++;
-               if (vi->big_packets)
-                       give_pages(rq, buf);
-               else if (vi->mergeable_rx_bufs)
+               if (vi->mergeable_rx_bufs)
                        put_page(virt_to_head_page(buf));
+               else if (vi->big_packets)
+                       give_pages(rq, buf);
                else
                        dev_kfree_skb(buf);
                return;
        }
 
-       if (!vi->mergeable_rx_bufs && !vi->big_packets) {
-               skb = buf;
-               len -= sizeof(struct virtio_net_hdr);
-               skb_trim(skb, len);
-       } else if (vi->mergeable_rx_bufs) {
-               struct page *page = virt_to_head_page(buf);
-               skb = page_to_skb(rq, page,
-                                 (char *)buf - (char *)page_address(page),
-                                 len, MERGE_BUFFER_LEN);
-               if (unlikely(!skb)) {
-                       dev->stats.rx_dropped++;
-                       put_page(page);
-                       return;
-               }
-               if (receive_mergeable(rq, skb)) {
-                       dev_kfree_skb(skb);
-                       return;
-               }
-       } else {
-               page = buf;
-               skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
-               if (unlikely(!skb)) {
-                       dev->stats.rx_dropped++;
-                       give_pages(rq, page);
-                       return;
-               }
-       }
+       if (vi->mergeable_rx_bufs)
+               skb = receive_mergeable(dev, rq, buf, len);
+       else if (vi->big_packets)
+               skb = receive_big(dev, rq, buf, len);
+       else
+               skb = receive_small(buf, len);
+
+       if (unlikely(!skb))
+               return;
 
        hdr = skb_vnet_hdr(skb);
 
@@ -1084,7 +1124,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
                                  VIRTIO_NET_CTRL_MAC_TABLE_SET,
                                  sg, NULL))
-               dev_warn(&dev->dev, "Failed to set MAC fitler table.\n");
+               dev_warn(&dev->dev, "Failed to set MAC filter table.\n");
 
        kfree(buf);
 }
@@ -1327,6 +1367,11 @@ static void virtnet_config_changed(struct virtio_device *vdev)
 
 static void virtnet_free_queues(struct virtnet_info *vi)
 {
+       int i;
+
+       for (i = 0; i < vi->max_queue_pairs; i++)
+               netif_napi_del(&vi->rq[i].napi);
+
        kfree(vi->rq);
        kfree(vi->sq);
 }
@@ -1356,10 +1401,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
                struct virtqueue *vq = vi->rq[i].vq;
 
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-                       if (vi->big_packets)
-                               give_pages(&vi->rq[i], buf);
-                       else if (vi->mergeable_rx_bufs)
+                       if (vi->mergeable_rx_bufs)
                                put_page(virt_to_head_page(buf));
+                       else if (vi->big_packets)
+                               give_pages(&vi->rq[i], buf);
                        else
                                dev_kfree_skb(buf);
                        --vi->rq[i].num;
index 0358c07f7669142034e089660425a8fdb88236e2..249e01c5600c9010a19ca07c175867ec9e5fb91d 100644 (file)
@@ -1668,7 +1668,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        netdev_dbg(dev, "circular route to %pI4\n",
                                   &dst->sin.sin_addr.s_addr);
                        dev->stats.collisions++;
-                       goto tx_error;
+                       goto rt_tx_error;
                }
 
                /* Bypass encapsulation if the destination is local */
index 1ec52356b5a16956dda70a2f7365103497b43c68..130657db5c4314321159b8d3fb7ec69c1ee01d21 100644 (file)
@@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
        int quick_drop;
        s32 t[3], f[3] = {5180, 5500, 5785};
 
-       if (!(pBase->miscConfiguration & BIT(1)))
+       if (!(pBase->miscConfiguration & BIT(4)))
                return;
 
-       if (freq < 4000)
-               quick_drop = eep->modalHeader2G.quick_drop;
-       else {
-               t[0] = eep->base_ext1.quick_drop_low;
-               t[1] = eep->modalHeader5G.quick_drop;
-               t[2] = eep->base_ext1.quick_drop_high;
-               quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+       if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) {
+               if (freq < 4000) {
+                       quick_drop = eep->modalHeader2G.quick_drop;
+               } else {
+                       t[0] = eep->base_ext1.quick_drop_low;
+                       t[1] = eep->modalHeader5G.quick_drop;
+                       t[2] = eep->base_ext1.quick_drop_high;
+                       quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+               }
+               REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
        }
-       REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
 }
 
 static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
@@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz)
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 bias;
 
-       if (!(eep->baseEepHeader.featureEnable & 0x40))
+       if (!(eep->baseEepHeader.miscConfiguration & 0x40))
                return;
 
        if (!AR_SREV_9300(ah))
index 54b04155e43b1058575aa44df3e6ece1ab18e55e..8918035da3a3510c04ad45e106cebd3d267ad6e8 100644 (file)
@@ -146,10 +146,9 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
        else
                clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
 
-       if (IS_CHAN_HT40(chan))
-               clockrate *= 2;
-
-       if (ah->curchan) {
+       if (chan) {
+               if (IS_CHAN_HT40(chan))
+                       clockrate *= 2;
                if (IS_CHAN_HALF_RATE(chan))
                        clockrate /= 2;
                if (IS_CHAN_QUARTER_RATE(chan))
index 09cdbcd097394a3a2c324230c2743f5d181b0900..b5a19e098f2d72f49dde181184bce20dc47bcebf 100644 (file)
@@ -1276,6 +1276,10 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
                                if (!rts_thresh || (len > rts_thresh))
                                        rts = true;
                        }
+
+                       if (!aggr)
+                               len = fi->framelen;
+
                        ath_buf_set_rate(sc, bf, &info, len, rts);
                }
 
index de9eb2cfbf4b5784c36a97da2748acd357250c37..366339421d4f1c924e4e1e69c34ce88bce9ab028 100644 (file)
@@ -2041,13 +2041,20 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
        case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
                mutex_lock(&wcn->hal_ind_mutex);
                msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-               msg_ind->msg_len = len;
-               msg_ind->msg = kmalloc(len, GFP_KERNEL);
-               memcpy(msg_ind->msg, buf, len);
-               list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
-               queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-               wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               if (msg_ind) {
+                       msg_ind->msg_len = len;
+                       msg_ind->msg = kmalloc(len, GFP_KERNEL);
+                       memcpy(msg_ind->msg, buf, len);
+                       list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
+                       queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
+                       wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               }
                mutex_unlock(&wcn->hal_ind_mutex);
+               if (msg_ind)
+                       break;
+               /* FIXME: Do something smarter then just printing an error. */
+               wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
+                           msg_header->msg_type);
                break;
        default:
                wcn36xx_err("SMD_EVENT (%d) not supported\n",
index b00a7e92225f7b928f5a3cf7395f860af27299bd..54e36fcb39542e8361dfdc019134f3ba1538de8f 100644 (file)
@@ -5,6 +5,8 @@ config BRCMSMAC
        tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
        depends on MAC80211
        depends on BCMA
+       select NEW_LEDS if BCMA_DRIVER_GPIO
+       select LEDS_CLASS if BCMA_DRIVER_GPIO
        select BRCMUTIL
        select FW_LOADER
        select CRC_CCITT
index 905704e335d7164b90a4ecb6fd51c2324911c154..abc9ceca70f3630251ad077fe307f05a8a979adc 100644 (file)
@@ -109,6 +109,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
                                        brcmf_err("Disable F2 failed:%d\n",
                                                  err_ret);
                        }
+               } else {
+                       err_ret = -ENOENT;
                }
        } else if ((regaddr == SDIO_CCCR_ABORT) ||
                   (regaddr == SDIO_CCCR_IENx)) {
index 85879dbaa402cdaa88d93247b678aaac9a3ff000..3c34a72a5d64769b8bbf156f9a74d4748fcb0228 100644 (file)
@@ -67,8 +67,8 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  7
-#define IWL3160_UCODE_API_MAX  7
+#define IWL7260_UCODE_API_MAX  8
+#define IWL3160_UCODE_API_MAX  8
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK   7
@@ -130,6 +130,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
@@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
        .high_temp = true,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_2n_cfg = {
@@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_2n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_n_cfg = {
@@ -158,6 +161,7 @@ const struct iwl_cfg iwl7260_n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_2ac_cfg = {
@@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_2n_cfg = {
@@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_n_cfg = {
@@ -185,6 +191,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7265_2ac_cfg = {
@@ -196,5 +203,23 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
 };
 
+const struct iwl_cfg iwl7265_2n_cfg = {
+       .name = "Intel(R) Dual Band Wireless N 7265",
+       .fw_name_pre = IWL7265_FW_PRE,
+       IWL_DEVICE_7000,
+       .ht_params = &iwl7000_ht_params,
+       .nvm_ver = IWL7265_NVM_VERSION,
+       .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+};
+
+const struct iwl_cfg iwl7265_n_cfg = {
+       .name = "Intel(R) Wireless N 7265",
+       .fw_name_pre = IWL7265_FW_PRE,
+       IWL_DEVICE_7000,
+       .ht_params = &iwl7000_ht_params,
+       .nvm_ver = IWL7265_NVM_VERSION,
+       .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+};
+
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
index 18f232e8e81253b31d730755f242b7a51552157c..03fd9aa8bfda93b67122b1fea0688c60aad1f95c 100644 (file)
@@ -207,6 +207,8 @@ struct iwl_eeprom_params {
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
  * @high_temp: Is this NIC is designated to be in high temperature.
+ * @host_interrupt_operation_mode: device needs host interrupt operation
+ *     mode set
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -235,6 +237,7 @@ struct iwl_cfg {
        enum iwl_led_mode led_mode;
        const bool rx_with_siso_diversity;
        const bool internal_wimax_coex;
+       const bool host_interrupt_operation_mode;
        bool high_temp;
 };
 
@@ -294,6 +297,8 @@ extern const struct iwl_cfg iwl3160_2ac_cfg;
 extern const struct iwl_cfg iwl3160_2n_cfg;
 extern const struct iwl_cfg iwl3160_n_cfg;
 extern const struct iwl_cfg iwl7265_2ac_cfg;
+extern const struct iwl_cfg iwl7265_2n_cfg;
+extern const struct iwl_cfg iwl7265_n_cfg;
 #endif /* CONFIG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
index 54a4fdc631b73c987f12e459e8245d38b18f0c0b..da4eca8b3007feabb267a1710c95a70306224455 100644 (file)
@@ -495,14 +495,11 @@ enum secure_load_status_reg {
  * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
  *
  * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
  */
 #define IWL_HOST_INT_TIMEOUT_MAX       (0xFF)
 #define IWL_HOST_INT_TIMEOUT_DEF       (0x40)
 #define IWL_HOST_INT_TIMEOUT_MIN       (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
+#define IWL_HOST_INT_OPER_MODE         BIT(31)
 
 /*****************************************************************************
  *                        7000/3000 series SHR DTS addresses                 *
index 5d066cbc5ac7eda17914e85c2510c53fe4a5be2a..75b72a956552759685613c249f51a31926059a8f 100644 (file)
@@ -391,7 +391,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
                                            BT_VALID_LUT |
                                            BT_VALID_WIFI_RX_SW_PRIO_BOOST |
                                            BT_VALID_WIFI_TX_SW_PRIO_BOOST |
-                                           BT_VALID_MULTI_PRIO_LUT |
                                            BT_VALID_CORUN_LUT_20 |
                                            BT_VALID_CORUN_LUT_40 |
                                            BT_VALID_ANT_ISOLATION |
@@ -842,6 +841,11 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
 
        sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
                                        lockdep_is_held(&mvm->mutex));
+
+       /* This can happen if the station has been removed right now */
+       if (IS_ERR_OR_NULL(sta))
+               return;
+
        mvmsta = (void *)sta->drv_priv;
 
        data->num_bss_ifaces++;
index 6f45966817bb4c1d34cd3a10c4db74536f4a13bf..b9b81e881dd011e5ca06747f2bcceea4ece64ac9 100644 (file)
@@ -895,7 +895,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm,
                /* new API returns next, not last-used seqno */
                if (mvm->fw->ucode_capa.flags &
                                IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)
-                       err -= 0x10;
+                       err = (u16) (err - 0x10);
        }
 
        iwl_free_resp(&cmd);
@@ -1549,7 +1549,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
        if (gtkdata.unhandled_cipher)
                return false;
        if (!gtkdata.num_keys)
-               return true;
+               goto out;
        if (!gtkdata.last_gtk)
                return false;
 
@@ -1600,6 +1600,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                                           (void *)&replay_ctr, GFP_KERNEL);
        }
 
+out:
        mvmvif->seqno_valid = true;
        /* +0x10 because the set API expects next-to-use, not last-used */
        mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10;
index 9864d713eb2cb54920053fb971a65866f5ec0bf4..a8fe6b41f9a34b417a12e5295c7b86c75361bb1b 100644 (file)
@@ -119,6 +119,10 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file,
 
        if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
                return -EINVAL;
+       if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
+               return -EINVAL;
+       if (drain < 0 || drain > 1)
+               return -EINVAL;
 
        mutex_lock(&mvm->mutex);
 
index 33cf56fdfc41f86b8bb517a8824740bdbb71a896..95ce4b601fef3050085518e59a4e32036c57fbfc 100644 (file)
@@ -176,8 +176,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * P2P Device discoveribility, while there are other higher priority
         * events in the system).
         */
-       if (WARN_ONCE(!le32_to_cpu(notif->status),
-                     "Failed to schedule time event\n")) {
+       if (!le32_to_cpu(notif->status)) {
+               bool start = le32_to_cpu(notif->action) &
+                               TE_V2_NOTIF_HOST_EVENT_START;
+               IWL_WARN(mvm, "Time Event %s notification failure\n",
+                        start ? "start" : "end");
                if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
                        iwl_mvm_te_clear_data(mvm, te_data);
                        return;
index 941c0c88f982639b28436a60e52a0fdc6fba8c4b..86605027c41d6b4187c15ba874ef8fe25056676e 100644 (file)
@@ -353,6 +353,27 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 
 /* 7265 Series */
        {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5012, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x500A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
 
        {0}
index fa22639b63c947d68247698cf109070a823b792b..051268c037b1d4f7d03715cdbf13b68311f883ff 100644 (file)
@@ -477,4 +477,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
                CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 }
 
+static inline void iwl_nic_error(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       set_bit(STATUS_FW_ERROR, &trans_pcie->status);
+       iwl_op_mode_nic_error(trans->op_mode);
+}
+
 #endif /* __iwl_trans_int_pcie_h__ */
index 3f237b42eb36d3c94cc84f94d0ba86b6a7861e41..be3995afa9d0acee4ce7f6e0d60907f896594c53 100644 (file)
@@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
 
        /* Set interrupt coalescing timer to default (2048 usecs) */
        iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+
+       /* W/A for interrupt coalescing bug in 7260 and 3160 */
+       if (trans->cfg->host_interrupt_operation_mode)
+               iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE);
 }
 
 static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
@@ -796,12 +800,13 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
        iwl_pcie_dump_csr(trans);
        iwl_dump_fh(trans, NULL);
 
+       /* set the ERROR bit before we wake up the caller */
        set_bit(STATUS_FW_ERROR, &trans_pcie->status);
        clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
        wake_up(&trans_pcie->wait_command_queue);
 
        local_bh_disable();
-       iwl_op_mode_nic_error(trans->op_mode);
+       iwl_nic_error(trans);
        local_bh_enable();
 }
 
index 5d9337bec67a87c59f3ccef73e5f5b26644930d5..cde9c16f6e4febb26c66c2206068bdba973c708a 100644 (file)
@@ -279,9 +279,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
        spin_lock_irqsave(&trans_pcie->irq_lock, flags);
        iwl_pcie_apm_init(trans);
 
-       /* Set interrupt coalescing calibration timer to default (512 usecs) */
-       iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
        spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
        iwl_pcie_set_pwr(trans, false);
index 059c5acad3a0d2e7b9eb73bf6466ef088e54e5c2..0adde919a258a65f9585651e8efb89add27f2add 100644 (file)
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
                        le32_to_cpu(txq->scratchbufs[i].scratch));
 
-       iwl_op_mode_nic_error(trans->op_mode);
+       iwl_nic_error(trans);
 }
 
 /*
@@ -1023,7 +1023,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
                if (nfreed++ > 0) {
                        IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
                                idx, q->write_ptr, q->read_ptr);
-                       iwl_op_mode_nic_error(trans->op_mode);
+                       iwl_nic_error(trans);
                }
        }
 
@@ -1562,7 +1562,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
                                       get_cmd_string(trans_pcie, cmd->id));
                        ret = -ETIMEDOUT;
 
-                       iwl_op_mode_nic_error(trans->op_mode);
+                       iwl_nic_error(trans);
 
                        goto cancel;
                }
index 9df7bc91a26f54c9812718e481c538895aa5b4f8..c72438bb2fafd24b8e59f416d4e4311752dce941 100644 (file)
@@ -383,6 +383,14 @@ struct hwsim_radiotap_hdr {
        __le16 rt_chbitmask;
 } __packed;
 
+struct hwsim_radiotap_ack_hdr {
+       struct ieee80211_radiotap_header hdr;
+       u8 rt_flags;
+       u8 pad;
+       __le16 rt_channel;
+       __le16 rt_chbitmask;
+} __packed;
+
 /* MAC80211_HWSIM netlinf family */
 static struct genl_family hwsim_genl_family = {
        .id = GENL_ID_GENERATE,
@@ -500,7 +508,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
                                       const u8 *addr)
 {
        struct sk_buff *skb;
-       struct hwsim_radiotap_hdr *hdr;
+       struct hwsim_radiotap_ack_hdr *hdr;
        u16 flags;
        struct ieee80211_hdr *hdr11;
 
@@ -511,14 +519,14 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
        if (skb == NULL)
                return;
 
-       hdr = (struct hwsim_radiotap_hdr *) skb_put(skb, sizeof(*hdr));
+       hdr = (struct hwsim_radiotap_ack_hdr *) skb_put(skb, sizeof(*hdr));
        hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
        hdr->hdr.it_pad = 0;
        hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
        hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
                                          (1 << IEEE80211_RADIOTAP_CHANNEL));
        hdr->rt_flags = 0;
-       hdr->rt_rate = 0;
+       hdr->pad = 0;
        hdr->rt_channel = cpu_to_le16(chan->center_freq);
        flags = IEEE80211_CHAN_2GHZ;
        hdr->rt_chbitmask = cpu_to_le16(flags);
@@ -1230,7 +1238,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
                                              HRTIMER_MODE_REL);
                } else if (!info->enable_beacon) {
                        unsigned int count = 0;
-                       ieee80211_iterate_active_interfaces(
+                       ieee80211_iterate_active_interfaces_atomic(
                                data->hw, IEEE80211_IFACE_ITER_NORMAL,
                                mac80211_hwsim_bcn_en_iter, &count);
                        wiphy_debug(hw->wiphy, "  beaconing vifs remaining: %u",
index c8e029df770e38cac9a52dccb660666bd8cc9f74..a09398fe9e2a67218f50530af8a0b4616443cbbb 100644 (file)
@@ -319,8 +319,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                if (bss_desc && bss_desc->ssid.ssid_len &&
                    (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
                                       ssid, &bss_desc->ssid))) {
-                       kfree(bss_desc);
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
 
                /* Exit Adhoc mode first */
index 2329cccf1fa6dd15f65c4dc30c54c62cce0551a7..870f1fa583702ee4bc61d9acab3e4925a4d984e0 100644 (file)
@@ -368,11 +368,11 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
                   unsigned long rx_ring_ref, unsigned int tx_evtchn,
                   unsigned int rx_evtchn)
 {
+       struct task_struct *task;
        int err = -ENOMEM;
 
-       /* Already connected through? */
-       if (vif->tx_irq)
-               return 0;
+       BUG_ON(vif->tx_irq);
+       BUG_ON(vif->task);
 
        err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
        if (err < 0)
@@ -411,14 +411,16 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
        }
 
        init_waitqueue_head(&vif->wq);
-       vif->task = kthread_create(xenvif_kthread,
-                                  (void *)vif, "%s", vif->dev->name);
-       if (IS_ERR(vif->task)) {
+       task = kthread_create(xenvif_kthread,
+                             (void *)vif, "%s", vif->dev->name);
+       if (IS_ERR(task)) {
                pr_warn("Could not allocate kthread for %s\n", vif->dev->name);
-               err = PTR_ERR(vif->task);
+               err = PTR_ERR(task);
                goto err_rx_unbind;
        }
 
+       vif->task = task;
+
        rtnl_lock();
        if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
                dev_set_mtu(vif->dev, ETH_DATA_LEN);
@@ -461,8 +463,10 @@ void xenvif_disconnect(struct xenvif *vif)
        if (netif_carrier_ok(vif->dev))
                xenvif_carrier_off(vif);
 
-       if (vif->task)
+       if (vif->task) {
                kthread_stop(vif->task);
+               vif->task = NULL;
+       }
 
        if (vif->tx_irq) {
                if (vif->tx_irq == vif->rx_irq)
index 919b6509455cfbaf45ba63c7d8b378fa13a8e758..27bbe58dcbe7bf424fdfd54a461af847836836eb 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/udp.h>
 
 #include <net/tcp.h>
+#include <net/ip6_checksum.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
@@ -451,7 +452,7 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        }
 
        /* Set up a GSO prefix descriptor, if necessary */
-       if ((1 << skb_shinfo(skb)->gso_type) & vif->gso_prefix_mask) {
+       if ((1 << gso_type) & vif->gso_prefix_mask) {
                req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
                meta = npo->meta + npo->meta_prod++;
                meta->gso_type = gso_type;
@@ -1148,75 +1149,95 @@ static int xenvif_set_skb_gso(struct xenvif *vif,
        return 0;
 }
 
-static inline void maybe_pull_tail(struct sk_buff *skb, unsigned int len)
+static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len,
+                                 unsigned int max)
 {
-       if (skb_is_nonlinear(skb) && skb_headlen(skb) < len) {
-               /* If we need to pullup then pullup to the max, so we
-                * won't need to do it again.
-                */
-               int target = min_t(int, skb->len, MAX_TCP_HEADER);
-               __pskb_pull_tail(skb, target - skb_headlen(skb));
-       }
+       if (skb_headlen(skb) >= len)
+               return 0;
+
+       /* If we need to pullup then pullup to the max, so we
+        * won't need to do it again.
+        */
+       if (max > skb->len)
+               max = skb->len;
+
+       if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
+               return -ENOMEM;
+
+       if (skb_headlen(skb) < len)
+               return -EPROTO;
+
+       return 0;
 }
 
+/* This value should be large enough to cover a tagged ethernet header plus
+ * maximally sized IP and TCP or UDP headers.
+ */
+#define MAX_IP_HDR_LEN 128
+
 static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                             int recalculate_partial_csum)
 {
-       struct iphdr *iph = (void *)skb->data;
-       unsigned int header_size;
        unsigned int off;
-       int err = -EPROTO;
+       bool fragment;
+       int err;
+
+       fragment = false;
 
-       off = sizeof(struct iphdr);
+       err = maybe_pull_tail(skb,
+                             sizeof(struct iphdr),
+                             MAX_IP_HDR_LEN);
+       if (err < 0)
+               goto out;
+
+       if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
+               fragment = true;
 
-       header_size = skb->network_header + off + MAX_IPOPTLEN;
-       maybe_pull_tail(skb, header_size);
+       off = ip_hdrlen(skb);
 
-       off = iph->ihl * 4;
+       err = -EPROTO;
+
+       if (fragment)
+               goto out;
 
-       switch (iph->protocol) {
+       switch (ip_hdr(skb)->protocol) {
        case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct tcphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_TCP, 0);
-               }
+               if (recalculate_partial_csum)
+                       tcp_hdr(skb)->check =
+                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                                  ip_hdr(skb)->daddr,
+                                                  skb->len - off,
+                                                  IPPROTO_TCP, 0);
                break;
        case IPPROTO_UDP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct udphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct udphdr *udph = udp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct udphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_UDP, 0);
-               }
+               if (recalculate_partial_csum)
+                       udp_hdr(skb)->check =
+                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                                  ip_hdr(skb)->daddr,
+                                                  skb->len - off,
+                                                  IPPROTO_UDP, 0);
                break;
        default:
-               if (net_ratelimit())
-                       netdev_err(vif->dev,
-                                  "Attempting to checksum a non-TCP/UDP packet, "
-                                  "dropping a protocol %d packet\n",
-                                  iph->protocol);
                goto out;
        }
 
@@ -1226,121 +1247,138 @@ out:
        return err;
 }
 
+/* This value should be large enough to cover a tagged ethernet header plus
+ * an IPv6 header, all options, and a maximal TCP or UDP header.
+ */
+#define MAX_IPV6_HDR_LEN 256
+
+#define OPT_HDR(type, skb, off) \
+       (type *)(skb_network_header(skb) + (off))
+
 static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                               int recalculate_partial_csum)
 {
-       int err = -EPROTO;
-       struct ipv6hdr *ipv6h = (void *)skb->data;
+       int err;
        u8 nexthdr;
-       unsigned int header_size;
        unsigned int off;
+       unsigned int len;
        bool fragment;
        bool done;
 
+       fragment = false;
        done = false;
 
        off = sizeof(struct ipv6hdr);
 
-       header_size = skb->network_header + off;
-       maybe_pull_tail(skb, header_size);
+       err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
+       if (err < 0)
+               goto out;
 
-       nexthdr = ipv6h->nexthdr;
+       nexthdr = ipv6_hdr(skb)->nexthdr;
 
-       while ((off <= sizeof(struct ipv6hdr) + ntohs(ipv6h->payload_len)) &&
-              !done) {
+       len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
+       while (off <= len && !done) {
                switch (nexthdr) {
                case IPPROTO_DSTOPTS:
                case IPPROTO_HOPOPTS:
                case IPPROTO_ROUTING: {
-                       struct ipv6_opt_hdr *hp = (void *)(skb->data + off);
+                       struct ipv6_opt_hdr *hp;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ipv6_opt_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ipv6_opt_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
+                       hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
                        nexthdr = hp->nexthdr;
                        off += ipv6_optlen(hp);
                        break;
                }
                case IPPROTO_AH: {
-                       struct ip_auth_hdr *hp = (void *)(skb->data + off);
+                       struct ip_auth_hdr *hp;
+
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ip_auth_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ip_auth_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       hp = OPT_HDR(struct ip_auth_hdr, skb, off);
+                       nexthdr = hp->nexthdr;
+                       off += ipv6_authlen(hp);
+                       break;
+               }
+               case IPPROTO_FRAGMENT: {
+                       struct frag_hdr *hp;
+
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct frag_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
+
+                       hp = OPT_HDR(struct frag_hdr, skb, off);
+
+                       if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
+                               fragment = true;
 
                        nexthdr = hp->nexthdr;
-                       off += (hp->hdrlen+2)<<2;
+                       off += sizeof(struct frag_hdr);
                        break;
                }
-               case IPPROTO_FRAGMENT:
-                       fragment = true;
-                       /* fall through */
                default:
                        done = true;
                        break;
                }
        }
 
-       if (!done) {
-               if (net_ratelimit())
-                       netdev_err(vif->dev, "Failed to parse packet header\n");
-               goto out;
-       }
+       err = -EPROTO;
 
-       if (fragment) {
-               if (net_ratelimit())
-                       netdev_err(vif->dev, "Packet is a fragment!\n");
+       if (!done || fragment)
                goto out;
-       }
 
        switch (nexthdr) {
        case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct tcphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       tcph->check = ~csum_ipv6_magic(&ipv6h->saddr,
-                                                      &ipv6h->daddr,
-                                                      skb->len - off,
-                                                      IPPROTO_TCP, 0);
-               }
+               if (recalculate_partial_csum)
+                       tcp_hdr(skb)->check =
+                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+                                                &ipv6_hdr(skb)->daddr,
+                                                skb->len - off,
+                                                IPPROTO_TCP, 0);
                break;
        case IPPROTO_UDP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct udphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct udphdr *udph = udp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct udphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       udph->check = ~csum_ipv6_magic(&ipv6h->saddr,
-                                                      &ipv6h->daddr,
-                                                      skb->len - off,
-                                                      IPPROTO_UDP, 0);
-               }
+               if (recalculate_partial_csum)
+                       udp_hdr(skb)->check =
+                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+                                                &ipv6_hdr(skb)->daddr,
+                                                skb->len - off,
+                                                IPPROTO_UDP, 0);
                break;
        default:
-               if (net_ratelimit())
-                       netdev_err(vif->dev,
-                                  "Attempting to checksum a non-TCP/UDP packet, "
-                                  "dropping a protocol %d packet\n",
-                                  nexthdr);
                goto out;
        }
 
@@ -1410,14 +1448,15 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
        return false;
 }
 
-static unsigned xenvif_tx_build_gops(struct xenvif *vif)
+static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
 {
        struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop;
        struct sk_buff *skb;
        int ret;
 
        while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX
-               < MAX_PENDING_REQS)) {
+               < MAX_PENDING_REQS) &&
+              (skb_queue_len(&vif->tx_queue) < budget)) {
                struct xen_netif_tx_request txreq;
                struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX];
                struct page *page;
@@ -1439,7 +1478,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif)
                        continue;
                }
 
-               RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
+               work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
                if (!work_to_do)
                        break;
 
@@ -1579,14 +1618,13 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif)
 }
 
 
-static int xenvif_tx_submit(struct xenvif *vif, int budget)
+static int xenvif_tx_submit(struct xenvif *vif)
 {
        struct gnttab_copy *gop = vif->tx_copy_ops;
        struct sk_buff *skb;
        int work_done = 0;
 
-       while (work_done < budget &&
-              (skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
+       while ((skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
                struct xen_netif_tx_request *txp;
                u16 pending_idx;
                unsigned data_len;
@@ -1661,14 +1699,14 @@ int xenvif_tx_action(struct xenvif *vif, int budget)
        if (unlikely(!tx_work_todo(vif)))
                return 0;
 
-       nr_gops = xenvif_tx_build_gops(vif);
+       nr_gops = xenvif_tx_build_gops(vif, budget);
 
        if (nr_gops == 0)
                return 0;
 
        gnttab_batch_copy(vif->tx_copy_ops, nr_gops);
 
-       work_done = xenvif_tx_submit(vif, nr_gops);
+       work_done = xenvif_tx_submit(vif);
 
        return work_done;
 }
index 1cb6e51e6bda97aadb4ba88bd46123544dcc4140..170e8e60cdb7fe3d47307d4b9146039e3af7f3a8 100644 (file)
@@ -141,6 +141,24 @@ void ntb_unregister_event_callback(struct ntb_device *ndev)
        ndev->event_cb = NULL;
 }
 
+static void ntb_irq_work(unsigned long data)
+{
+       struct ntb_db_cb *db_cb = (struct ntb_db_cb *)data;
+       int rc;
+
+       rc = db_cb->callback(db_cb->data, db_cb->db_num);
+       if (rc)
+               tasklet_schedule(&db_cb->irq_work);
+       else {
+               struct ntb_device *ndev = db_cb->ndev;
+               unsigned long mask;
+
+               mask = readw(ndev->reg_ofs.ldb_mask);
+               clear_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
+               writew(mask, ndev->reg_ofs.ldb_mask);
+       }
+}
+
 /**
  * ntb_register_db_callback() - register a callback for doorbell interrupt
  * @ndev: pointer to ntb_device instance
@@ -155,7 +173,7 @@ void ntb_unregister_event_callback(struct ntb_device *ndev)
  * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  */
 int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
-                            void *data, void (*func)(void *data, int db_num))
+                            void *data, int (*func)(void *data, int db_num))
 {
        unsigned long mask;
 
@@ -166,6 +184,10 @@ int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
 
        ndev->db_cb[idx].callback = func;
        ndev->db_cb[idx].data = data;
+       ndev->db_cb[idx].ndev = ndev;
+
+       tasklet_init(&ndev->db_cb[idx].irq_work, ntb_irq_work,
+                    (unsigned long) &ndev->db_cb[idx]);
 
        /* unmask interrupt */
        mask = readw(ndev->reg_ofs.ldb_mask);
@@ -194,6 +216,8 @@ void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx)
        set_bit(idx * ndev->bits_per_vector, &mask);
        writew(mask, ndev->reg_ofs.ldb_mask);
 
+       tasklet_disable(&ndev->db_cb[idx].irq_work);
+
        ndev->db_cb[idx].callback = NULL;
 }
 
@@ -678,6 +702,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
                                return -EINVAL;
 
                        ndev->limits.max_mw = SNB_ERRATA_MAX_MW;
+                       ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
                        ndev->reg_ofs.spad_write = ndev->mw[1].vbase +
                                                   SNB_SPAD_OFFSET;
                        ndev->reg_ofs.rdb = ndev->mw[1].vbase +
@@ -688,8 +713,21 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
                         */
                        writeq(ndev->mw[1].bar_sz + 0x1000, ndev->reg_base +
                               SNB_PBAR4LMT_OFFSET);
+                       /* HW errata on the Limit registers.  They can only be
+                        * written when the base register is 4GB aligned and
+                        * < 32bit.  This should already be the case based on the
+                        * driver defaults, but write the Limit registers first
+                        * just in case.
+                        */
                } else {
                        ndev->limits.max_mw = SNB_MAX_MW;
+
+                       /* HW Errata on bit 14 of b2bdoorbell register.  Writes
+                        * will not be mirrored to the remote system.  Shrink
+                        * the number of bits by one, since bit 14 is the last
+                        * bit.
+                        */
+                       ndev->limits.max_db_bits = SNB_MAX_DB_BITS - 1;
                        ndev->reg_ofs.spad_write = ndev->reg_base +
                                                   SNB_B2B_SPAD_OFFSET;
                        ndev->reg_ofs.rdb = ndev->reg_base +
@@ -699,6 +737,12 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
                         * something silly
                         */
                        writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET);
+                       /* HW errata on the Limit registers.  They can only be
+                        * written when the base register is 4GB aligned and
+                        * < 32bit.  This should already be the case based on the
+                        * driver defaults, but write the Limit registers first
+                        * just in case.
+                        */
                }
 
                /* The Xeon errata workaround requires setting SBAR Base
@@ -769,6 +813,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
                 * have an equal amount.
                 */
                ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2;
+               ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
                /* Note: The SDOORBELL is the cause of the errata.  You REALLY
                 * don't want to touch it.
                 */
@@ -793,6 +838,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
                 * have an equal amount.
                 */
                ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2;
+               ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
                ndev->reg_ofs.rdb = ndev->reg_base + SNB_PDOORBELL_OFFSET;
                ndev->reg_ofs.ldb = ndev->reg_base + SNB_SDOORBELL_OFFSET;
                ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_SDBMSK_OFFSET;
@@ -819,7 +865,6 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
        ndev->reg_ofs.lnk_stat = ndev->reg_base + SNB_SLINK_STATUS_OFFSET;
        ndev->reg_ofs.spci_cmd = ndev->reg_base + SNB_PCICMD_OFFSET;
 
-       ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
        ndev->limits.msix_cnt = SNB_MSIX_CNT;
        ndev->bits_per_vector = SNB_DB_BITS_PER_VEC;
 
@@ -934,12 +979,16 @@ static irqreturn_t bwd_callback_msix_irq(int irq, void *data)
 {
        struct ntb_db_cb *db_cb = data;
        struct ntb_device *ndev = db_cb->ndev;
+       unsigned long mask;
 
        dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq,
                db_cb->db_num);
 
-       if (db_cb->callback)
-               db_cb->callback(db_cb->data, db_cb->db_num);
+       mask = readw(ndev->reg_ofs.ldb_mask);
+       set_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
+       writew(mask, ndev->reg_ofs.ldb_mask);
+
+       tasklet_schedule(&db_cb->irq_work);
 
        /* No need to check for the specific HB irq, any interrupt means
         * we're connected.
@@ -955,12 +1004,16 @@ static irqreturn_t xeon_callback_msix_irq(int irq, void *data)
 {
        struct ntb_db_cb *db_cb = data;
        struct ntb_device *ndev = db_cb->ndev;
+       unsigned long mask;
 
        dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq,
                db_cb->db_num);
 
-       if (db_cb->callback)
-               db_cb->callback(db_cb->data, db_cb->db_num);
+       mask = readw(ndev->reg_ofs.ldb_mask);
+       set_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
+       writew(mask, ndev->reg_ofs.ldb_mask);
+
+       tasklet_schedule(&db_cb->irq_work);
 
        /* On Sandybridge, there are 16 bits in the interrupt register
         * but only 4 vectors.  So, 5 bits are assigned to the first 3
@@ -986,7 +1039,7 @@ static irqreturn_t xeon_event_msix_irq(int irq, void *dev)
                dev_err(&ndev->pdev->dev, "Error determining link status\n");
 
        /* bit 15 is always the link bit */
-       writew(1 << ndev->limits.max_db_bits, ndev->reg_ofs.ldb);
+       writew(1 << SNB_LINK_DB, ndev->reg_ofs.ldb);
 
        return IRQ_HANDLED;
 }
@@ -1075,6 +1128,10 @@ static int ntb_setup_msix(struct ntb_device *ndev)
                         "Only %d MSI-X vectors.  Limiting the number of queues to that number.\n",
                         rc);
                msix_entries = rc;
+
+               rc = pci_enable_msix(pdev, ndev->msix_entries, msix_entries);
+               if (rc)
+                       goto err1;
        }
 
        for (i = 0; i < msix_entries; i++) {
@@ -1176,9 +1233,10 @@ static int ntb_setup_interrupts(struct ntb_device *ndev)
         */
        if (ndev->hw_type == BWD_HW)
                writeq(~0, ndev->reg_ofs.ldb_mask);
-       else
-               writew(~(1 << ndev->limits.max_db_bits),
-                      ndev->reg_ofs.ldb_mask);
+       else {
+               u16 var = 1 << SNB_LINK_DB;
+               writew(~var, ndev->reg_ofs.ldb_mask);
+       }
 
        rc = ntb_setup_msix(ndev);
        if (!rc)
@@ -1286,6 +1344,39 @@ static void ntb_free_debugfs(struct ntb_device *ndev)
        }
 }
 
+static void ntb_hw_link_up(struct ntb_device *ndev)
+{
+       if (ndev->conn_type == NTB_CONN_TRANSPARENT)
+               ntb_link_event(ndev, NTB_LINK_UP);
+       else {
+               u32 ntb_cntl;
+
+               /* Let's bring the NTB link up */
+               ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
+               ntb_cntl &= ~(NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK);
+               ntb_cntl |= NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP;
+               ntb_cntl |= NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP;
+               writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
+       }
+}
+
+static void ntb_hw_link_down(struct ntb_device *ndev)
+{
+       u32 ntb_cntl;
+
+       if (ndev->conn_type == NTB_CONN_TRANSPARENT) {
+               ntb_link_event(ndev, NTB_LINK_DOWN);
+               return;
+       }
+
+       /* Bring NTB link down */
+       ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
+       ntb_cntl &= ~(NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP);
+       ntb_cntl &= ~(NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP);
+       ntb_cntl |= NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK;
+       writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
+}
+
 static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct ntb_device *ndev;
@@ -1374,9 +1465,7 @@ static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                goto err6;
 
-       /* Let's bring the NTB link up */
-       writel(NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP,
-              ndev->reg_ofs.lnk_cntl);
+       ntb_hw_link_up(ndev);
 
        return 0;
 
@@ -1406,12 +1495,8 @@ static void ntb_pci_remove(struct pci_dev *pdev)
 {
        struct ntb_device *ndev = pci_get_drvdata(pdev);
        int i;
-       u32 ntb_cntl;
 
-       /* Bring NTB link down */
-       ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
-       ntb_cntl |= NTB_CNTL_LINK_DISABLE;
-       writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
+       ntb_hw_link_down(ndev);
 
        ntb_transport_free(ndev->ntb_transport);
 
index 0a31cedae7d42f9227d125bfabe97297b47255d9..bbdb7edca10cd8647e4b739dfab29f1ed33fc1e6 100644 (file)
@@ -106,10 +106,11 @@ struct ntb_mw {
 };
 
 struct ntb_db_cb {
-       void (*callback) (void *data, int db_num);
+       int (*callback)(void *data, int db_num);
        unsigned int db_num;
        void *data;
        struct ntb_device *ndev;
+       struct tasklet_struct irq_work;
 };
 
 struct ntb_device {
@@ -228,8 +229,8 @@ struct ntb_device *ntb_register_transport(struct pci_dev *pdev,
 void ntb_unregister_transport(struct ntb_device *ndev);
 void ntb_set_mw_addr(struct ntb_device *ndev, unsigned int mw, u64 addr);
 int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
-                            void *data, void (*db_cb_func) (void *data,
-                                                            int db_num));
+                            void *data, int (*db_cb_func)(void *data,
+                                                          int db_num));
 void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx);
 int ntb_register_event_callback(struct ntb_device *ndev,
                                void (*event_cb_func) (void *handle,
index aa4bdd393c58ee2c4cf40105b1644afdcb19913c..9774506419d75ba1a5dc08a5f0e4d52e90d33ad7 100644 (file)
@@ -55,6 +55,7 @@
 #define SNB_MAX_COMPAT_SPADS   16
 /* Reserve the uppermost bit for link interrupt */
 #define SNB_MAX_DB_BITS                15
+#define SNB_LINK_DB            15
 #define SNB_DB_BITS_PER_VEC    5
 #define SNB_MAX_MW             2
 #define SNB_ERRATA_MAX_MW      1
@@ -75,9 +76,6 @@
 #define SNB_SBAR2XLAT_OFFSET   0x0030
 #define SNB_SBAR4XLAT_OFFSET   0x0038
 #define SNB_SBAR0BASE_OFFSET   0x0040
-#define SNB_SBAR0BASE_OFFSET   0x0040
-#define SNB_SBAR2BASE_OFFSET   0x0048
-#define SNB_SBAR4BASE_OFFSET   0x0050
 #define SNB_SBAR2BASE_OFFSET   0x0048
 #define SNB_SBAR4BASE_OFFSET   0x0050
 #define SNB_NTBCNTL_OFFSET     0x0058
 #define BWD_LTSSMSTATEJMP_FORCEDETECT  (1 << 2)
 #define BWD_IBIST_ERR_OFLOW    0x7FFF7FFF
 
-#define NTB_CNTL_CFG_LOCK      (1 << 0)
-#define NTB_CNTL_LINK_DISABLE  (1 << 1)
-#define NTB_CNTL_BAR23_SNOOP   (1 << 2)
-#define NTB_CNTL_BAR45_SNOOP   (1 << 6)
-#define BWD_CNTL_LINK_DOWN     (1 << 16)
+#define NTB_CNTL_CFG_LOCK              (1 << 0)
+#define NTB_CNTL_LINK_DISABLE          (1 << 1)
+#define NTB_CNTL_S2P_BAR23_SNOOP       (1 << 2)
+#define NTB_CNTL_P2S_BAR23_SNOOP       (1 << 4)
+#define NTB_CNTL_S2P_BAR45_SNOOP       (1 << 6)
+#define NTB_CNTL_P2S_BAR45_SNOOP       (1 << 8)
+#define BWD_CNTL_LINK_DOWN             (1 << 16)
 
 #define NTB_PPD_OFFSET         0x00D4
 #define SNB_PPD_CONN_TYPE      0x0003
index d0222f13d154808f3cfa4ed3cab26cd1a7b899ee..3217f394d45b106051b282f824be1413b5efa65d 100644 (file)
@@ -119,7 +119,6 @@ struct ntb_transport_qp {
 
        void (*rx_handler) (struct ntb_transport_qp *qp, void *qp_data,
                            void *data, int len);
-       struct tasklet_struct rx_work;
        struct list_head rx_pend_q;
        struct list_head rx_free_q;
        spinlock_t ntb_rx_pend_q_lock;
@@ -584,11 +583,8 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size)
        return 0;
 }
 
-static void ntb_qp_link_cleanup(struct work_struct *work)
+static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
 {
-       struct ntb_transport_qp *qp = container_of(work,
-                                                  struct ntb_transport_qp,
-                                                  link_cleanup);
        struct ntb_transport *nt = qp->transport;
        struct pci_dev *pdev = ntb_query_pdev(nt->ndev);
 
@@ -602,6 +598,16 @@ static void ntb_qp_link_cleanup(struct work_struct *work)
 
        dev_info(&pdev->dev, "qp %d: Link Down\n", qp->qp_num);
        qp->qp_link = NTB_LINK_DOWN;
+}
+
+static void ntb_qp_link_cleanup_work(struct work_struct *work)
+{
+       struct ntb_transport_qp *qp = container_of(work,
+                                                  struct ntb_transport_qp,
+                                                  link_cleanup);
+       struct ntb_transport *nt = qp->transport;
+
+       ntb_qp_link_cleanup(qp);
 
        if (nt->transport_link == NTB_LINK_UP)
                schedule_delayed_work(&qp->link_work,
@@ -613,22 +619,20 @@ static void ntb_qp_link_down(struct ntb_transport_qp *qp)
        schedule_work(&qp->link_cleanup);
 }
 
-static void ntb_transport_link_cleanup(struct work_struct *work)
+static void ntb_transport_link_cleanup(struct ntb_transport *nt)
 {
-       struct ntb_transport *nt = container_of(work, struct ntb_transport,
-                                               link_cleanup);
        int i;
 
+       /* Pass along the info to any clients */
+       for (i = 0; i < nt->max_qps; i++)
+               if (!test_bit(i, &nt->qp_bitmap))
+                       ntb_qp_link_cleanup(&nt->qps[i]);
+
        if (nt->transport_link == NTB_LINK_DOWN)
                cancel_delayed_work_sync(&nt->link_work);
        else
                nt->transport_link = NTB_LINK_DOWN;
 
-       /* Pass along the info to any clients */
-       for (i = 0; i < nt->max_qps; i++)
-               if (!test_bit(i, &nt->qp_bitmap))
-                       ntb_qp_link_down(&nt->qps[i]);
-
        /* The scratchpad registers keep the values if the remote side
         * goes down, blast them now to give them a sane value the next
         * time they are accessed
@@ -637,6 +641,14 @@ static void ntb_transport_link_cleanup(struct work_struct *work)
                ntb_write_local_spad(nt->ndev, i, 0);
 }
 
+static void ntb_transport_link_cleanup_work(struct work_struct *work)
+{
+       struct ntb_transport *nt = container_of(work, struct ntb_transport,
+                                               link_cleanup);
+
+       ntb_transport_link_cleanup(nt);
+}
+
 static void ntb_transport_event_callback(void *data, enum ntb_hw_event event)
 {
        struct ntb_transport *nt = data;
@@ -880,7 +892,7 @@ static int ntb_transport_init_queue(struct ntb_transport *nt,
        }
 
        INIT_DELAYED_WORK(&qp->link_work, ntb_qp_link_work);
-       INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup);
+       INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup_work);
 
        spin_lock_init(&qp->ntb_rx_pend_q_lock);
        spin_lock_init(&qp->ntb_rx_free_q_lock);
@@ -936,7 +948,7 @@ int ntb_transport_init(struct pci_dev *pdev)
        }
 
        INIT_DELAYED_WORK(&nt->link_work, ntb_transport_link_work);
-       INIT_WORK(&nt->link_cleanup, ntb_transport_link_cleanup);
+       INIT_WORK(&nt->link_cleanup, ntb_transport_link_cleanup_work);
 
        rc = ntb_register_event_callback(nt->ndev,
                                         ntb_transport_event_callback);
@@ -972,7 +984,7 @@ void ntb_transport_free(void *transport)
        struct ntb_device *ndev = nt->ndev;
        int i;
 
-       nt->transport_link = NTB_LINK_DOWN;
+       ntb_transport_link_cleanup(nt);
 
        /* verify that all the qp's are freed */
        for (i = 0; i < nt->max_qps; i++) {
@@ -1188,11 +1200,14 @@ err:
        goto out;
 }
 
-static void ntb_transport_rx(unsigned long data)
+static int ntb_transport_rxc_db(void *data, int db_num)
 {
-       struct ntb_transport_qp *qp = (struct ntb_transport_qp *)data;
+       struct ntb_transport_qp *qp = data;
        int rc, i;
 
+       dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%s: doorbell %d received\n",
+               __func__, db_num);
+
        /* Limit the number of packets processed in a single interrupt to
         * provide fairness to others
         */
@@ -1204,16 +1219,8 @@ static void ntb_transport_rx(unsigned long data)
 
        if (qp->dma_chan)
                dma_async_issue_pending(qp->dma_chan);
-}
-
-static void ntb_transport_rxc_db(void *data, int db_num)
-{
-       struct ntb_transport_qp *qp = data;
-
-       dev_dbg(&ntb_query_pdev(qp->ndev)->dev, "%s: doorbell %d received\n",
-               __func__, db_num);
 
-       tasklet_schedule(&qp->rx_work);
+       return i;
 }
 
 static void ntb_tx_copy_callback(void *data)
@@ -1432,11 +1439,12 @@ ntb_transport_create_queue(void *data, struct pci_dev *pdev,
        qp->tx_handler = handlers->tx_handler;
        qp->event_handler = handlers->event_handler;
 
+       dmaengine_get();
        qp->dma_chan = dma_find_channel(DMA_MEMCPY);
-       if (!qp->dma_chan)
+       if (!qp->dma_chan) {
+               dmaengine_put();
                dev_info(&pdev->dev, "Unable to allocate DMA channel, using CPU instead\n");
-       else
-               dmaengine_get();
+       }
 
        for (i = 0; i < NTB_QP_DEF_NUM_ENTRIES; i++) {
                entry = kzalloc(sizeof(struct ntb_queue_entry), GFP_ATOMIC);
@@ -1458,25 +1466,23 @@ ntb_transport_create_queue(void *data, struct pci_dev *pdev,
                             &qp->tx_free_q);
        }
 
-       tasklet_init(&qp->rx_work, ntb_transport_rx, (unsigned long) qp);
-
        rc = ntb_register_db_callback(qp->ndev, free_queue, qp,
                                      ntb_transport_rxc_db);
        if (rc)
-               goto err3;
+               goto err2;
 
        dev_info(&pdev->dev, "NTB Transport QP %d created\n", qp->qp_num);
 
        return qp;
 
-err3:
-       tasklet_disable(&qp->rx_work);
 err2:
        while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q)))
                kfree(entry);
 err1:
        while ((entry = ntb_list_rm(&qp->ntb_rx_free_q_lock, &qp->rx_free_q)))
                kfree(entry);
+       if (qp->dma_chan)
+               dmaengine_put();
        set_bit(free_queue, &nt->qp_bitmap);
 err:
        return NULL;
@@ -1515,7 +1521,6 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
        }
 
        ntb_unregister_db_callback(qp->ndev, qp->qp_num);
-       tasklet_disable(&qp->rx_work);
 
        cancel_delayed_work_sync(&qp->link_work);
 
index c269e430c760a9bc80ad982db9cb4aa211f16f45..2aa7b77c7c88bab6c2b70b79666205c061afec7d 100644 (file)
@@ -447,6 +447,11 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
                *value = 0;
                break;
 
+       case PCI_INTERRUPT_LINE:
+               /* LINE PIN MIN_GNT MAX_LAT */
+               *value = 0;
+               break;
+
        default:
                *value = 0xffffffff;
                return PCIBIOS_BAD_REGISTER_NUMBER;
index 9042fdbd724405bc96808ed699a1d543fcf17c17..25f0bc6591645707bb3b452bbaa4c28bee0efc59 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
+#include <linux/kexec.h>
 #include "pci.h"
 
 struct pci_dynid {
@@ -288,12 +289,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
        int error, node;
        struct drv_dev_and_id ddi = { drv, dev, id };
 
-       /* Execute driver initialization on node where the device's
-          bus is attached to.  This way the driver likely allocates
-          its local memory on the right node without any need to
-          change it. */
+       /*
+        * Execute driver initialization on node where the device is
+        * attached.  This way the driver likely allocates its local memory
+        * on the right node.
+        */
        node = dev_to_node(&dev->dev);
-       if (node >= 0) {
+
+       /*
+        * On NUMA systems, we are likely to call a PF probe function using
+        * work_on_cpu().  If that probe calls pci_enable_sriov() (which
+        * adds the VF devices via pci_bus_add_device()), we may re-enter
+        * this function to call the VF probe function.  Calling
+        * work_on_cpu() again will cause a lockdep warning.  Since VFs are
+        * always on the same node as the PF, we can work around this by
+        * avoiding work_on_cpu() when we're already on the correct node.
+        *
+        * Preemption is enabled, so it's theoretically unsafe to use
+        * numa_node_id(), but even if we run the probe function on the
+        * wrong node, it should be functionally correct.
+        */
+       if (node >= 0 && node != numa_node_id()) {
                int cpu;
 
                get_online_cpus();
@@ -305,6 +321,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
                put_online_cpus();
        } else
                error = local_pci_probe(&ddi);
+
        return error;
 }
 
@@ -399,12 +416,17 @@ static void pci_device_shutdown(struct device *dev)
        pci_msi_shutdown(pci_dev);
        pci_msix_shutdown(pci_dev);
 
+#ifdef CONFIG_KEXEC
        /*
-        * Turn off Bus Master bit on the device to tell it to not
-        * continue to do DMA. Don't touch devices in D3cold or unknown states.
+        * If this is a kexec reboot, turn off Bus Master bit on the
+        * device to tell it to not continue to do DMA. Don't touch
+        * devices in D3cold or unknown states.
+        * If it is not a kexec reboot, firmware will hit the PCI
+        * devices with big hammer and stop their DMA any way.
         */
-       if (pci_dev->current_state <= PCI_D3hot)
+       if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot))
                pci_clear_master(pci_dev);
+#endif
 }
 
 #ifdef CONFIG_PM
index 33120d15666895a2b48aec1c83f7b41f7b93c3be..07369f32e8bbdd79b1294ad844baeb7dc80ef7ea 100644 (file)
@@ -4165,6 +4165,14 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
        return 0;
 }
 
+bool pci_device_is_present(struct pci_dev *pdev)
+{
+       u32 v;
+
+       return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
+}
+EXPORT_SYMBOL_GPL(pci_device_is_present);
+
 #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
 static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
 static DEFINE_SPINLOCK(resource_alignment_lock);
index b3b1b9aa8863817e16812fdb65a26cb6dd1c27fd..3a02717473adc7dfb775a543d6c8f786ddb91ff4 100644 (file)
@@ -9,10 +9,6 @@
  *
  *  Init/reset quirks for USB host controllers should be in the
  *  USB quirks file, where their drivers can access reuse it.
- *
- *  The bridge optimization stuff has been removed. If you really
- *  have a silly BIOS which is unable to set your host bridge right,
- *  use the PowerTweak utility (see http://powertweak.sourceforge.net).
  */
 
 #include <linux/types.h>
index 1576851028db700be2413b01e815cc8387b3cd47..cc9337a71529180eaebc7beb991dfb7c9e186ea8 100644 (file)
@@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev)
        if (dev->is_added) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
-               device_del(&dev->dev);
+               device_release_driver(&dev->dev);
                dev->is_added = 0;
        }
 
@@ -34,6 +34,8 @@ static void pci_stop_dev(struct pci_dev *dev)
 
 static void pci_destroy_dev(struct pci_dev *dev)
 {
+       device_del(&dev->dev);
+
        down_write(&pci_bus_sem);
        list_del(&dev->bus_list);
        up_write(&pci_bus_sem);
index a344f3d52361f0eed4d2a0d1fdc81a957e3a7967..330ef2d065670eb91b84a6d553bdf1df2dabf79f 100644 (file)
@@ -24,8 +24,8 @@ config PHY_EXYNOS_MIPI_VIDEO
 config OMAP_USB2
        tristate "OMAP USB2 PHY Driver"
        depends on ARCH_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        select OMAP_CONTROL_USB
        help
          Enable this to support the transceiver that is part of SOC. This
@@ -36,8 +36,8 @@ config OMAP_USB2
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
        depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        help
          Enable this to support the USB OTG transceiver on TWL4030
          family chips (including the TWL5030 and TPS659x0 devices).
index 03cf8fb815543537fb14995fde36a5216706dab9..58e0e97390287364287eae1eecdf8b43ba7b72f1 100644 (file)
@@ -437,23 +437,18 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
        int id;
        struct phy *phy;
 
-       if (!dev) {
-               dev_WARN(dev, "no device provided for PHY\n");
-               ret = -EINVAL;
-               goto err0;
-       }
+       if (WARN_ON(!dev))
+               return ERR_PTR(-EINVAL);
 
        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               ret = -ENOMEM;
-               goto err0;
-       }
+       if (!phy)
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
        if (id < 0) {
                dev_err(dev, "unable to get id\n");
                ret = id;
-               goto err0;
+               goto free_phy;
        }
 
        device_initialize(&phy->dev);
@@ -468,11 +463,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        ret = device_add(&phy->dev);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        if (pm_runtime_enabled(dev)) {
                pm_runtime_enable(&phy->dev);
@@ -481,12 +476,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        return phy;
 
-err1:
-       ida_remove(&phy_ida, phy->id);
+put_dev:
        put_device(&phy->dev);
+       ida_remove(&phy_ida, phy->id);
+free_phy:
        kfree(phy);
-
-err0:
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(phy_create);
index 4780959e11d4c858e55703bee4a3835876d05550..5183e7bb8de33632618b360c2c607009539c73b8 100644 (file)
@@ -418,7 +418,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        ret = abx500_gpio_set_bits(chip,
                                        AB8500_GPIO_ALTFUN_REG,
                                        af.alt_bit1,
-                                       !!(af.alta_val && BIT(0)));
+                                       !!(af.alta_val & BIT(0)));
                        if (ret < 0)
                                goto out;
 
@@ -439,7 +439,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        goto out;
 
                ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-                               af.alt_bit1, !!(af.altb_val && BIT(0)));
+                               af.alt_bit1, !!(af.altb_val & BIT(0)));
                if (ret < 0)
                        goto out;
 
@@ -462,7 +462,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        goto out;
 
                ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-                               af.alt_bit2, !!(af.altc_val && BIT(1)));
+                               af.alt_bit2, !!(af.altc_val & BIT(1)));
                break;
 
        default:
index eeca8f97399923c462f43328b1850ad3da7ee77d..82293806e842c1b86b55c1b8f229da1aec1c58d5 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef PINCTRL_PINCTRL_ABx5O0_H
+#ifndef PINCTRL_PINCTRL_ABx500_H
 #define PINCTRL_PINCTRL_ABx500_H
 
 /* Package definitions */
index 2832576d8b12ee7c99e24896c3fe333dd8cffadc..114f5ef4b73abdbcd02e524a1a34f84aeeb5b7cb 100644 (file)
@@ -512,6 +512,7 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
 
 static const struct acpi_device_id byt_gpio_acpi_match[] = {
        { "INT33B2", 0 },
+       { "INT33FC", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
index e939c28cbf1fe13573f7538a2e9d01071b094aa1..46dddc159286387dbbbe979d729d4d00cf159d43 100644 (file)
@@ -504,6 +504,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                        data |= (3 << bit);
                        break;
                default:
+                       spin_unlock_irqrestore(&bank->slock, flags);
                        dev_err(info->dev, "unsupported pull setting %d\n",
                                pull);
                        return -EINVAL;
@@ -1453,8 +1454,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
        if (ctrl->type == RK3188) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                info->reg_pull = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(info->reg_base))
-                       return PTR_ERR(info->reg_base);
+               if (IS_ERR(info->reg_pull))
+                       return PTR_ERR(info->reg_pull);
        }
 
        ret = rockchip_gpiolib_register(pdev, info);
index 009174d07767ff71451ac70cb4ce4de8b50efdf1..bc5eb453a45ccfb7826e60825b75afed8de868a7 100644 (file)
@@ -3720,7 +3720,7 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
                const struct r8a7740_portcr_group *group =
                        &r8a7740_portcr_offsets[i];
 
-               if (i <= group->end_pin)
+               if (pin <= group->end_pin)
                        return pfc->window->virt + group->offset + pin;
        }
 
index 70b522d348218e43dad2952f9c54b3c90c18c215..cc097b6938208ea029902f8dc2f68af548f9429a 100644 (file)
@@ -2584,7 +2584,7 @@ static void __iomem *sh7372_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
                const struct sh7372_portcr_group *group =
                        &sh7372_portcr_offsets[i];
 
-               if (i <= group->end_pin)
+               if (pin <= group->end_pin)
                        return pfc->window->virt + group->offset + pin;
        }
 
index 11bd0d970a5246a378185e77955e957d7b4e7376..e2142956a8e5fff5bd1363f3e6837e00b1064bff 100644 (file)
@@ -254,7 +254,7 @@ struct sh_pfc_soc_info {
 #define PINMUX_GPIO(_pin)                                              \
        [GPIO_##_pin] = {                                               \
                .pin = (u16)-1,                                         \
-               .name = __stringify(name),                              \
+               .name = __stringify(GPIO_##_pin),                       \
                .enum_id = _pin##_DATA,                                 \
        }
 
index 69616aeaa966218efa16eb3858324107e816e7bf..09fde58b12e0fa1e2446d56218fa644f32aeeef1 100644 (file)
@@ -5,3 +5,4 @@ if GOLDFISH
 source "drivers/platform/goldfish/Kconfig"
 endif
 
+source "drivers/platform/chrome/Kconfig"
index 8a44a4cd6d1efc30789d5da4cc392447695d68ae..3656b7b17b99ee8ecc806fd21f3fa493873ff122 100644 (file)
@@ -5,3 +5,4 @@
 obj-$(CONFIG_X86)              += x86/
 obj-$(CONFIG_OLPC)             += olpc/
 obj-$(CONFIG_GOLDFISH)         += goldfish/
+obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
new file mode 100644 (file)
index 0000000..b13303e
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# Platform support for Chrome OS hardware (Chromebooks and Chromeboxes)
+#
+
+menuconfig CHROME_PLATFORMS
+       bool "Platform support for Chrome hardware"
+       depends on X86
+       ---help---
+         Say Y here to get to see options for platform support for
+         various Chromebooks and Chromeboxes. This option alone does
+         not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and disabled.
+
+if CHROME_PLATFORMS
+
+config CHROMEOS_LAPTOP
+       tristate "Chrome OS Laptop"
+       depends on I2C
+       depends on DMI
+       ---help---
+         This driver instantiates i2c and smbus devices such as
+         light sensors and touchpads.
+
+         If you have a supported Chromebook, choose Y or M here.
+         The module will be called chromeos_laptop.
+
+endif # CHROMEOS_PLATFORMS
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
new file mode 100644 (file)
index 0000000..015e919
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_CHROMEOS_LAPTOP)  += chromeos_laptop.o
index b51a7460cc49bc03b4c055e8f46bfe2fedf718ff..d9dcd37b5a521e86baf54702ff96f91657037aff 100644 (file)
@@ -79,17 +79,6 @@ config ASUS_LAPTOP
 
          If you have an ACPI-compatible ASUS laptop, say Y or M here.
 
-config CHROMEOS_LAPTOP
-       tristate "Chrome OS Laptop"
-       depends on I2C
-       depends on DMI
-       ---help---
-         This driver instantiates i2c and smbus devices such as
-         light sensors and touchpads.
-
-         If you have a supported Chromebook, choose Y or M here.
-         The module will be called chromeos_laptop.
-
 config DELL_LAPTOP
        tristate "Dell Laptop Extras"
        depends on X86
index 5dbe193243510a94db296ba690ded6fa1af768e5..f0e6aa407ffb9ee8786e7aa71f5c76ed00ec6d81 100644 (file)
@@ -50,7 +50,6 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON)  += intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)   += intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)      += samsung-q10.o
 obj-$(CONFIG_APPLE_GMUX)       += apple-gmux.o
-obj-$(CONFIG_CHROMEOS_LAPTOP)  += chromeos_laptop.o
 obj-$(CONFIG_INTEL_RST)                += intel-rst.o
 obj-$(CONFIG_INTEL_SMARTCONNECT)       += intel-smartconnect.o
 
index 0e9c169b42f82a782b1166b2c05880ad4e1ad0da..594323a926cf0b8c62c4accfd88d297fe0caa567 100644 (file)
@@ -1494,10 +1494,9 @@ static int asus_input_init(struct asus_laptop *asus)
        int error;
 
        input = input_allocate_device();
-       if (!input) {
-               pr_warn("Unable to allocate input device\n");
+       if (!input)
                return -ENOMEM;
-       }
+
        input->name = "Asus Laptop extra buttons";
        input->phys = ASUS_LAPTOP_FILE "/input0";
        input->id.bustype = BUS_HOST;
index bb77e18b3dd4d5a8ce882f883dddbd98a28e037f..c608b1d33f4a60893a3bdc87b52773f872259f6d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/dmi.h>
 #include <linux/io.h>
+#include <linux/rfkill.h>
 #include <linux/power_supply.h>
 #include <linux/acpi.h>
 #include <linux/mm.h>
@@ -89,6 +90,13 @@ static struct platform_driver platform_driver = {
 
 static struct platform_device *platform_device;
 static struct backlight_device *dell_backlight_device;
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bluetooth_rfkill;
+static struct rfkill *wwan_rfkill;
+static bool force_rfkill;
+
+module_param(force_rfkill, bool, 0444);
+MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");
 
 static const struct dmi_system_id dell_device_table[] __initconst = {
        {
@@ -355,6 +363,108 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
        return buffer;
 }
 
+/* Derived from information in DellWirelessCtl.cpp:
+   Class 17, select 11 is radio control. It returns an array of 32-bit values.
+
+   Input byte 0 = 0: Wireless information
+
+   result[0]: return code
+   result[1]:
+     Bit 0:      Hardware switch supported
+     Bit 1:      Wifi locator supported
+     Bit 2:      Wifi is supported
+     Bit 3:      Bluetooth is supported
+     Bit 4:      WWAN is supported
+     Bit 5:      Wireless keyboard supported
+     Bits 6-7:   Reserved
+     Bit 8:      Wifi is installed
+     Bit 9:      Bluetooth is installed
+     Bit 10:     WWAN is installed
+     Bits 11-15: Reserved
+     Bit 16:     Hardware switch is on
+     Bit 17:     Wifi is blocked
+     Bit 18:     Bluetooth is blocked
+     Bit 19:     WWAN is blocked
+     Bits 20-31: Reserved
+   result[2]: NVRAM size in bytes
+   result[3]: NVRAM format version number
+
+   Input byte 0 = 2: Wireless switch configuration
+   result[0]: return code
+   result[1]:
+     Bit 0:      Wifi controlled by switch
+     Bit 1:      Bluetooth controlled by switch
+     Bit 2:      WWAN controlled by switch
+     Bits 3-6:   Reserved
+     Bit 7:      Wireless switch config locked
+     Bit 8:      Wifi locator enabled
+     Bits 9-14:  Reserved
+     Bit 15:     Wifi locator setting locked
+     Bits 16-31: Reserved
+*/
+
+static int dell_rfkill_set(void *data, bool blocked)
+{
+       int disable = blocked ? 1 : 0;
+       unsigned long radio = (unsigned long)data;
+       int hwswitch_bit = (unsigned long)data - 1;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+
+       /* If the hardware switch controls this radio, and the hardware
+          switch is disabled, always disable the radio */
+       if ((hwswitch_state & BIT(hwswitch_bit)) &&
+           !(buffer->output[1] & BIT(16)))
+               disable = 1;
+
+       buffer->input[0] = (1 | (radio<<8) | (disable << 16));
+       dell_send_request(buffer, 17, 11);
+
+       release_buffer();
+       return 0;
+}
+
+/* Must be called with the buffer held */
+static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
+                                       int status)
+{
+       if (status & BIT(0)) {
+               /* Has hw-switch, sync sw_state to BIOS */
+               int block = rfkill_blocked(rfkill);
+               buffer->input[0] = (1 | (radio << 8) | (block << 16));
+               dell_send_request(buffer, 17, 11);
+       } else {
+               /* No hw-switch, sync BIOS state to sw_state */
+               rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
+       }
+}
+
+static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
+                                       int status)
+{
+       if (hwswitch_state & (BIT(radio - 1)))
+               rfkill_set_hw_state(rfkill, !(status & BIT(16)));
+}
+
+static void dell_rfkill_query(struct rfkill *rfkill, void *data)
+{
+       int status;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+
+       dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status);
+
+       release_buffer();
+}
+
+static const struct rfkill_ops dell_rfkill_ops = {
+       .set_block = dell_rfkill_set,
+       .query = dell_rfkill_query,
+};
+
 static struct dentry *dell_laptop_dir;
 
 static int dell_debugfs_show(struct seq_file *s, void *data)
@@ -424,6 +534,136 @@ static const struct file_operations dell_debugfs_fops = {
        .release = single_release,
 };
 
+static void dell_update_rfkill(struct work_struct *ignored)
+{
+       int status;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+
+       if (wifi_rfkill) {
+               dell_rfkill_update_hw_state(wifi_rfkill, 1, status);
+               dell_rfkill_update_sw_state(wifi_rfkill, 1, status);
+       }
+       if (bluetooth_rfkill) {
+               dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status);
+               dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status);
+       }
+       if (wwan_rfkill) {
+               dell_rfkill_update_hw_state(wwan_rfkill, 3, status);
+               dell_rfkill_update_sw_state(wwan_rfkill, 3, status);
+       }
+
+       release_buffer();
+}
+static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
+
+
+static int __init dell_setup_rfkill(void)
+{
+       int status;
+       int ret;
+       const char *product;
+
+       /*
+        * rfkill causes trouble on various non Latitudes, according to Dell
+        * actually testing the rfkill functionality is only done on Latitudes.
+        */
+       product = dmi_get_system_info(DMI_PRODUCT_NAME);
+       if (!force_rfkill && (!product || strncmp(product, "Latitude", 8)))
+               return 0;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+       buffer->input[0] = 0x2;
+       dell_send_request(buffer, 17, 11);
+       hwswitch_state = buffer->output[1];
+       release_buffer();
+
+       if (!(status & BIT(0))) {
+               if (force_rfkill) {
+                       /* No hwsitch, clear all hw-controlled bits */
+                       hwswitch_state &= ~7;
+               } else {
+                       /* rfkill is only tested on laptops with a hwswitch */
+                       return 0;
+               }
+       }
+
+       if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
+               wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
+                                          RFKILL_TYPE_WLAN,
+                                          &dell_rfkill_ops, (void *) 1);
+               if (!wifi_rfkill) {
+                       ret = -ENOMEM;
+                       goto err_wifi;
+               }
+               ret = rfkill_register(wifi_rfkill);
+               if (ret)
+                       goto err_wifi;
+       }
+
+       if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
+               bluetooth_rfkill = rfkill_alloc("dell-bluetooth",
+                                               &platform_device->dev,
+                                               RFKILL_TYPE_BLUETOOTH,
+                                               &dell_rfkill_ops, (void *) 2);
+               if (!bluetooth_rfkill) {
+                       ret = -ENOMEM;
+                       goto err_bluetooth;
+               }
+               ret = rfkill_register(bluetooth_rfkill);
+               if (ret)
+                       goto err_bluetooth;
+       }
+
+       if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
+               wwan_rfkill = rfkill_alloc("dell-wwan",
+                                          &platform_device->dev,
+                                          RFKILL_TYPE_WWAN,
+                                          &dell_rfkill_ops, (void *) 3);
+               if (!wwan_rfkill) {
+                       ret = -ENOMEM;
+                       goto err_wwan;
+               }
+               ret = rfkill_register(wwan_rfkill);
+               if (ret)
+                       goto err_wwan;
+       }
+
+       return 0;
+err_wwan:
+       rfkill_destroy(wwan_rfkill);
+       if (bluetooth_rfkill)
+               rfkill_unregister(bluetooth_rfkill);
+err_bluetooth:
+       rfkill_destroy(bluetooth_rfkill);
+       if (wifi_rfkill)
+               rfkill_unregister(wifi_rfkill);
+err_wifi:
+       rfkill_destroy(wifi_rfkill);
+
+       return ret;
+}
+
+static void dell_cleanup_rfkill(void)
+{
+       if (wifi_rfkill) {
+               rfkill_unregister(wifi_rfkill);
+               rfkill_destroy(wifi_rfkill);
+       }
+       if (bluetooth_rfkill) {
+               rfkill_unregister(bluetooth_rfkill);
+               rfkill_destroy(bluetooth_rfkill);
+       }
+       if (wwan_rfkill) {
+               rfkill_unregister(wwan_rfkill);
+               rfkill_destroy(wwan_rfkill);
+       }
+}
+
 static int dell_send_intensity(struct backlight_device *bd)
 {
        int ret = 0;
@@ -515,6 +755,30 @@ static void touchpad_led_exit(void)
        led_classdev_unregister(&touchpad_led);
 }
 
+static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
+                             struct serio *port)
+{
+       static bool extended;
+
+       if (str & 0x20)
+               return false;
+
+       if (unlikely(data == 0xe0)) {
+               extended = true;
+               return false;
+       } else if (unlikely(extended)) {
+               switch (data) {
+               case 0x8:
+                       schedule_delayed_work(&dell_rfkill_work,
+                                             round_jiffies_relative(HZ / 4));
+                       break;
+               }
+               extended = false;
+       }
+
+       return false;
+}
+
 static int __init dell_init(void)
 {
        int max_intensity = 0;
@@ -557,10 +821,26 @@ static int __init dell_init(void)
        }
        buffer = page_address(bufferpage);
 
+       ret = dell_setup_rfkill();
+
+       if (ret) {
+               pr_warn("Unable to setup rfkill\n");
+               goto fail_rfkill;
+       }
+
+       ret = i8042_install_filter(dell_laptop_i8042_filter);
+       if (ret) {
+               pr_warn("Unable to install key filter\n");
+               goto fail_filter;
+       }
+
        if (quirks && quirks->touchpad_led)
                touchpad_led_init(&platform_device->dev);
 
        dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
+       if (dell_laptop_dir != NULL)
+               debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
+                                   &dell_debugfs_fops);
 
 #ifdef CONFIG_ACPI
        /* In the event of an ACPI backlight being available, don't
@@ -603,6 +883,11 @@ static int __init dell_init(void)
        return 0;
 
 fail_backlight:
+       i8042_remove_filter(dell_laptop_i8042_filter);
+       cancel_delayed_work_sync(&dell_rfkill_work);
+fail_filter:
+       dell_cleanup_rfkill();
+fail_rfkill:
        free_page((unsigned long)bufferpage);
 fail_buffer:
        platform_device_del(platform_device);
@@ -620,7 +905,10 @@ static void __exit dell_exit(void)
        debugfs_remove_recursive(dell_laptop_dir);
        if (quirks && quirks->touchpad_led)
                touchpad_led_exit();
+       i8042_remove_filter(dell_laptop_i8042_filter);
+       cancel_delayed_work_sync(&dell_rfkill_work);
        backlight_device_unregister(dell_backlight_device);
+       dell_cleanup_rfkill();
        if (platform_device) {
                platform_device_unregister(platform_device);
                platform_driver_unregister(&platform_driver);
index fa9a2171cc134b733c837f89a4f1b80aeb0989ea..60e0900bc117995e6373bfb5bedfcc1c8aac2aed 100644 (file)
@@ -130,7 +130,8 @@ static const u16 bios_to_linux_keycode[256] __initconst = {
        KEY_BRIGHTNESSUP,       KEY_UNKNOWN,    KEY_KBDILLUMTOGGLE,
        KEY_UNKNOWN,    KEY_SWITCHVIDEOMODE,    KEY_UNKNOWN, KEY_UNKNOWN,
        KEY_SWITCHVIDEOMODE,    KEY_UNKNOWN,    KEY_UNKNOWN, KEY_PROG2,
-       KEY_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       KEY_UNKNOWN,    KEY_UNKNOWN,    KEY_UNKNOWN,    KEY_UNKNOWN,
+       KEY_UNKNOWN,    KEY_UNKNOWN,    KEY_UNKNOWN,    KEY_MICMUTE,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -139,8 +140,8 @@ static const u16 bios_to_linux_keycode[256] __initconst = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       KEY_PROG3
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PROG3
 };
 
 static struct input_dev *dell_wmi_input_dev;
index aefcc32e563479d2b22404fdd75ceb7072423d16..dec68e7a99c79482f5f7cf4eb78b98bd0e2cd58d 100644 (file)
@@ -1203,10 +1203,8 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
        int error;
 
        input = input_allocate_device();
-       if (!input) {
-               pr_info("Unable to allocate input device\n");
+       if (!input)
                return -ENOMEM;
-       }
 
        input->name = "Asus EeePC extra buttons";
        input->phys = EEEPC_LAPTOP_FILE "/input0";
index 1c86fa0857c8eb73dfb64ec90ee9e7f7e50404c3..8ba8956b5a48f7f1fccc37df42cdaf4772892209 100644 (file)
@@ -54,6 +54,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
 #define HPWMI_HOTKEY_QUERY 0xc
+#define HPWMI_FEATURE_QUERY 0xd
 #define HPWMI_WIRELESS2_QUERY 0x1b
 #define HPWMI_POSTCODEERROR_QUERY 0x2a
 
@@ -292,6 +293,17 @@ static int hp_wmi_tablet_state(void)
        return (state & 0x4) ? 1 : 0;
 }
 
+static int hp_wmi_bios_2009_later(void)
+{
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state,
+                                      sizeof(state), sizeof(state));
+       if (ret)
+               return ret;
+
+       return (state & 0x10) ? 1 : 0;
+}
+
 static int hp_wmi_set_block(void *data, bool blocked)
 {
        enum hp_wmi_radio r = (enum hp_wmi_radio) data;
@@ -871,7 +883,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
        gps_rfkill = NULL;
        rfkill2_count = 0;
 
-       if (hp_wmi_rfkill_setup(device))
+       if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device))
                hp_wmi_rfkill2_setup(device);
 
        err = device_create_file(&device->dev, &dev_attr_display);
index 6788acc22ab97f01b410240eef0a5b2082c98550..19ec95147f6925d1de52e99886f7efc6a10dff7a 100644 (file)
@@ -570,10 +570,8 @@ static int ideapad_input_init(struct ideapad_private *priv)
        int error;
 
        inputdev = input_allocate_device();
-       if (!inputdev) {
-               pr_info("Unable to allocate input device\n");
+       if (!inputdev)
                return -ENOMEM;
-       }
 
        inputdev->name = "Ideapad extra buttons";
        inputdev->phys = "ideapad/input0";
index 6b18aba82cfae450bde3cad8fd2b2d01f20b3d03..8d6775266d66263bac3bdd45d7a5f580e598731e 100644 (file)
@@ -66,10 +66,8 @@ static int mfld_pb_probe(struct platform_device *pdev)
                return -EINVAL;
 
        input = input_allocate_device();
-       if (!input) {
-               dev_err(&pdev->dev, "Input device allocation error\n");
+       if (!input)
                return -ENOMEM;
-       }
 
        input->name = pdev->name;
        input->phys = "power-button/input0";
index d654f831410de9621df488aadbca2d6c6d174721..60ea476a91305c8f357f1950064cee54e92f0f29 100644 (file)
  *    message handler is called within firmware.
  */
 
-#define IPC_BASE_ADDR     0xFF11C000   /* IPC1 base register address */
-#define IPC_MAX_ADDR      0x100                /* Maximum IPC regisers */
 #define IPC_WWBUF_SIZE    20           /* IPC Write buffer Size */
 #define IPC_RWBUF_SIZE    20           /* IPC Read buffer Size */
-#define IPC_I2C_BASE      0xFF12B000   /* I2C control register base address */
-#define IPC_I2C_MAX_ADDR  0x10         /* Maximum I2C regisers */
+#define IPC_IOC                  0x100         /* IPC command register IOC bit */
+
+enum {
+       SCU_IPC_LINCROFT,
+       SCU_IPC_PENWELL,
+       SCU_IPC_CLOVERVIEW,
+       SCU_IPC_TANGIER,
+};
+
+/* intel scu ipc driver data*/
+struct intel_scu_ipc_pdata_t {
+       u32 ipc_base;
+       u32 i2c_base;
+       u32 ipc_len;
+       u32 i2c_len;
+       u8 irq_mode;
+};
+
+static struct intel_scu_ipc_pdata_t intel_scu_ipc_pdata[] = {
+       [SCU_IPC_LINCROFT] = {
+               .ipc_base = 0xff11c000,
+               .i2c_base = 0xff12b000,
+               .ipc_len = 0x100,
+               .i2c_len = 0x10,
+               .irq_mode = 0,
+       },
+       [SCU_IPC_PENWELL] = {
+               .ipc_base = 0xff11c000,
+               .i2c_base = 0xff12b000,
+               .ipc_len = 0x100,
+               .i2c_len = 0x10,
+               .irq_mode = 1,
+       },
+       [SCU_IPC_CLOVERVIEW] = {
+               .ipc_base = 0xff11c000,
+               .i2c_base = 0xff12b000,
+               .ipc_len = 0x100,
+               .i2c_len = 0x10,
+               .irq_mode = 1,
+       },
+       [SCU_IPC_TANGIER] = {
+               .ipc_base = 0xff009000,
+               .i2c_base  = 0xff00d000,
+               .ipc_len  = 0x100,
+               .i2c_len = 0x10,
+               .irq_mode = 0,
+       },
+};
 
 static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id);
 static void ipc_remove(struct pci_dev *pdev);
@@ -72,6 +116,8 @@ struct intel_scu_ipc_dev {
        struct pci_dev *pdev;
        void __iomem *ipc_base;
        void __iomem *i2c_base;
+       struct completion cmd_complete;
+       u8 irq_mode;
 };
 
 static struct intel_scu_ipc_dev  ipcdev; /* Only one for now */
@@ -98,6 +144,10 @@ static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
  */
 static inline void ipc_command(u32 cmd) /* Send ipc command */
 {
+       if (ipcdev.irq_mode) {
+               reinit_completion(&ipcdev.cmd_complete);
+               writel(cmd | IPC_IOC, ipcdev.ipc_base);
+       }
        writel(cmd, ipcdev.ipc_base);
 }
 
@@ -156,6 +206,30 @@ static inline int busy_loop(void) /* Wait till scu status is busy */
        return 0;
 }
 
+/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
+static inline int ipc_wait_for_interrupt(void)
+{
+       int status;
+
+       if (!wait_for_completion_timeout(&ipcdev.cmd_complete, 3 * HZ)) {
+               struct device *dev = &ipcdev.pdev->dev;
+               dev_err(dev, "IPC timed out\n");
+               return -ETIMEDOUT;
+       }
+
+       status = ipc_read_status();
+
+       if ((status >> 1) & 1)
+               return -EIO;
+
+       return 0;
+}
+
+int intel_scu_ipc_check_status(void)
+{
+       return ipcdev.irq_mode ? ipc_wait_for_interrupt() : busy_loop();
+}
+
 /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */
 static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
 {
@@ -196,8 +270,8 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
                ipc_command(4 << 16 |  id << 12 | 0 << 8 | op);
        }
 
-       err = busy_loop();
-       if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */
+       err = intel_scu_ipc_check_status();
+       if (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */
                /* Workaround: values are read as 0 without memcpy_fromio */
                memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16);
                for (nc = 0; nc < count; nc++)
@@ -391,7 +465,7 @@ int intel_scu_ipc_simple_command(int cmd, int sub)
                return -ENODEV;
        }
        ipc_command(sub << 12 | cmd);
-       err = busy_loop();
+       err = intel_scu_ipc_check_status();
        mutex_unlock(&ipclock);
        return err;
 }
@@ -425,10 +499,12 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
                ipc_data_writel(*in++, 4 * i);
 
        ipc_command((inlen << 16) | (sub << 12) | cmd);
-       err = busy_loop();
+       err = intel_scu_ipc_check_status();
 
-       for (i = 0; i < outlen; i++)
-               *out++ = ipc_data_readl(4 * i);
+       if (!err) {
+               for (i = 0; i < outlen; i++)
+                       *out++ = ipc_data_readl(4 * i);
+       }
 
        mutex_unlock(&ipclock);
        return err;
@@ -491,6 +567,9 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
  */
 static irqreturn_t ioc(int irq, void *dev_id)
 {
+       if (ipcdev.irq_mode)
+               complete(&ipcdev.cmd_complete);
+
        return IRQ_HANDLED;
 }
 
@@ -504,13 +583,18 @@ static irqreturn_t ioc(int irq, void *dev_id)
  */
 static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       int err;
+       int err, pid;
+       struct intel_scu_ipc_pdata_t *pdata;
        resource_size_t pci_resource;
 
        if (ipcdev.pdev)                /* We support only one SCU */
                return -EBUSY;
 
+       pid = id->driver_data;
+       pdata = &intel_scu_ipc_pdata[pid];
+
        ipcdev.pdev = pci_dev_get(dev);
+       ipcdev.irq_mode = pdata->irq_mode;
 
        err = pci_enable_device(dev);
        if (err)
@@ -524,14 +608,16 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (!pci_resource)
                return -ENOMEM;
 
+       init_completion(&ipcdev.cmd_complete);
+
        if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev))
                return -EBUSY;
 
-       ipcdev.ipc_base = ioremap_nocache(IPC_BASE_ADDR, IPC_MAX_ADDR);
+       ipcdev.ipc_base = ioremap_nocache(pdata->ipc_base, pdata->ipc_len);
        if (!ipcdev.ipc_base)
                return -ENOMEM;
 
-       ipcdev.i2c_base = ioremap_nocache(IPC_I2C_BASE, IPC_I2C_MAX_ADDR);
+       ipcdev.i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
        if (!ipcdev.i2c_base) {
                iounmap(ipcdev.ipc_base);
                return -ENOMEM;
@@ -564,7 +650,10 @@ static void ipc_remove(struct pci_dev *pdev)
 }
 
 static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
+       {PCI_VDEVICE(INTEL, 0x082a), SCU_IPC_LINCROFT},
+       {PCI_VDEVICE(INTEL, 0x080e), SCU_IPC_PENWELL},
+       {PCI_VDEVICE(INTEL, 0x08ea), SCU_IPC_CLOVERVIEW},
+       {PCI_VDEVICE(INTEL, 0x11a0), SCU_IPC_TANGIER},
        { 0,}
 };
 MODULE_DEVICE_TABLE(pci, pci_ids);
index 10d12b221601ddae853fe3b0e8554d99d0c5ef06..3008fd20572e96a2d93823c4d15db27592fed2e2 100644 (file)
@@ -490,11 +490,8 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc)
        int error;
 
        input_dev = input_allocate_device();
-       if (!input_dev) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Couldn't allocate input device for hotkey"));
+       if (!input_dev)
                return -ENOMEM;
-       }
 
        input_dev->name = ACPI_PCC_DRIVER_NAME;
        input_dev->phys = ACPI_PCC_INPUT_PHYS;
index 47caab0ea7a14faa1051b35eafe1ff8e53703ee0..fb233ae7bb0e3e8374691818cfe61125e66371a5 100644 (file)
@@ -140,12 +140,12 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
                 "on the model (default: no change from current value)");
 
 #ifdef CONFIG_PM_SLEEP
-static void sony_nc_kbd_backlight_resume(void);
 static void sony_nc_thermal_resume(void);
 #endif
 static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
                unsigned int handle);
-static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd);
+static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd,
+               unsigned int handle);
 
 static int sony_nc_battery_care_setup(struct platform_device *pd,
                unsigned int handle);
@@ -304,8 +304,8 @@ static int sony_laptop_input_keycode_map[] = {
        KEY_FN_F10,     /* 14 SONYPI_EVENT_FNKEY_F10 */
        KEY_FN_F11,     /* 15 SONYPI_EVENT_FNKEY_F11 */
        KEY_FN_F12,     /* 16 SONYPI_EVENT_FNKEY_F12 */
-       KEY_FN_F1,      /* 17 SONYPI_EVENT_FNKEY_1 */
-       KEY_FN_F2,      /* 18 SONYPI_EVENT_FNKEY_2 */
+       KEY_FN_1,       /* 17 SONYPI_EVENT_FNKEY_1 */
+       KEY_FN_2,       /* 18 SONYPI_EVENT_FNKEY_2 */
        KEY_FN_D,       /* 19 SONYPI_EVENT_FNKEY_D */
        KEY_FN_E,       /* 20 SONYPI_EVENT_FNKEY_E */
        KEY_FN_F,       /* 21 SONYPI_EVENT_FNKEY_F */
@@ -1444,7 +1444,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)
                case 0x014b:
                case 0x014c:
                case 0x0163:
-                       sony_nc_kbd_backlight_cleanup(pd);
+                       sony_nc_kbd_backlight_cleanup(pd, handle);
                        break;
                default:
                        continue;
@@ -1486,13 +1486,6 @@ static void sony_nc_function_resume(void)
                case 0x0135:
                        sony_nc_rfkill_update();
                        break;
-               case 0x0137:
-               case 0x0143:
-               case 0x014b:
-               case 0x014c:
-               case 0x0163:
-                       sony_nc_kbd_backlight_resume();
-                       break;
                default:
                        continue;
                }
@@ -1822,6 +1815,12 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
        int result;
        int ret = 0;
 
+       if (kbdbl_ctl) {
+               pr_warn("handle 0x%.4x: keyboard backlight setup already done for 0x%.4x\n",
+                               handle, kbdbl_ctl->handle);
+               return -EBUSY;
+       }
+
        /* verify the kbd backlight presence, these handles are not used for
         * keyboard backlight only
         */
@@ -1881,9 +1880,10 @@ outkzalloc:
        return ret;
 }
 
-static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
+static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd,
+               unsigned int handle)
 {
-       if (kbdbl_ctl) {
+       if (kbdbl_ctl && handle == kbdbl_ctl->handle) {
                device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
                device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
                kfree(kbdbl_ctl);
@@ -1891,25 +1891,6 @@ static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
        }
 }
 
-#ifdef CONFIG_PM_SLEEP
-static void sony_nc_kbd_backlight_resume(void)
-{
-       int ignore = 0;
-
-       if (!kbdbl_ctl)
-               return;
-
-       if (kbdbl_ctl->mode == 0)
-               sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base,
-                               &ignore);
-
-       if (kbdbl_ctl->timeout != 0)
-               sony_call_snc_handle(kbdbl_ctl->handle,
-                               (kbdbl_ctl->base + 0x200) |
-                               (kbdbl_ctl->timeout << 0x10), &ignore);
-}
-#endif
-
 struct battery_care_control {
        struct device_attribute attrs[2];
        unsigned int handle;
index 05e046aa5e314be112b0e165f93fd82c6ab16fe5..58b0274d24cc2968e35e6a9cdad75b1533c35e2d 100644 (file)
@@ -6438,7 +6438,12 @@ static struct ibm_struct brightness_driver_data = {
 #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
 #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
 
-static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */
+#if SNDRV_CARDS <= 32
+#define DEFAULT_ALSA_IDX               ~((1 << (SNDRV_CARDS - 3)) - 1)
+#else
+#define DEFAULT_ALSA_IDX               ~((1 << (32 - 3)) - 1)
+#endif
+static int alsa_index = DEFAULT_ALSA_IDX; /* last three slots */
 static char *alsa_id = "ThinkPadEC";
 static bool alsa_enable = SNDRV_DEFAULT_ENABLE1;
 
@@ -9163,7 +9168,6 @@ static int __init thinkpad_acpi_module_init(void)
        mutex_init(&tpacpi_inputdev_send_mutex);
        tpacpi_inputdev = input_allocate_device();
        if (!tpacpi_inputdev) {
-               pr_err("unable to allocate input device\n");
                thinkpad_acpi_module_exit();
                return -ENOMEM;
        } else {
index 67897c8740ba58ea3c93cf54b0a2a3e74a1e3a84..e597de05e6c27badfe97ea533ddb2f7a6c41d3b5 100644 (file)
@@ -97,10 +97,8 @@ static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
        int error;
 
        input = input_allocate_device();
-       if (!input) {
-               pr_err("Unable to allocate input device\n");
+       if (!input)
                return -ENOMEM;
-       }
 
        input->name = "Topstar Laptop extra buttons";
        input->phys = "topstar/input0";
index 0cfadb65f7c639597abce1d1bcb81ba3a04ff1d3..7fce391818d30a183962b7888a8bfd275b10423c 100644 (file)
@@ -975,10 +975,8 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        u32 hci_result;
 
        dev->hotkey_dev = input_allocate_device();
-       if (!dev->hotkey_dev) {
-               pr_info("Unable to register input device\n");
+       if (!dev->hotkey_dev)
                return -ENOMEM;
-       }
 
        dev->hotkey_dev->name = "Toshiba input device";
        dev->hotkey_dev->phys = "toshiba_acpi/input0";
index 62e8c221d01ea10a5f105a0a44b2d2d8277d7878..c2e7b2657aeb31bf5ab50a4f8a8821e2ad53f696 100644 (file)
@@ -672,8 +672,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
        struct wmi_block *wblock;
 
        wblock = dev_get_drvdata(dev);
-       if (!wblock)
-               return -ENOMEM;
+       if (!wblock) {
+               strcat(buf, "\n");
+               return strlen(buf);
+       }
 
        wmi_gtoa(wblock->gblock.guid, guid_string);
 
index 6936e0acedcd6bfce4b8166bb4b8da6a922e0f47..f748cc8cbb031cf3ad3fd943688fc6172a452bd2 100644 (file)
@@ -197,6 +197,11 @@ static int pnp_bus_freeze(struct device *dev)
        return __pnp_bus_suspend(dev, PMSG_FREEZE);
 }
 
+static int pnp_bus_poweroff(struct device *dev)
+{
+       return __pnp_bus_suspend(dev, PMSG_HIBERNATE);
+}
+
 static int pnp_bus_resume(struct device *dev)
 {
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
@@ -234,9 +239,14 @@ static int pnp_bus_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
+       /* Suspend callbacks */
        .suspend = pnp_bus_suspend,
-       .freeze = pnp_bus_freeze,
        .resume = pnp_bus_resume,
+       /* Hibernate callbacks */
+       .freeze = pnp_bus_freeze,
+       .thaw = pnp_bus_resume,
+       .poweroff = pnp_bus_poweroff,
+       .restore = pnp_bus_resume,
 };
 
 struct bus_type pnp_bus_type = {
index 2a786c504460f5be0246c363fab622223ebd990e..3c6768378a94600bc487c61bc9d3fffcbf581750 100644 (file)
@@ -833,6 +833,11 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
        return 0;
 }
 
+static const struct x86_cpu_id energy_unit_quirk_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
+       {}
+};
+
 static int rapl_check_unit(struct rapl_package *rp, int cpu)
 {
        u64 msr_val;
@@ -853,8 +858,11 @@ static int rapl_check_unit(struct rapl_package *rp, int cpu)
         * time unit: 1/time_unit_divisor Seconds
         */
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit_divisor = 1 << value;
-
+       /* some CPUs have different way to calculate energy unit */
+       if (x86_match_cpu(energy_unit_quirk_ids))
+               rp->energy_unit_divisor = 1000000 / (1 << value);
+       else
+               rp->energy_unit_divisor = 1 << value;
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit_divisor = 1 << value;
@@ -941,6 +949,7 @@ static void package_power_limit_irq_restore(int package_id)
 static const struct x86_cpu_id rapl_ids[] = {
        { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
        { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
        { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
        { X86_VENDOR_INTEL, 6, 0x45},/* HSW */
        /* TODO: Add more CPU IDs after testing */
index 8d0fe431dbdd54ef0c175c06dbbc4b5d76f6d9cd..84419af16f777095687eddb59d74c7ca6762e3bb 100644 (file)
@@ -377,9 +377,14 @@ static void create_power_zone_common_attributes(
        if (power_zone->ops->get_max_energy_range_uj)
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_max_energy_range_uj.attr;
-       if (power_zone->ops->get_energy_uj)
+       if (power_zone->ops->get_energy_uj) {
+               if (power_zone->ops->reset_energy_uj)
+                       dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
+               else
+                       dev_attr_energy_uj.attr.mode = S_IRUGO;
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_energy_uj.attr;
+       }
        if (power_zone->ops->get_power_uw)
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_power_uw.attr;
index 724706a97dc40c5cf7e21d89f7c58bc2385f6226..fd3154d86901fcf3865139d42bc997d72b4ff608 100644 (file)
@@ -174,6 +174,33 @@ static const struct regulator_desc arizona_micsupp = {
        .owner = THIS_MODULE,
 };
 
+static const struct regulator_linear_range arizona_micsupp_ext_ranges[] = {
+       REGULATOR_LINEAR_RANGE(900000,  0,    0x14, 25000),
+       REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000),
+};
+
+static const struct regulator_desc arizona_micsupp_ext = {
+       .name = "MICVDD",
+       .supply_name = "CPVDD",
+       .type = REGULATOR_VOLTAGE,
+       .n_voltages = 40,
+       .ops = &arizona_micsupp_ops,
+
+       .vsel_reg = ARIZONA_LDO2_CONTROL_1,
+       .vsel_mask = ARIZONA_LDO2_VSEL_MASK,
+       .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
+       .enable_mask = ARIZONA_CPMIC_ENA,
+       .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
+       .bypass_mask = ARIZONA_CPMIC_BYPASS,
+
+       .linear_ranges = arizona_micsupp_ext_ranges,
+       .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges),
+
+       .enable_time = 3000,
+
+       .owner = THIS_MODULE,
+};
+
 static const struct regulator_init_data arizona_micsupp_default = {
        .constraints = {
                .valid_ops_mask = REGULATOR_CHANGE_STATUS |
@@ -186,9 +213,22 @@ static const struct regulator_init_data arizona_micsupp_default = {
        .num_consumer_supplies = 1,
 };
 
+static const struct regulator_init_data arizona_micsupp_ext_default = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                               REGULATOR_CHANGE_VOLTAGE |
+                               REGULATOR_CHANGE_BYPASS,
+               .min_uV = 900000,
+               .max_uV = 3300000,
+       },
+
+       .num_consumer_supplies = 1,
+};
+
 static int arizona_micsupp_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       const struct regulator_desc *desc;
        struct regulator_config config = { };
        struct arizona_micsupp *micsupp;
        int ret;
@@ -207,7 +247,17 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
         * default init_data for it.  This will be overridden with
         * platform data if provided.
         */
-       micsupp->init_data = arizona_micsupp_default;
+       switch (arizona->type) {
+       case WM5110:
+               desc = &arizona_micsupp_ext;
+               micsupp->init_data = arizona_micsupp_ext_default;
+               break;
+       default:
+               desc = &arizona_micsupp;
+               micsupp->init_data = arizona_micsupp_default;
+               break;
+       }
+
        micsupp->init_data.consumer_supplies = &micsupp->supply;
        micsupp->supply.supply = "MICVDD";
        micsupp->supply.dev_name = dev_name(arizona->dev);
@@ -226,7 +276,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
                           ARIZONA_CPMIC_BYPASS, 0);
 
        micsupp->regulator = devm_regulator_register(&pdev->dev,
-                                                    &arizona_micsupp,
+                                                    desc,
                                                     &config);
        if (IS_ERR(micsupp->regulator)) {
                ret = PTR_ERR(micsupp->regulator);
index 5917fe3dc983dc5335d62e393fe079459817d439..b9f1d24c6812eb91d0cf55031c617888b914c560 100644 (file)
@@ -590,8 +590,8 @@ static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
        default:
                return -EINVAL;
        }
+       ret <<= ffs(mask) - 1;
        val = ret & mask;
-       val <<= ffs(mask) - 1;
        return as3722_update_bits(as3722, reg, mask, val);
 }
 
index 6382f0af353bc257e3ee6c3b545f75c0c1f2904e..d85f31385b24fe9b68ae45dfe0ece4be0ecc2ceb 100644 (file)
@@ -119,6 +119,11 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
                return "";
 }
 
+static bool have_full_constraints(void)
+{
+       return has_full_constraints || of_have_populated_dt();
+}
+
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
@@ -1340,7 +1345,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
         * Assume that a regulator is physically present and enabled
         * even if it isn't hooked up and just provide a dummy.
         */
-       if (has_full_constraints && allow_dummy) {
+       if (have_full_constraints() && allow_dummy) {
                pr_warn("%s supply %s not found, using dummy regulator\n",
                        devname, id);
 
@@ -2184,6 +2189,9 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector)
        struct regulator_ops    *ops = rdev->desc->ops;
        int                     ret;
 
+       if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
+               return rdev->desc->fixed_uV;
+
        if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
                return -EINVAL;
 
@@ -3624,7 +3632,7 @@ int regulator_suspend_finish(void)
                        if (error)
                                ret = error;
                } else {
-                       if (!has_full_constraints)
+                       if (!have_full_constraints())
                                goto unlock;
                        if (!ops->disable)
                                goto unlock;
@@ -3822,7 +3830,7 @@ static int __init regulator_init_complete(void)
                if (!enabled)
                        goto unlock;
 
-               if (has_full_constraints) {
+               if (have_full_constraints()) {
                        /* We log since this may kill the system if it
                         * goes wrong. */
                        rdev_info(rdev, "disabling\n");
index 04406a918c041b5773adcf9adf331eadf289caf4..234960dc96077389460632cdc832f0c6ea5e69e1 100644 (file)
@@ -139,6 +139,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
        struct property *prop;
        const char *regtype;
        int proplen, gpio, i;
+       int ret;
 
        config = devm_kzalloc(dev,
                        sizeof(struct gpio_regulator_config),
@@ -202,7 +203,11 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
        }
        config->nr_states = i;
 
-       of_property_read_string(np, "regulator-type", &regtype);
+       ret = of_property_read_string(np, "regulator-type", &regtype);
+       if (ret < 0) {
+               dev_err(dev, "Missing 'regulator-type' property\n");
+               return ERR_PTR(-EINVAL);
+       }
 
        if (!strncmp("voltage", regtype, 7))
                config->type = REGULATOR_VOLTAGE;
index ba67b2c4e2e7fe4da91fdd6afd269ab1233a284e..8b5e4c712a0190b0643c6ee40a8918582829d4fd 100644 (file)
@@ -38,7 +38,7 @@
 
 #define PFUZE100_DEVICEID      0x0
 #define PFUZE100_REVID         0x3
-#define PFUZE100_FABID         0x3
+#define PFUZE100_FABID         0x4
 
 #define PFUZE100_SW1ABVOL      0x20
 #define PFUZE100_SW1CVOL       0x2e
@@ -308,9 +308,15 @@ static int pfuze_identify(struct pfuze_chip *pfuze_chip)
        if (ret)
                return ret;
 
-       if (value & 0x0f) {
-               dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value);
-               return -ENODEV;
+       switch (value & 0x0f) {
+               /* Freescale misprogrammed 1-3% of parts prior to week 8 of 2013 as ID=8 */
+               case 0x8:
+                       dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8");
+               case 0x0:
+                       break;
+               default:
+                       dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value);
+                       return -ENODEV;
        }
 
        ret = regmap_read(pfuze_chip->regmap, PFUZE100_REVID, &value);
index 333677d68d0ee31f784e76906bc930b592fc7257..9e61922d82302372c08ab5499b676a4b51363248 100644 (file)
@@ -438,7 +438,7 @@ common_reg:
        platform_set_drvdata(pdev, s2mps11);
 
        config.dev = &pdev->dev;
-       config.regmap = iodev->regmap;
+       config.regmap = iodev->regmap_pmic;
        config.driver_data = s2mps11;
        for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
                if (!reg_np) {
index cbf91e25cf7ff2a632270caed53d05533fcf81db..aeb40aad0ae7775442f775403fdaea047bdd16d8 100644 (file)
@@ -925,7 +925,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
                config.dev = s5m8767->dev;
                config.init_data = pdata->regulators[i].initdata;
                config.driver_data = s5m8767;
-               config.regmap = iodev->regmap;
+               config.regmap = iodev->regmap_pmic;
                config.of_node = pdata->regulators[i].reg_node;
 
                rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
index c0da95e95702123d403bf58ed4b894a104eeb2ec..3281c90691c3e143fe14142c9234e3f0a60650e6 100644 (file)
@@ -220,6 +220,8 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        at91_alarm_year = tm.tm_year;
 
+       tm.tm_mon = alrm->time.tm_mon;
+       tm.tm_mday = alrm->time.tm_mday;
        tm.tm_hour = alrm->time.tm_hour;
        tm.tm_min = alrm->time.tm_min;
        tm.tm_sec = alrm->time.tm_sec;
index b7fd02bc0a1473a41f00bc233f845551085f5009..ae8119dc2846aac28c8f47019720bf93fd39803f 100644 (file)
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/rtc.h>
 
+/*
+ * Maximum number of retries for checking changes in UDR field
+ * of SEC_RTC_UDR_CON register (to limit possible endless loop).
+ *
+ * After writing to RTC registers (setting time or alarm) read the UDR field
+ * in SEC_RTC_UDR_CON register. UDR is auto-cleared when data have
+ * been transferred.
+ */
+#define UDR_READ_RETRY_CNT     5
+
 struct s5m_rtc_info {
        struct device *dev;
        struct sec_pmic_dev *s5m87xx;
-       struct regmap *rtc;
+       struct regmap *regmap;
        struct rtc_device *rtc_dev;
        int irq;
        int device_type;
@@ -84,12 +94,31 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
        }
 }
 
+/*
+ * Read RTC_UDR_CON register and wait till UDR field is cleared.
+ * This indicates that time/alarm update ended.
+ */
+static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
+{
+       int ret, retry = UDR_READ_RETRY_CNT;
+       unsigned int data;
+
+       do {
+               ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
+       } while (--retry && (data & RTC_UDR_MASK) && !ret);
+
+       if (!retry)
+               dev_err(info->dev, "waiting for UDR update, reached max number of retries\n");
+
+       return ret;
+}
+
 static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 {
        int ret;
        unsigned int data;
 
-       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
        if (ret < 0) {
                dev_err(info->dev, "failed to read update reg(%d)\n", ret);
                return ret;
@@ -98,15 +127,13 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
        data |= RTC_TIME_EN_MASK;
        data |= RTC_UDR_MASK;
 
-       ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data);
+       ret = regmap_write(info->regmap, SEC_RTC_UDR_CON, data);
        if (ret < 0) {
                dev_err(info->dev, "failed to write update reg(%d)\n", ret);
                return ret;
        }
 
-       do {
-               ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
-       } while ((data & RTC_UDR_MASK) && !ret);
+       ret = s5m8767_wait_for_udr_update(info);
 
        return ret;
 }
@@ -116,7 +143,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
        int ret;
        unsigned int data;
 
-       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to read update reg(%d)\n",
                        __func__, ret);
@@ -126,16 +153,14 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
        data &= ~RTC_TIME_EN_MASK;
        data |= RTC_UDR_MASK;
 
-       ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data);
+       ret = regmap_write(info->regmap, SEC_RTC_UDR_CON, data);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to write update reg(%d)\n",
                        __func__, ret);
                return ret;
        }
 
-       do {
-               ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
-       } while ((data & RTC_UDR_MASK) && !ret);
+       ret = s5m8767_wait_for_udr_update(info);
 
        return ret;
 }
@@ -178,7 +203,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
        u8 data[8];
        int ret;
 
-       ret = regmap_bulk_read(info->rtc, SEC_RTC_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_RTC_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -226,7 +251,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
                1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
                tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
 
-       ret = regmap_raw_write(info->rtc, SEC_RTC_SEC, data, 8);
+       ret = regmap_raw_write(info->regmap, SEC_RTC_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -242,20 +267,20 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        unsigned int val;
        int ret, i;
 
-       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
        switch (info->device_type) {
        case S5M8763X:
                s5m8763_data_to_tm(data, &alrm->time);
-               ret = regmap_read(info->rtc, SEC_ALARM0_CONF, &val);
+               ret = regmap_read(info->regmap, SEC_ALARM0_CONF, &val);
                if (ret < 0)
                        return ret;
 
                alrm->enabled = !!val;
 
-               ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val);
+               ret = regmap_read(info->regmap, SEC_RTC_STATUS, &val);
                if (ret < 0)
                        return ret;
 
@@ -278,7 +303,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                }
 
                alrm->pending = 0;
-               ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val);
+               ret = regmap_read(info->regmap, SEC_RTC_STATUS, &val);
                if (ret < 0)
                        return ret;
                break;
@@ -301,7 +326,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
        int ret, i;
        struct rtc_time tm;
 
-       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -312,14 +337,14 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
 
        switch (info->device_type) {
        case S5M8763X:
-               ret = regmap_write(info->rtc, SEC_ALARM0_CONF, 0);
+               ret = regmap_write(info->regmap, SEC_ALARM0_CONF, 0);
                break;
 
        case S5M8767X:
                for (i = 0; i < 7; i++)
                        data[i] &= ~ALARM_ENABLE_MASK;
 
-               ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+               ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8);
                if (ret < 0)
                        return ret;
 
@@ -341,7 +366,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
        u8 alarm0_conf;
        struct rtc_time tm;
 
-       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -353,7 +378,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
        switch (info->device_type) {
        case S5M8763X:
                alarm0_conf = 0x77;
-               ret = regmap_write(info->rtc, SEC_ALARM0_CONF, alarm0_conf);
+               ret = regmap_write(info->regmap, SEC_ALARM0_CONF, alarm0_conf);
                break;
 
        case S5M8767X:
@@ -368,7 +393,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
                if (data[RTC_YEAR1] & 0x7f)
                        data[RTC_YEAR1] |= ALARM_ENABLE_MASK;
 
-               ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+               ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8);
                if (ret < 0)
                        return ret;
                ret = s5m8767_rtc_set_alarm_reg(info);
@@ -410,7 +435,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        if (ret < 0)
                return ret;
 
-       ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -455,7 +480,7 @@ static const struct rtc_class_ops s5m_rtc_ops = {
 static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
 {
        int ret;
-       ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL,
+       ret = regmap_update_bits(info->regmap, SEC_WTSR_SMPL_CNTL,
                                 WTSR_ENABLE_MASK,
                                 enable ? WTSR_ENABLE_MASK : 0);
        if (ret < 0)
@@ -466,7 +491,7 @@ static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
 static void s5m_rtc_enable_smpl(struct s5m_rtc_info *info, bool enable)
 {
        int ret;
-       ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL,
+       ret = regmap_update_bits(info->regmap, SEC_WTSR_SMPL_CNTL,
                                 SMPL_ENABLE_MASK,
                                 enable ? SMPL_ENABLE_MASK : 0);
        if (ret < 0)
@@ -481,7 +506,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
        int ret;
        struct rtc_time tm;
 
-       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &tp_read);
+       ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &tp_read);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to read control reg(%d)\n",
                        __func__, ret);
@@ -493,7 +518,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
        data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
 
        info->rtc_24hr_mode = 1;
-       ret = regmap_raw_write(info->rtc, SEC_ALARM0_CONF, data, 2);
+       ret = regmap_raw_write(info->regmap, SEC_ALARM0_CONF, data, 2);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
                        __func__, ret);
@@ -515,7 +540,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
                ret = s5m_rtc_set_time(info->dev, &tm);
        }
 
-       ret = regmap_update_bits(info->rtc, SEC_RTC_UDR_CON,
+       ret = regmap_update_bits(info->regmap, SEC_RTC_UDR_CON,
                                 RTC_TCON_MASK, tp_read | RTC_TCON_MASK);
        if (ret < 0)
                dev_err(info->dev, "%s: fail to update TCON reg(%d)\n",
@@ -542,17 +567,19 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 
        info->dev = &pdev->dev;
        info->s5m87xx = s5m87xx;
-       info->rtc = s5m87xx->rtc;
+       info->regmap = s5m87xx->regmap_rtc;
        info->device_type = s5m87xx->device_type;
        info->wtsr_smpl = s5m87xx->wtsr_smpl;
 
        switch (pdata->device_type) {
        case S5M8763X:
-               info->irq = s5m87xx->irq_base + S5M8763_IRQ_ALARM0;
+               info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
+                               S5M8763_IRQ_ALARM0);
                break;
 
        case S5M8767X:
-               info->irq = s5m87xx->irq_base + S5M8767_IRQ_RTCA1;
+               info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
+                               S5M8767_IRQ_RTCA1);
                break;
 
        default:
@@ -596,7 +623,7 @@ static void s5m_rtc_shutdown(struct platform_device *pdev)
        if (info->wtsr_smpl) {
                for (i = 0; i < 3; i++) {
                        s5m_rtc_enable_wtsr(info, false);
-                       regmap_read(info->rtc, SEC_WTSR_SMPL_CNTL, &val);
+                       regmap_read(info->regmap, SEC_WTSR_SMPL_CNTL, &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",
@@ -612,6 +639,30 @@ static void s5m_rtc_shutdown(struct platform_device *pdev)
        s5m_rtc_enable_smpl(info, false);
 }
 
+static int s5m_rtc_resume(struct device *dev)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (device_may_wakeup(dev))
+               ret = disable_irq_wake(info->irq);
+
+       return ret;
+}
+
+static int s5m_rtc_suspend(struct device *dev)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (device_may_wakeup(dev))
+               ret = enable_irq_wake(info->irq);
+
+       return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
+
 static const struct platform_device_id s5m_rtc_id[] = {
        { "s5m-rtc", 0 },
 };
@@ -620,6 +671,7 @@ static struct platform_driver s5m_rtc_driver = {
        .driver         = {
                .name   = "s5m-rtc",
                .owner  = THIS_MODULE,
+               .pm     = &s5m_rtc_pm_ops,
        },
        .probe          = s5m_rtc_probe,
        .shutdown       = s5m_rtc_shutdown,
index cee7e2708a1fe35359eb81cc458d939e50ad1906..95e45782692fa7bb2a89e9ec566a6a035f736381 100644 (file)
@@ -3224,6 +3224,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
 
        fcx_multitrack = private->features.feature[40] & 0x20;
        data_size = blk_rq_bytes(req);
+       if (data_size % blksize)
+               return ERR_PTR(-EINVAL);
        /* tpm write request add CBC data on each track boundary */
        if (rq_data_dir(req) == WRITE)
                data_size += (last_trk - first_trk) * 4;
index f64921756ad610375134b3b59f13bbdb5d9906af..f224d59c4b6be35b8a5d827dde6cdc173953f3f5 100644 (file)
@@ -87,7 +87,6 @@ void dasd_gendisk_free(struct dasd_block *block)
 {
        if (block->gdp) {
                del_gendisk(block->gdp);
-               block->gdp->queue = NULL;
                block->gdp->private_data = NULL;
                put_disk(block->gdp);
                block->gdp = NULL;
index f7aa080e9b28db1d5b962de7b5380f60ae97cc10..1465e9563101f0a2cbc697a8f26edb2200368d5f 100644 (file)
@@ -35,7 +35,6 @@ struct read_info_sccb {
        u8      _reserved5[4096 - 112]; /* 112-4095 */
 } __packed __aligned(PAGE_SIZE);
 
-static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE);
 static __initdata struct read_info_sccb early_read_info_sccb;
 static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE);
 static unsigned long sclp_hsa_size;
@@ -113,7 +112,7 @@ static void __init sclp_facilities_detect(void)
 
 bool __init sclp_has_linemode(void)
 {
-       struct init_sccb *sccb = &early_event_mask_sccb;
+       struct init_sccb *sccb = (void *) &sccb_early;
 
        if (sccb->header.response_code != 0x20)
                return 0;
@@ -126,7 +125,7 @@ bool __init sclp_has_linemode(void)
 
 bool __init sclp_has_vt220(void)
 {
-       struct init_sccb *sccb = &early_event_mask_sccb;
+       struct init_sccb *sccb = (void *) &sccb_early;
 
        if (sccb->header.response_code != 0x20)
                return 0;
index 5e1e12c0cf4220796112d2d6dd9d9e102fdf537d..0a7325361d2958dceeae99da5959e518f8490985 100644 (file)
@@ -2025,7 +2025,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twa_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index c845bdbeb6c06f971923300e7f8e11182d18d84c..4de346017e9ff91b43aed80d48231ac60f23a4e3 100644 (file)
@@ -1600,7 +1600,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twl_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index b9276d10b25c2e277c05e1b6e48e196a11b38fa4..752624e6bc0022807c6265539cad6d8b42d1611f 100644 (file)
@@ -2279,7 +2279,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,  
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = tw_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index f0d432c139d0cecedf51295562c858d22a9f44f0..4921ed19a027f819b731271c4804be74d2426e5a 100644 (file)
@@ -1081,6 +1081,7 @@ static struct scsi_host_template aac_driver_template = {
 #endif
        .use_clustering                 = ENABLE_CLUSTERING,
        .emulated                       = 1,
+       .no_write_same                  = 1,
 };
 
 static void __aac_shutdown(struct aac_dev * aac)
index 97fd450aff09315194233e7a8ea1f06b566248ef..4f6a30b8e5f99bb3cba345bfec806cdc4972b9f3 100644 (file)
@@ -137,6 +137,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
        .cmd_per_lun            = ARCMSR_MAX_CMD_PERLUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = arcmsr_host_attrs,
+       .no_write_same          = 1,
 };
 static struct pci_device_id arcmsr_device_id_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
index 94d5d0102f7dcc4da5754591a828b47699cec644..42bcb970445a8a7212fafa1aa7285639d5c7d8a3 100644 (file)
@@ -296,6 +296,7 @@ wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
 struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
                                            u16 vf_id, wwn_t lpwwn);
 
+void bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, char *symname);
 void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
                            struct bfa_lport_info_s *port_info);
 void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
index 2f61a5af36581bce4db052d09d7024352063f0a4..f5e4e61a0fd7ba5bd461e0f79bd2f333317bf74a 100644 (file)
@@ -1097,6 +1097,17 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
        bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
 }
 
+void
+bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port,
+                               char *symname)
+{
+       strcpy(port->port_cfg.sym_name.symname, symname);
+
+       if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
+               bfa_fcs_lport_ns_util_send_rspn_id(
+                       BFA_FCS_GET_NS_FROM_PORT(port), NULL);
+}
+
 /*
  *  fcs_lport_api
  */
@@ -5140,9 +5151,6 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
        u8 *psymbl = &symbl[0];
        int len;
 
-       if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
-               return;
-
        /* Avoid sending RSPN in the following states. */
        if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
index e9a681d31223cffca67210615a45c6813f1d56af..40be670a1cbc865c4b39694d10e86584f0dc6321 100644 (file)
@@ -593,11 +593,8 @@ bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
                return;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       if (strlen(sym_name) > 0) {
-               strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name);
-               bfa_fcs_lport_ns_util_send_rspn_id(
-                       BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL);
-       }
+       if (strlen(sym_name) > 0)
+               bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
 
index ee4fa40a50b131597a3e1b6960bffc17191f2d03..ce5ef0190bad3f99f7459a859ce0ca0a1e947246 100644 (file)
@@ -4684,6 +4684,7 @@ static struct scsi_host_template gdth_template = {
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .unchecked_isa_dma      = 1,
         .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 #ifdef CONFIG_ISA
index f334859024c0652e3ce9bd197c66ca39b877af65..f2c5005f312af9aabeb25f8831ee17b5f28f6a42 100644 (file)
@@ -395,6 +395,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
        shost->eh_deadline = shost_eh_deadline * HZ;
+       shost->no_write_same = sht->no_write_same;
 
        if (sht->supported_mode == MODE_UNKNOWN)
                /* means we didn't set it ... default to INITIATOR */
index 22f6432eb4755a20af732e8c4d4060e9fbb9e909..20a5e6ecf945fab55a982840d6921046b4c552bf 100644 (file)
@@ -561,6 +561,7 @@ static struct scsi_host_template hpsa_driver_template = {
        .sdev_attrs = hpsa_sdev_attrs,
        .shost_attrs = hpsa_shost_attrs,
        .max_sectors = 8192,
+       .no_write_same = 1,
 };
 
 
@@ -1288,7 +1289,7 @@ static void complete_scsi_command(struct CommandList *cp)
                                        "has check condition: aborted command: "
                                        "ASC: 0x%x, ASCQ: 0x%x\n",
                                        cp, asc, ascq);
-                               cmd->result = DID_SOFT_ERROR << 16;
+                               cmd->result |= DID_SOFT_ERROR << 16;
                                break;
                        }
                        /* Must be some other type of check condition */
@@ -4925,7 +4926,7 @@ reinit_after_soft_reset:
        hpsa_hba_inquiry(h);
        hpsa_register_scsi(h);  /* hook ourselves into SCSI subsystem */
        start_controller_lockup_detector(h);
-       return 1;
+       return 0;
 
 clean4:
        hpsa_free_sg_chain_blocks(h);
index 36ac1c34ce97eb53374f55451b8b42f4752b88f2..573f4128b6b68018f43a3263d166232ef39601fc 100644 (file)
@@ -6305,7 +6305,8 @@ static struct scsi_host_template driver_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = ipr_ioa_attrs,
        .sdev_attrs = ipr_dev_attrs,
-       .proc_name = IPR_NAME
+       .proc_name = IPR_NAME,
+       .no_write_same = 1,
 };
 
 /**
index 8d5ea8a1e5a6f33ab8235b300417d7ba352f84f7..52a216f21ae579644b97c093e89e12306a265595 100644 (file)
@@ -374,6 +374,7 @@ static struct scsi_host_template ips_driver_template = {
        .sg_tablesize           = IPS_MAX_SG,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 
index 161c98efade9b9f290c04588e4638df0f3c421ac..d2895836f9fa4c00fec1a46d993074ecb3edeaea 100644 (file)
@@ -211,7 +211,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
                qc->tf.nsect = 0;
        }
 
-       ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
+       ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis);
        task->uldd_task = qc;
        if (ata_is_atapi(qc->tf.protocol)) {
                memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
index 90c95a3385d18bb52f93093da10c8d400514f712..816db12ef5d555159226c5eb618b110ebb790776 100644 (file)
@@ -4244,6 +4244,7 @@ static struct scsi_host_template megaraid_template = {
        .eh_device_reset_handler        = megaraid_reset,
        .eh_bus_reset_handler           = megaraid_reset,
        .eh_host_reset_handler          = megaraid_reset,
+       .no_write_same                  = 1,
 };
 
 static int
index d1a4b82836ea6936f55504e33bcaabb5db9adbee..e2237a97cb9d314b485869cc37da7e3de8062531 100644 (file)
@@ -367,6 +367,7 @@ static struct scsi_host_template megaraid_template_g = {
        .eh_host_reset_handler          = megaraid_reset_handler,
        .change_queue_depth             = megaraid_change_queue_depth,
        .use_clustering                 = ENABLE_CLUSTERING,
+       .no_write_same                  = 1,
        .sdev_attrs                     = megaraid_sdev_attrs,
        .shost_attrs                    = megaraid_shost_attrs,
 };
index 0a743a5d16477a5e168f02a77a99e90f201caac3..c99812bf2a732f7180c291f3dcc23b5eda81a74c 100644 (file)
@@ -2148,6 +2148,7 @@ static struct scsi_host_template megasas_template = {
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
        .change_queue_depth = megasas_change_queue_depth,
+       .no_write_same = 1,
 };
 
 /**
index f16ece91b94ac73de979eda5496925c1d253b37b..0a1296a87d66d5919859ea586a8637109b537c50 100644 (file)
@@ -3403,6 +3403,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
        port->port_state =  portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPC;
        PM8001_MSG_DBG(pm8001_ha,
                pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
                port_id, phy_id));
@@ -3483,6 +3484,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
                " phy id = %d\n", port_id, phy_id));
        port->port_state =  portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPC;
        port->port_attached = 1;
        pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
index 6d91e2446542c78290dfba8f9e846380ccda3067..e4867e690c846db4ab2954644b959cc044f39f83 100644 (file)
 #define LINKRATE_30                    (0x02 << 8)
 #define LINKRATE_60                    (0x04 << 8)
 
+/* for phy state */
+
+#define PHY_STATE_LINK_UP_SPC          0x1
+
 /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
 #define GSM_SM_BASE                    0x4F0000
 struct mpi_msg_hdr{
index 34f5f5ffef056ec2e86e44726dd99c13ae204877..73a120d81b4dacf7c22e3b99c07458680dacbaf5 100644 (file)
@@ -175,20 +175,16 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 static void pm8001_tasklet(unsigned long opaque)
 {
        struct pm8001_hba_info *pm8001_ha;
-       u32 vec;
-       pm8001_ha = (struct pm8001_hba_info *)opaque;
+       struct isr_param *irq_vector;
+
+       irq_vector = (struct isr_param *)opaque;
+       pm8001_ha = irq_vector->drv_inst;
        if (unlikely(!pm8001_ha))
                BUG_ON(1);
-       vec = pm8001_ha->int_vector;
-       PM8001_CHIP_DISP->isr(pm8001_ha, vec);
+       PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 }
 #endif
 
-static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
-{
-       return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
-}
-
 /**
  * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
  * It obtains the vector number and calls the equivalent bottom
@@ -198,18 +194,20 @@ static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
  */
 static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
 {
-       struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
-       u8 outq = *(u8 *)opaque;
+       struct isr_param *irq_vector;
+       struct pm8001_hba_info *pm8001_ha;
        irqreturn_t ret = IRQ_HANDLED;
+       irq_vector = (struct isr_param *)opaque;
+       pm8001_ha = irq_vector->drv_inst;
+
        if (unlikely(!pm8001_ha))
                return IRQ_NONE;
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
-       pm8001_ha->int_vector = outq;
 #ifdef PM8001_USE_TASKLET
-       tasklet_schedule(&pm8001_ha->tasklet);
+       tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]);
 #else
-       ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
+       ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 #endif
        return ret;
 }
@@ -230,9 +228,8 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
 
-       pm8001_ha->int_vector = 0;
 #ifdef PM8001_USE_TASKLET
-       tasklet_schedule(&pm8001_ha->tasklet);
+       tasklet_schedule(&pm8001_ha->tasklet[0]);
 #else
        ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
 #endif
@@ -457,7 +454,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 {
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
-
+       int j;
 
        pm8001_ha = sha->lldd_ha;
        if (!pm8001_ha)
@@ -480,12 +477,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
                pm8001_ha->iomb_size = IOMB_SIZE_SPC;
 
 #ifdef PM8001_USE_TASKLET
-       /**
-       * default tasklet for non msi-x interrupt handler/first msi-x
-       * interrupt handler
-       **/
-       tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                       (unsigned long)pm8001_ha);
+       /* Tasklet for non msi-x interrupt handler */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+                       (unsigned long)&(pm8001_ha->irq_vector[0]));
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+                               (unsigned long)&(pm8001_ha->irq_vector[j]));
 #endif
        pm8001_ioremap(pm8001_ha);
        if (!pm8001_alloc(pm8001_ha, ent))
@@ -733,19 +732,20 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
                        "pci_enable_msix request ret:%d no of intr %d\n",
                                        rc, pm8001_ha->number_of_intr));
 
-               for (i = 0; i < number_of_intr; i++)
-                       pm8001_ha->outq[i] = i;
 
                for (i = 0; i < number_of_intr; i++) {
                        snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
                                        DRV_NAME"%d", i);
+                       pm8001_ha->irq_vector[i].irq_id = i;
+                       pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
+
                        if (request_irq(pm8001_ha->msix_entries[i].vector,
                                pm8001_interrupt_handler_msix, flag,
-                               intr_drvname[i], &pm8001_ha->outq[i])) {
+                               intr_drvname[i], &(pm8001_ha->irq_vector[i]))) {
                                for (j = 0; j < i; j++)
                                        free_irq(
                                        pm8001_ha->msix_entries[j].vector,
-                                       &pm8001_ha->outq[j]);
+                                       &(pm8001_ha->irq_vector[i]));
                                pci_disable_msix(pm8001_ha->pdev);
                                break;
                        }
@@ -907,7 +907,7 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
-       int i;
+       int i, j;
        pm8001_ha = sha->lldd_ha;
        sas_unregister_ha(sha);
        sas_remove_host(pm8001_ha->shost);
@@ -921,13 +921,18 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                free_irq(pm8001_ha->msix_entries[i].vector,
-                               &pm8001_ha->outq[i]);
+                               &(pm8001_ha->irq_vector[i]));
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
 #endif
 #ifdef PM8001_USE_TASKLET
-       tasklet_kill(&pm8001_ha->tasklet);
+       /* For non-msix and msix interrupts */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_kill(&pm8001_ha->tasklet[0]);
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_kill(&pm8001_ha->tasklet[j]);
 #endif
        pm8001_free(pm8001_ha);
        kfree(sha->sas_phy);
@@ -948,7 +953,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
-       int i;
+       int  i, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        flush_workqueue(pm8001_wq);
@@ -964,13 +969,18 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                free_irq(pm8001_ha->msix_entries[i].vector,
-                               &pm8001_ha->outq[i]);
+                               &(pm8001_ha->irq_vector[i]));
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
 #endif
 #ifdef PM8001_USE_TASKLET
-       tasklet_kill(&pm8001_ha->tasklet);
+       /* For non-msix and msix interrupts */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_kill(&pm8001_ha->tasklet[0]);
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_kill(&pm8001_ha->tasklet[j]);
 #endif
        device_state = pci_choose_state(pdev, state);
        pm8001_printk("pdev=0x%p, slot=%s, entering "
@@ -993,7 +1003,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
        int rc;
-       u8 i = 0;
+       u8 i = 0, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        device_state = pdev->current_state;
@@ -1033,10 +1043,14 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        if (rc)
                goto err_out_disable;
 #ifdef PM8001_USE_TASKLET
-       /* default tasklet for non msi-x interrupt handler/first msi-x
-       * interrupt handler */
-       tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                       (unsigned long)pm8001_ha);
+       /*  Tasklet for non msi-x interrupt handler */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+                       (unsigned long)&(pm8001_ha->irq_vector[0]));
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+                               (unsigned long)&(pm8001_ha->irq_vector[j]));
 #endif
        PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
        if (pm8001_ha->chip_id != chip_8001) {
@@ -1169,6 +1183,7 @@ module_exit(pm8001_exit);
 MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
 MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
 MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
+MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
 MODULE_DESCRIPTION(
                "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 "
                "SAS/SATA controller driver");
index f4eb18e5163152b414fc8b0a08b4a07a7f844111..f50ac44b950e5f0fbd12772689a03c5aaebfea87 100644 (file)
@@ -1098,15 +1098,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
        struct pm8001_tmf_task tmf_task;
        struct pm8001_device *pm8001_dev = dev->lldd_dev;
        struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
+       DECLARE_COMPLETION_ONSTACK(completion_setstate);
        if (dev_is_sata(dev)) {
                struct sas_phy *phy = sas_get_local_phy(dev);
                rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
                        dev, 1, 0);
                rc = sas_phy_reset(phy, 1);
                sas_put_local_phy(phy);
+               pm8001_dev->setds_completion = &completion_setstate;
                rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
                        pm8001_dev, 0x01);
-               msleep(2000);
+               wait_for_completion(&completion_setstate);
        } else {
                tmf_task.tmf = TMF_LU_RESET;
                rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
index 6037d477a183241c0010d73a00580c3667f3aaa9..6c5fd5ee22d30cf5f1ef0b38cbcc8666f46b0d79 100644 (file)
@@ -466,6 +466,10 @@ struct pm8001_hba_memspace {
        u64                     membase;
        u32                     memsize;
 };
+struct isr_param {
+       struct pm8001_hba_info *drv_inst;
+       u32 irq_id;
+};
 struct pm8001_hba_info {
        char                    name[PM8001_NAME_LENGTH];
        struct list_head        list;
@@ -519,14 +523,13 @@ struct pm8001_hba_info {
        int                     number_of_intr;/*will be used in remove()*/
 #endif
 #ifdef PM8001_USE_TASKLET
-       struct tasklet_struct   tasklet;
+       struct tasklet_struct   tasklet[PM8001_MAX_MSIX_VEC];
 #endif
        u32                     logging_level;
        u32                     fw_status;
        u32                     smp_exp_mode;
-       u32                     int_vector;
        const struct firmware   *fw_image;
-       u8                      outq[PM8001_MAX_MSIX_VEC];
+       struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
 };
 
 struct pm8001_work {
index 8987b1706216436ef36392eb329e56320547ab23..c950dc5c99432967891c093d7bddb0bb24186e7e 100644 (file)
@@ -2894,6 +2894,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
        port->port_state = portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
                "portid:%d; phyid:%d; linkrate:%d; "
                "portstate:%x; devicetype:%x\n",
@@ -2978,6 +2979,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                                port_id, phy_id, link_rate, portstate));
 
        port->port_state = portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        port->port_attached = 1;
        pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
index c86816bea4243354d8864a5422778996ebec215e..9970a385795d16c5328ca6c7711ebf146e02c63c 100644 (file)
 #define SAS_DOPNRJT_RTRY_TMO            128
 #define SAS_COPNRJT_RTRY_TMO            128
 
+/* for phy state */
+#define PHY_STATE_LINK_UP_SPCV         0x2
 /*
   Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
   Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
index bd6f743d87a78af19c698d38d70291723fd28dfb..be8ce54f99b247bcba427a16c2f4873b987329c8 100644 (file)
@@ -1404,11 +1404,22 @@ enum {
 };
 #define PMCRAID_AEN_CMD_MAX (__PMCRAID_AEN_CMD_MAX - 1)
 
+static struct genl_multicast_group pmcraid_mcgrps[] = {
+       { .name = "events", /* not really used - see ID discussion below */ },
+};
+
 static struct genl_family pmcraid_event_family = {
-       .id = GENL_ID_GENERATE,
+       /*
+        * Due to prior multicast group abuse (the code having assumed that
+        * the family ID can be used as a multicast group ID) we need to
+        * statically allocate a family (and thus group) ID.
+        */
+       .id = GENL_ID_PMCRAID,
        .name = "pmcraid",
        .version = 1,
-       .maxattr = PMCRAID_AEN_ATTR_MAX
+       .maxattr = PMCRAID_AEN_ATTR_MAX,
+       .mcgrps = pmcraid_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(pmcraid_mcgrps),
 };
 
 /**
@@ -1511,9 +1522,8 @@ static int pmcraid_notify_aen(
                return result;
        }
 
-       result =
-               genlmsg_multicast(&pmcraid_event_family, skb, 0,
-                                 pmcraid_event_family.id, GFP_ATOMIC);
+       result = genlmsg_multicast(&pmcraid_event_family, skb,
+                                  0, 0, GFP_ATOMIC);
 
        /* If there are no listeners, genlmsg_multicast may return non-zero
         * value.
@@ -4315,6 +4325,7 @@ static struct scsi_host_template pmcraid_host_template = {
        .this_id = -1,
        .sg_tablesize = PMCRAID_MAX_IOADLS,
        .max_sectors = PMCRAID_IOA_MAX_SECTORS,
+       .no_write_same = 1,
        .cmd_per_lun = PMCRAID_MAX_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = pmcraid_host_attrs,
index 596480022b0a4b88eb7a3d855e472200d5ab4fef..38a1257e76e1ec432c6cc81893b54a27ee30081a 100644 (file)
@@ -471,7 +471,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
                schedule_delayed_work(&tgt->sess_del_work, 0);
        else
                schedule_delayed_work(&tgt->sess_del_work,
-                   jiffies - sess->expires);
+                   sess->expires - jiffies);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -550,13 +550,14 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
        struct scsi_qla_host *vha = tgt->vha;
        struct qla_hw_data *ha = vha->hw;
        struct qla_tgt_sess *sess;
-       unsigned long flags;
+       unsigned long flags, elapsed;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        while (!list_empty(&tgt->del_sess_list)) {
                sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
                    del_list_entry);
-               if (time_after_eq(jiffies, sess->expires)) {
+               elapsed = jiffies;
+               if (time_after_eq(elapsed, sess->expires)) {
                        qlt_undelete_sess(sess);
 
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
@@ -566,7 +567,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
                        ha->tgt.tgt_ops->put_sess(sess);
                } else {
                        schedule_delayed_work(&tgt->sess_del_work,
-                           jiffies - sess->expires);
+                           sess->expires - elapsed);
                        break;
                }
        }
@@ -4290,6 +4291,7 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn,
                if (rc != 0) {
                        ha->tgt.tgt_ops = NULL;
                        ha->tgt.target_lport_ptr = NULL;
+                       scsi_host_put(host);
                }
                mutex_unlock(&qla_tgt_mutex);
                return rc;
index e6c4bff04339cb1975637a92bb3842601e1e158f..69725f7c32c1bc5b6c6dbfb93756aa4770b5d17e 100644 (file)
@@ -2659,6 +2659,12 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        struct scsi_device *sdev = sdkp->device;
 
+       if (sdev->host->no_write_same) {
+               sdev->no_write_same = 1;
+
+               return;
+       }
+
        if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
                /* too large values might cause issues with arcmsr */
                int vpd_buf_len = 64;
index 1a28f5632797ed2da2f27c0752013e3c7e4dde5d..17d7404272400dd1a76989a3965e0c4b85343036 100644 (file)
@@ -1697,6 +1697,7 @@ static struct scsi_host_template scsi_driver = {
        .use_clustering =       DISABLE_CLUSTERING,
        /* Make sure we dont get a sg segment crosses a page boundary */
        .dma_boundary =         PAGE_SIZE-1,
+       .no_write_same =        1,
 };
 
 enum {
index eb1f1ef5fa2eb69db729b6061b2d96c85aaf968b..e2dd2fbec5ee869f014db05a2fe8b3b616ac9d75 100644 (file)
@@ -395,7 +395,7 @@ config SPI_S3C24XX_FIQ
 config SPI_S3C64XX
        tristate "Samsung S3C64XX series type SPI"
        depends on PLAT_SAMSUNG
-       select S3C64XX_DMA if ARCH_S3C64XX
+       select S3C64XX_PL080 if ARCH_S3C64XX
        help
          SPI driver for Samsung S3C64XX and newer SoCs.
 
index 3ed666fe840a0cdbaf1a2a2c6cd75670dd25fb48..9025edd7dc45fde131c7c9c6004ce5434829c785 100644 (file)
@@ -377,7 +377,7 @@ out_master_put:
 
 static int bcm2835_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
 
        free_irq(bs->irq, master);
index 80d56b214eb51af96ceb9e9d55ffea6bbb2d7302..469ecd8763581c3628c033e00adc47699e033f12 100644 (file)
@@ -435,7 +435,7 @@ out:
 
 static int bcm63xx_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        /* reset spi block */
index 9602bbd8d7eac061fffb5543704fc9d68a48f135..87676587d783551e120f5478f9b522c7add7df31 100644 (file)
@@ -557,7 +557,7 @@ free_master:
 
 static int mpc512x_psc_spi_do_remove(struct device *dev)
 {
-       struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
        clk_disable_unprepare(mps->clk_mclk);
index 73afb56c08cc26826d468ad4aaacdce3a7e7043f..3adebfa22e3d785b6bf7ffb2149e77652039c3c3 100644 (file)
@@ -565,7 +565,7 @@ static int mxs_spi_remove(struct platform_device *pdev)
        struct mxs_spi *spi;
        struct mxs_ssp *ssp;
 
-       master = spi_master_get(platform_get_drvdata(pdev));
+       master = platform_get_drvdata(pdev);
        spi = spi_master_get_devdata(master);
        ssp = &spi->ssp;
 
index cb0e1f1137adb65384188ce31651171cb3f5f311..7765b1999537a08e5c6d95eed39bdea4c8c9c9dd 100644 (file)
@@ -1073,6 +1073,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
        { "INT33C0", 0 },
        { "INT33C1", 0 },
+       { "INT3430", 0 },
+       { "INT3431", 0 },
        { "80860F0E", 0 },
        { },
 };
@@ -1291,6 +1293,9 @@ static int pxa2xx_spi_resume(struct device *dev)
        /* Enable the SSP clock */
        clk_prepare_enable(ssp->clk);
 
+       /* Restore LPSS private register bits */
+       lpss_ssp_setup(drv_data);
+
        /* Start the queue running */
        status = spi_master_resume(drv_data->master);
        if (status != 0) {
index 58449ad4ad0d3a83eb273b49f292909078519ca1..9e829cee73572bab01eae87f3e4a219a8e76c98f 100644 (file)
@@ -885,14 +885,13 @@ static void rspi_release_dma(struct rspi_data *rspi)
 
 static int rspi_remove(struct platform_device *pdev)
 {
-       struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
+       struct rspi_data *rspi = platform_get_drvdata(pdev);
 
        spi_unregister_master(rspi->master);
        rspi_release_dma(rspi);
        free_irq(platform_get_irq(pdev, 0), rspi);
        clk_put(rspi->clk);
        iounmap(rspi->addr);
-       spi_master_put(rspi->master);
 
        return 0;
 }
index 0b71270fbf67ba671dd43f116db48de30076514c..4396bd44854063d9488cfd5dadc863c40c9e1dbf 100644 (file)
@@ -161,7 +161,7 @@ static int ti_qspi_setup(struct spi_device *spi)
                        qspi->spi_max_frequency, clk_div);
 
        ret = pm_runtime_get_sync(qspi->dev);
-       if (ret) {
+       if (ret < 0) {
                dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
                return ret;
        }
@@ -459,11 +459,10 @@ static int ti_qspi_probe(struct platform_device *pdev)
        if (!of_property_read_u32(np, "num-cs", &num_cs))
                master->num_chipselect = num_cs;
 
-       platform_set_drvdata(pdev, master);
-
        qspi = spi_master_get_devdata(master);
        qspi->master = master;
        qspi->dev = &pdev->dev;
+       platform_set_drvdata(pdev, qspi);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -517,10 +516,26 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
-       struct  ti_qspi *qspi = platform_get_drvdata(pdev);
+       struct spi_master *master;
+       struct ti_qspi *qspi;
+       int ret;
+
+       master = platform_get_drvdata(pdev);
+       qspi = spi_master_get_devdata(master);
+
+       ret = pm_runtime_get_sync(qspi->dev);
+       if (ret < 0) {
+               dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
+               return ret;
+       }
 
        ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
 
+       pm_runtime_put(qspi->dev);
+       pm_runtime_disable(&pdev->dev);
+
+       spi_unregister_master(master);
+
        return 0;
 }
 
index 637cce2b8bdde8d3f37c8134a5f3aee7c4adead8..18c9bb2b5f39108793a32a2b71624f0e59434712 100644 (file)
@@ -425,7 +425,7 @@ exit:
 
 static int txx9spi_remove(struct platform_device *dev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+       struct spi_master *master = platform_get_drvdata(dev);
        struct txx9spi *c = spi_master_get_devdata(master);
 
        destroy_workqueue(c->workqueue);
index 18cc625d887f796aed4b082eb2366262aec8aaa8..349ebba4b1992afdf703e689022dfbf67b07f626 100644 (file)
@@ -1415,7 +1415,7 @@ int devm_spi_register_master(struct device *dev, struct spi_master *master)
                return -ENOMEM;
 
        ret = spi_register_master(master);
-       if (ret != 0) {
+       if (!ret) {
                *ptr = master;
                devres_add(dev, ptr);
        } else {
index 7a9bf3b578104bf57939ce032c96dc17c88840be..9a5ebd6cc51235b699756c1c08c7609235b7d1e4 100644 (file)
@@ -1284,9 +1284,8 @@ done:
        kfree_skb(skb);
 }
 
-static int btmtk_usb_send_frame(struct sk_buff *skb)
+static int btmtk_usb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
-       struct hci_dev *hdev = (struct hci_dev *)skb->dev;
        struct btmtk_usb_data *data = hci_get_drvdata(hdev);
        struct usb_ctrlrequest *dr;
        struct urb *urb;
index 8f02bf66e20b2002b3b52655919a89f95c0fcad9..4964d2a2fc7d54ba099541b3f9c2c61be4799936 100644 (file)
@@ -446,7 +446,7 @@ int comedi_load_firmware(struct comedi_device *dev,
                release_firmware(fw);
        }
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 EXPORT_SYMBOL_GPL(comedi_load_firmware);
 
index 432e3f9c3301ecc7ce6f6d633913bf1e1e85f4e4..c55f234b29e6052e541dc7b7043d0a877682b4cb 100644 (file)
@@ -63,7 +63,8 @@ enum pci_8255_boardid {
        BOARD_ADLINK_PCI7296,
        BOARD_CB_PCIDIO24,
        BOARD_CB_PCIDIO24H,
-       BOARD_CB_PCIDIO48H,
+       BOARD_CB_PCIDIO48H_OLD,
+       BOARD_CB_PCIDIO48H_NEW,
        BOARD_CB_PCIDIO96H,
        BOARD_NI_PCIDIO96,
        BOARD_NI_PCIDIO96B,
@@ -106,11 +107,16 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
                .dio_badr       = 2,
                .n_8255         = 1,
        },
-       [BOARD_CB_PCIDIO48H] = {
+       [BOARD_CB_PCIDIO48H_OLD] = {
                .name           = "cb_pci-dio48h",
                .dio_badr       = 1,
                .n_8255         = 2,
        },
+       [BOARD_CB_PCIDIO48H_NEW] = {
+               .name           = "cb_pci-dio48h",
+               .dio_badr       = 2,
+               .n_8255         = 2,
+       },
        [BOARD_CB_PCIDIO96H] = {
                .name           = "cb_pci-dio96h",
                .dio_badr       = 2,
@@ -263,7 +269,10 @@ static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = {
        { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 },
        { PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 },
        { PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H },
-       { PCI_VDEVICE(CB, 0x000b), BOARD_CB_PCIDIO48H },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, 0x0000, 0x0000),
+         .driver_data = BOARD_CB_PCIDIO48H_OLD },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b),
+         .driver_data = BOARD_CB_PCIDIO48H_NEW },
        { PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H },
        { PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 },
        { PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B },
index d041b714db29732f91e8739db8dcf1122f55d55b..2baaf1db6fbf34e6a9d8694d560b6a047871bf81 100644 (file)
@@ -173,11 +173,11 @@ static int pcl730_do_insn_bits(struct comedi_device *dev,
        if (mask) {
                if (mask & 0x00ff)
                        outb(s->state & 0xff, dev->iobase + reg);
-               if ((mask & 0xff00) & (s->n_chan > 8))
+               if ((mask & 0xff00) && (s->n_chan > 8))
                        outb((s->state >> 8) & 0xff, dev->iobase + reg + 1);
-               if ((mask & 0xff0000) & (s->n_chan > 16))
+               if ((mask & 0xff0000) && (s->n_chan > 16))
                        outb((s->state >> 16) & 0xff, dev->iobase + reg + 2);
-               if ((mask & 0xff000000) & (s->n_chan > 24))
+               if ((mask & 0xff000000) && (s->n_chan > 24))
                        outb((s->state >> 24) & 0xff, dev->iobase + reg + 3);
        }
 
index 6815cfe2664e42e632114b3e87ca140b349008f3..b486099b543d56e61a14e94b3bc698c58cc04cb0 100644 (file)
@@ -494,7 +494,7 @@ static void s626_send_dac(struct comedi_device *dev, uint32_t val)
  * Private helper function: Write setpoint to an application DAC channel.
  */
 static void s626_set_dac(struct comedi_device *dev, uint16_t chan,
-                        unsigned short dacdata)
+                        int16_t dacdata)
 {
        struct s626_private *devpriv = dev->private;
        uint16_t signmask;
index 933b01a0f03d4274e4f82ced6240a79f78b2c742..0adf3cffddb07251f09d961eedc490206db88fb3 100644 (file)
@@ -465,7 +465,7 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev,
        unsigned char *rx_buf = devpriv->usb_rx_buf;
        unsigned char *tx_buf = devpriv->usb_tx_buf;
        int reg, cmd;
-       int ret;
+       int ret = 0;
 
        if (devpriv->model == VMK8061_MODEL) {
                reg = VMK8061_DO_REG;
index 68ded17c0f5c7f9302613d37ed48238f9f54422b..12f333fa59b525ef7598d2a9cf0e213f925b34a4 100644 (file)
@@ -578,7 +578,7 @@ static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file,
                 u8 **c_file, const u8 *endpoint, bool boot_case)
 {
        long word_length;
-       int status;
+       int status = 0;
 
        /*DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");i*/
        word_length = get_request_value(ft1000dev);
@@ -1074,4 +1074,3 @@ int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
 
        return status;
 }
-
index a3ea69e9d800ef3ae992efbacb4575bc7ad94782..34634da1f9f733fd0268a728fc5e3653aeedff58 100644 (file)
@@ -6,6 +6,8 @@ menu "Magnetometer sensors"
 config SENSORS_HMC5843
        tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer"
        depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          Say Y here to add support for the Honeywell HMC5843, HMC5883 and
          HMC5883L 3-Axis Magnetometer (digital compass).
index 99421f90d1895f6a0691d4443c457f5aac2335db..0485d7f398672a61045367b7ac85a267b34b6e8d 100644 (file)
@@ -451,7 +451,12 @@ done:
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
                        BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
                .scan_index = idx,                                      \
-               .scan_type = IIO_ST('s', 16, 16, IIO_BE),               \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
        }
 
 static const struct iio_chan_spec hmc5843_channels[] = {
index 2c3a9e178fb5e65a073dc777b1c7dd86c7a9f34f..8742432d7b0170f72144675d8d9b591f976a0af7 100644 (file)
@@ -8,4 +8,6 @@ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
 obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
 obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
-obj-$(CONFIG_DRM_IMX_IPUV3)    += ipuv3-crtc.o ipuv3-plane.o
+
+imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
+obj-$(CONFIG_DRM_IMX_IPUV3)    += imx-ipuv3-crtc.o
index 51aa9772f959520db89a91e2be69a8c20bb9774c..96e4eee344ef602174acec2ce27cf57bfb0ce128 100644 (file)
@@ -72,6 +72,7 @@ int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
 {
        return crtc->pipe;
 }
+EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
 
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
@@ -87,8 +88,9 @@ static int imx_drm_driver_unload(struct drm_device *drm)
 
        imx_drm_device_put();
 
-       drm_mode_config_cleanup(imxdrm->drm);
+       drm_vblank_cleanup(imxdrm->drm);
        drm_kms_helper_poll_fini(imxdrm->drm);
+       drm_mode_config_cleanup(imxdrm->drm);
 
        return 0;
 }
@@ -198,8 +200,8 @@ static void imx_drm_driver_preclose(struct drm_device *drm,
        if (!file->is_master)
                return;
 
-       for (i = 0; i < 4; i++)
-               imx_drm_disable_vblank(drm , i);
+       for (i = 0; i < MAX_CRTC; i++)
+               imx_drm_disable_vblank(drm, i);
 }
 
 static const struct file_operations imx_drm_driver_fops = {
@@ -375,8 +377,6 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        struct imx_drm_device *imxdrm = __imx_drm_device();
        int ret;
 
-       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
        ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
        if (ret)
                return ret;
@@ -384,6 +384,9 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        drm_crtc_helper_add(imx_drm_crtc->crtc,
                        imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
+       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
+                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
+
        drm_mode_group_reinit(imxdrm->drm);
 
        return 0;
@@ -427,11 +430,11 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
        ret = drm_mode_group_init_legacy_group(imxdrm->drm,
                        &imxdrm->drm->primary->mode_group);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        /*
         * with vblank_disable_allowed = true, vblank interrupt will be disabled
@@ -440,12 +443,19 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
         */
        imxdrm->drm->vblank_disable_allowed = true;
 
-       if (!imx_drm_device_get())
+       if (!imx_drm_device_get()) {
                ret = -EINVAL;
+               goto err_vblank;
+       }
 
-       ret = 0;
+       mutex_unlock(&imxdrm->mutex);
+       return 0;
 
-err_init:
+err_vblank:
+       drm_vblank_cleanup(drm);
+err_kms:
+       drm_kms_helper_poll_fini(drm);
+       drm_mode_config_cleanup(drm);
        mutex_unlock(&imxdrm->mutex);
 
        return ret;
@@ -491,6 +501,15 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 
        mutex_lock(&imxdrm->mutex);
 
+       /*
+        * The vblank arrays are dimensioned by MAX_CRTC - we can't
+        * pass IDs greater than this to those functions.
+        */
+       if (imxdrm->pipes >= MAX_CRTC) {
+               ret = -EINVAL;
+               goto err_busy;
+       }
+
        if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
@@ -527,6 +546,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
        return 0;
 
 err_register:
+       list_del(&imx_drm_crtc->list);
        kfree(imx_drm_crtc);
 err_alloc:
 err_busy:
index 680f4c8fa0815481a410621eb616879dbb149109..2c44fef8d58b327df92e97667f0661c45e3e57d6 100644 (file)
@@ -114,7 +114,6 @@ struct imx_tve {
        struct drm_encoder encoder;
        struct imx_drm_encoder *imx_drm_encoder;
        struct device *dev;
-       spinlock_t enable_lock; /* serializes tve_enable/disable */
        spinlock_t lock;        /* register lock */
        bool enabled;
        int mode;
@@ -146,10 +145,8 @@ __releases(&tve->lock)
 
 static void tve_enable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (!tve->enabled) {
                tve->enabled = true;
                clk_prepare_enable(tve->clk);
@@ -169,23 +166,18 @@ static void tve_enable(struct imx_tve *tve)
                             TVE_CD_SM_IEN |
                             TVE_CD_LM_IEN |
                             TVE_CD_MON_END_IEN);
-
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static void tve_disable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (tve->enabled) {
                tve->enabled = false;
                ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
                                         TVE_IPU_CLK_EN | TVE_EN, 0);
                clk_disable_unprepare(tve->clk);
        }
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static int tve_setup_tvout(struct imx_tve *tve)
@@ -601,7 +593,6 @@ static int imx_tve_probe(struct platform_device *pdev)
 
        tve->dev = &pdev->dev;
        spin_lock_init(&tve->lock);
-       spin_lock_init(&tve->enable_lock);
 
        ddc_node = of_parse_phandle(np, "ddc", 0);
        if (ddc_node) {
index 7a22ce619ed264ba536de785650700b02f6d3ef3..97ca6924dbb3fce7b5db813aefb781adb273187a 100644 (file)
@@ -996,35 +996,35 @@ static const struct ipu_platform_reg client_reg[] = {
        },
 };
 
+static DEFINE_MUTEX(ipu_client_id_mutex);
 static int ipu_client_id;
 
-static int ipu_add_subdevice_pdata(struct device *dev,
-               const struct ipu_platform_reg *reg)
-{
-       struct platform_device *pdev;
-
-       pdev = platform_device_register_data(dev, reg->name, ipu_client_id++,
-                       &reg->pdata, sizeof(struct ipu_platform_reg));
-
-       return PTR_ERR_OR_ZERO(pdev);
-}
-
 static int ipu_add_client_devices(struct ipu_soc *ipu)
 {
-       int ret;
-       int i;
+       struct device *dev = ipu->dev;
+       unsigned i;
+       int id, ret;
+
+       mutex_lock(&ipu_client_id_mutex);
+       id = ipu_client_id;
+       ipu_client_id += ARRAY_SIZE(client_reg);
+       mutex_unlock(&ipu_client_id_mutex);
 
        for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
                const struct ipu_platform_reg *reg = &client_reg[i];
-               ret = ipu_add_subdevice_pdata(ipu->dev, reg);
-               if (ret)
+               struct platform_device *pdev;
+
+               pdev = platform_device_register_data(dev, reg->name,
+                       id++, &reg->pdata, sizeof(reg->pdata));
+
+               if (IS_ERR(pdev))
                        goto err_register;
        }
 
        return 0;
 
 err_register:
-       platform_device_unregister_children(to_platform_device(ipu->dev));
+       platform_device_unregister_children(to_platform_device(dev));
 
        return ret;
 }
index 5dec771d70eee8c08a6bc0b787f7f116ddd6906d..4d340f4a2198618d22bc37ab9cebb4f0c0cb2c06 100644 (file)
@@ -409,8 +409,8 @@ int ptlrpc_stop_pinger(void)
        struct l_wait_info lwi = { 0 };
        int rc = 0;
 
-       if (!thread_is_init(&pinger_thread) &&
-           !thread_is_stopped(&pinger_thread))
+       if (thread_is_init(&pinger_thread) ||
+           thread_is_stopped(&pinger_thread))
                return -EALREADY;
 
        ptlrpc_pinger_remove_timeouts();
index 58684da45e6c2927cb042ceb0dc4a364b3037a5c..b658c2316df340b4480ed72ca90d457d913e3691 100644 (file)
@@ -15,6 +15,8 @@
  * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -661,7 +663,7 @@ static int go7007_usb_interface_reset(struct go7007 *go)
 
        if (usb->board->flags & GO7007_USB_EZUSB) {
                /* Reset buffer in EZ-USB */
-               dev_dbg(go->dev, "resetting EZ-USB buffers\n");
+               pr_debug("resetting EZ-USB buffers\n");
                if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
                    go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
                        return -1;
@@ -689,7 +691,7 @@ static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
        u16 status_reg = 0;
        int timeout = 500;
 
-       dev_dbg(go->dev, "WriteInterrupt: %04x %04x\n", addr, data);
+       pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
 
        for (i = 0; i < 100; ++i) {
                r = usb_control_msg(usb->usbdev,
@@ -734,7 +736,7 @@ static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
        int r;
        int timeout = 500;
 
-       dev_dbg(go->dev, "WriteInterrupt: %04x %04x\n", addr, data);
+       pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
 
        go->usb_buf[0] = data & 0xff;
        go->usb_buf[1] = data >> 8;
@@ -771,7 +773,7 @@ static void go7007_usb_readinterrupt_complete(struct urb *urb)
                go->interrupt_available = 1;
                go->interrupt_data = __le16_to_cpu(regs[0]);
                go->interrupt_value = __le16_to_cpu(regs[1]);
-               dev_dbg(go->dev, "ReadInterrupt: %04x %04x\n",
+               pr_debug("ReadInterrupt: %04x %04x\n",
                                go->interrupt_value, go->interrupt_data);
        }
 
@@ -891,7 +893,7 @@ static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
        int transferred, pipe;
        int timeout = 500;
 
-       dev_dbg(go->dev, "DownloadBuffer sending %d bytes\n", len);
+       pr_debug("DownloadBuffer sending %d bytes\n", len);
 
        if (usb->board->flags & GO7007_USB_EZUSB)
                pipe = usb_sndbulkpipe(usb->usbdev, 2);
@@ -977,7 +979,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
                                !(msgs[i].flags & I2C_M_RD) &&
                                (msgs[i + 1].flags & I2C_M_RD)) {
 #ifdef GO7007_I2C_DEBUG
-                       dev_dbg(go->dev, "i2c write/read %d/%d bytes on %02x\n",
+                       pr_debug("i2c write/read %d/%d bytes on %02x\n",
                                msgs[i].len, msgs[i + 1].len, msgs[i].addr);
 #endif
                        buf[0] = 0x01;
@@ -988,7 +990,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
                        buf[buf_len++] = msgs[++i].len;
                } else if (msgs[i].flags & I2C_M_RD) {
 #ifdef GO7007_I2C_DEBUG
-                       dev_dbg(go->dev, "i2c read %d bytes on %02x\n",
+                       pr_debug("i2c read %d bytes on %02x\n",
                                        msgs[i].len, msgs[i].addr);
 #endif
                        buf[0] = 0x01;
@@ -998,7 +1000,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
                        buf_len = 4;
                } else {
 #ifdef GO7007_I2C_DEBUG
-                       dev_dbg(go->dev, "i2c write %d bytes on %02x\n",
+                       pr_debug("i2c write %d bytes on %02x\n",
                                        msgs[i].len, msgs[i].addr);
 #endif
                        buf[0] = 0x00;
@@ -1057,7 +1059,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
        char *name;
        int video_pipe, i, v_urb_len;
 
-       dev_dbg(go->dev, "probing new GO7007 USB board\n");
+       pr_debug("probing new GO7007 USB board\n");
 
        switch (id->driver_info) {
        case GO7007_BOARDID_MATRIX_II:
@@ -1097,13 +1099,13 @@ static int go7007_usb_probe(struct usb_interface *intf,
                board = &board_px_tv402u;
                break;
        case GO7007_BOARDID_LIFEVIEW_LR192:
-               dev_err(go->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
+               dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
                return -ENODEV;
                name = "Lifeview TV Walker Ultra";
                board = &board_lifeview_lr192;
                break;
        case GO7007_BOARDID_SENSORAY_2250:
-               dev_info(go->dev, "Sensoray 2250 found\n");
+               dev_info(&intf->dev, "Sensoray 2250 found\n");
                name = "Sensoray 2250/2251";
                board = &board_sensoray_2250;
                break;
@@ -1112,7 +1114,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
                board = &board_ads_usbav_709;
                break;
        default:
-               dev_err(go->dev, "unknown board ID %d!\n",
+               dev_err(&intf->dev, "unknown board ID %d!\n",
                                (unsigned int)id->driver_info);
                return -ENODEV;
        }
@@ -1247,7 +1249,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
                                        sizeof(go->name));
                        break;
                default:
-                       dev_dbg(go->dev, "unable to detect tuner type!\n");
+                       pr_debug("unable to detect tuner type!\n");
                        break;
                }
                /* Configure tuner mode selection inputs connected
index 3066ee2e753be3ed887d11b9615b41b78261b6bb..49ea76b3435dcd19b9a9f8bbbfb561a92b0a53fe 100644 (file)
@@ -681,7 +681,8 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
                        dev_err(nvec->dev,
                                "RX buffer overflow on %p: "
                                "Trying to write byte %u of %u\n",
-                               nvec->rx, nvec->rx->pos, NVEC_MSG_SIZE);
+                               nvec->rx, nvec->rx ? nvec->rx->pos : 0,
+                               NVEC_MSG_SIZE);
                break;
        default:
                nvec->state = 0;
index 2c678f4095734698b2fcfcdf6318691b7b8c4855..2f548ebada59286fbc8290bd3ce8724d2641aae0 100644 (file)
@@ -1115,6 +1115,9 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf,  int len)
                        return _FAIL;
        }
 
+       /* fix bug of flush_cam_entry at STOP AP mode */
+       psta->state |= WIFI_AP_STATE;
+       rtw_indicate_connect(padapter);
        pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */
        return ret;
 }
index 165b918b8171b6380c4d8653d576a0bc085ecb99..1b6d581c438b56a970fdf1b08e52c94846c9d793 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig TIDSPBRIDGE
        tristate "DSP Bridge driver"
-       depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM
+       depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM && BROKEN
        select MAILBOX
        select OMAP2PLUS_MBOX
        help
index 1aa4a3fd0f1ba3b023367974593897ba1077df18..56e355b3e7fa00b5dd6a8ca4929071cc5cdaca09 100644 (file)
@@ -258,7 +258,8 @@ err:
 /* This function maps kernel space memory to user space memory. */
 static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-       u32 status;
+       struct omap_dsp_platform_data *pdata =
+                                       omap_dspbridge_dev->dev.platform_data;
 
        /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -268,13 +269,9 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
                vma->vm_start, vma->vm_end, vma->vm_page_prot,
                vma->vm_flags);
 
-       status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                                vma->vm_end - vma->vm_start,
-                                vma->vm_page_prot);
-       if (status != 0)
-               status = -EAGAIN;
-
-       return status;
+       return vm_iomap_memory(vma,
+                              pdata->phys_mempool_base,
+                              pdata->phys_mempool_size);
 }
 
 static const struct file_operations bridge_fops = {
index aab0012bba92909611659b78ef982d48aec82cfb..ab8b2ba6eedd79cdb2146ef0911fc0ae88e7a63a 100644 (file)
@@ -143,7 +143,8 @@ static int hostap_disable_hostapd(PSDevice pDevice, int rtnl_locked)
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
                        pDevice->dev->name, pDevice->apdev->name);
        }
-       free_netdev(pDevice->apdev);
+       if (pDevice->apdev)
+               free_netdev(pDevice->apdev);
        pDevice->apdev = NULL;
        pDevice->bEnable8021x = false;
        pDevice->bEnableHostWEP = false;
index 1e8b8412e67e4b6663161c977f2334a154b65e0a..4aa5ef54b683734097075127136512f314c5664f 100644 (file)
@@ -939,6 +939,7 @@ int BBbVT3184Init(struct vnt_private *pDevice)
     u8 *                   pbyAgc;
     u16                    wLengthAgc;
     u8                    abyArray[256];
+       u8 data;
 
     ntStatus = CONTROLnsRequestIn(pDevice,
                                   MESSAGE_TYPE_READ,
@@ -1104,6 +1105,16 @@ else {
     ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x0D,0x01);
 
     RFbRFTableDownload(pDevice);
+
+       /* Fix for TX USB resets from vendors driver */
+       CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, USB_REG4,
+               MESSAGE_REQUEST_MEM, sizeof(data), &data);
+
+       data |= 0x2;
+
+       CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, USB_REG4,
+               MESSAGE_REQUEST_MEM, sizeof(data), &data);
+
     return true;//ntStatus;
 }
 
index ae1676d190c5b318fcaa43466f58539d39fed095..67ba48b9a8d906d7c8e1091a7ccfdddebf9b9ee5 100644 (file)
@@ -133,7 +133,8 @@ static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked)
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
                       pDevice->dev->name, pDevice->apdev->name);
        }
-       free_netdev(pDevice->apdev);
+       if (pDevice->apdev)
+               free_netdev(pDevice->apdev);
        pDevice->apdev = NULL;
     pDevice->bEnable8021x = false;
     pDevice->bEnableHostWEP = false;
index 5e073062017a2e657e1f0b33ebddcaa1d2fa21c4..5cf5e732a36fdc1f4a485c14b3eaa05c14a1f0c5 100644 (file)
@@ -66,6 +66,8 @@
 
 #define VIAUSB20_PACKET_HEADER          0x04
 
+#define USB_REG4       0x604
+
 typedef struct _CMD_MESSAGE
 {
     u8        byData[256];
index 79ce363b2ea9d1dd2cb0b79362b607659ca37345..3277d9838f4e928ab3555720a186e476e826a720 100644 (file)
@@ -652,21 +652,30 @@ static ssize_t reset_store(struct device *dev,
                return -ENOMEM;
 
        /* Do not reset an active device! */
-       if (bdev->bd_holders)
-               return -EBUSY;
+       if (bdev->bd_holders) {
+               ret = -EBUSY;
+               goto out;
+       }
 
        ret = kstrtou16(buf, 10, &do_reset);
        if (ret)
-               return ret;
+               goto out;
 
-       if (!do_reset)
-               return -EINVAL;
+       if (!do_reset) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        /* Make sure all pending I/O is finished */
        fsync_bdev(bdev);
+       bdput(bdev);
 
        zram_reset_device(zram, true);
        return len;
+
+out:
+       bdput(bdev);
+       return ret;
 }
 
 static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
index 1a67537dbc5654be28e7d640f89d3fe3fd903e30..3b950e5a918f8c1a252aabc7da049e2732e2e15d 100644 (file)
@@ -430,7 +430,12 @@ static struct page *get_next_page(struct page *page)
        return next;
 }
 
-/* Encode <page, obj_idx> as a single handle value */
+/*
+ * Encode <page, obj_idx> as a single handle value.
+ * On hardware platforms with physical memory starting at 0x0 the pfn
+ * could be 0 so we ensure that the handle will never be 0 by adjusting the
+ * encoded obj_idx value before encoding.
+ */
 static void *obj_location_to_handle(struct page *page, unsigned long obj_idx)
 {
        unsigned long handle;
@@ -441,17 +446,21 @@ static void *obj_location_to_handle(struct page *page, unsigned long obj_idx)
        }
 
        handle = page_to_pfn(page) << OBJ_INDEX_BITS;
-       handle |= (obj_idx & OBJ_INDEX_MASK);
+       handle |= ((obj_idx + 1) & OBJ_INDEX_MASK);
 
        return (void *)handle;
 }
 
-/* Decode <page, obj_idx> pair from the given object handle */
+/*
+ * Decode <page, obj_idx> pair from the given object handle. We adjust the
+ * decoded obj_idx back to its original value since it was adjusted in
+ * obj_location_to_handle().
+ */
 static void obj_handle_to_location(unsigned long handle, struct page **page,
                                unsigned long *obj_idx)
 {
        *page = pfn_to_page(handle >> OBJ_INDEX_BITS);
-       *obj_idx = handle & OBJ_INDEX_MASK;
+       *obj_idx = (handle & OBJ_INDEX_MASK) - 1;
 }
 
 static unsigned long obj_idx_to_offset(struct page *page,
index d70e9119e906cba0c0f38da61948ce745bc5d6e5..00867190413c78d1f3226348e5c68718077c0b9f 100644 (file)
@@ -465,6 +465,7 @@ int iscsit_del_np(struct iscsi_np *np)
                 */
                send_sig(SIGINT, np->np_thread, 1);
                kthread_stop(np->np_thread);
+               np->np_thread = NULL;
        }
 
        np->np_transport->iscsit_free_np(np);
@@ -823,24 +824,22 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
             (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
                /*
-                * Vmware ESX v3.0 uses a modified Cisco Initiator (v3.4.2)
-                * that adds support for RESERVE/RELEASE.  There is a bug
-                * add with this new functionality that sets R/W bits when
-                * neither CDB carries any READ or WRITE datapayloads.
+                * From RFC-3720 Section 10.3.1:
+                *
+                * "Either or both of R and W MAY be 1 when either the
+                *  Expected Data Transfer Length and/or Bidirectional Read
+                *  Expected Data Transfer Length are 0"
+                *
+                * For this case, go ahead and clear the unnecssary bits
+                * to avoid any confusion with ->data_direction.
                 */
-               if ((hdr->cdb[0] == 0x16) || (hdr->cdb[0] == 0x17)) {
-                       hdr->flags &= ~ISCSI_FLAG_CMD_READ;
-                       hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
-                       goto done;
-               }
+               hdr->flags &= ~ISCSI_FLAG_CMD_READ;
+               hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
 
-               pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
+               pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
                        " set when Expected Data Transfer Length is 0 for"
-                       " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
-               return iscsit_add_reject_cmd(cmd,
-                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
+                       " CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
        }
-done:
 
        if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
            !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
index e3318edb233dbe91b8e35f9fe1a7fff58508fb6b..1c0088fe9e99368c2dfb50b378dee6033cd42cab 100644 (file)
@@ -474,7 +474,8 @@ static ssize_t __iscsi_##prefix##_store_##name(                             \
                                                                        \
        if (!capable(CAP_SYS_ADMIN))                                    \
                return -EPERM;                                          \
-                                                                       \
+       if (count >= sizeof(auth->name))                                \
+               return -EINVAL;                                         \
        snprintf(auth->name, sizeof(auth->name), "%s", page);           \
        if (!strncmp("NULL", auth->name, 4))                            \
                auth->naf_flags &= ~flags;                              \
index 4eb93b2b6473bcce92f912908a0790485db15e85..e29279e6b577dd564e8271f95c171838ead5ca39 100644 (file)
@@ -1403,11 +1403,6 @@ old_sess_out:
 
 out:
        stop = kthread_should_stop();
-       if (!stop && signal_pending(current)) {
-               spin_lock_bh(&np->np_thread_lock);
-               stop = (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN);
-               spin_unlock_bh(&np->np_thread_lock);
-       }
        /* Wait for another socket.. */
        if (!stop)
                return 1;
@@ -1415,7 +1410,6 @@ exit:
        iscsi_stop_login_thread_timer(np);
        spin_lock_bh(&np->np_thread_lock);
        np->np_thread_state = ISCSI_NP_THREAD_EXIT;
-       np->np_thread = NULL;
        spin_unlock_bh(&np->np_thread_lock);
 
        return 0;
index 207b340498a3645231dbb2ae449e48f052e3313f..d06de84b069bb0c283495bdf09da4b3e9b96ba2f 100644 (file)
@@ -1106,6 +1106,11 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
        dev->dev_attrib.block_size = block_size;
        pr_debug("dev[%p]: SE Device block_size changed to %u\n",
                        dev, block_size);
+
+       if (dev->dev_attrib.max_bytes_per_io)
+               dev->dev_attrib.hw_max_sectors =
+                       dev->dev_attrib.max_bytes_per_io / block_size;
+
        return 0;
 }
 
index 0e34cda3271e9bb3291b06a934c1ef7136488811..78241a53b555fc5600d0a6ffe7b8d8b4e15687d0 100644 (file)
@@ -66,9 +66,8 @@ static int fd_attach_hba(struct se_hba *hba, u32 host_id)
        pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
                " Target Core Stack %s\n", hba->hba_id, FD_VERSION,
                TARGET_CORE_MOD_VERSION);
-       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic"
-               " MaxSectors: %u\n",
-               hba->hba_id, fd_host->fd_host_id, FD_MAX_SECTORS);
+       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n",
+               hba->hba_id, fd_host->fd_host_id);
 
        return 0;
 }
@@ -220,7 +219,8 @@ static int fd_configure_device(struct se_device *dev)
        }
 
        dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
-       dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
+       dev->dev_attrib.max_bytes_per_io = FD_MAX_BYTES;
+       dev->dev_attrib.hw_max_sectors = FD_MAX_BYTES / fd_dev->fd_block_size;
        dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
 
        if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
index 37ffc5bd23992a5f1e1124b2c6eba9889e7119ff..d7772c167685fecc89caf699884198b9a9d9f999 100644 (file)
@@ -7,7 +7,10 @@
 #define FD_DEVICE_QUEUE_DEPTH  32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE           512
-#define FD_MAX_SECTORS         2048
+/*
+ * Limited by the number of iovecs (2048) per vfs_[writev,readv] call
+ */
+#define FD_MAX_BYTES           8388608
 
 #define RRF_EMULATE_CDB                0x01
 #define RRF_GOT_LBA            0x02
index f697f8baec5418d13484904bf3730880f90639fd..2a573de19a9fdceea07d233f15a699be6c10c770 100644 (file)
@@ -278,7 +278,6 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
        acl->dynamic_node_acl = 1;
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
@@ -406,7 +405,6 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
@@ -658,15 +656,9 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
        spin_lock_init(&lun->lun_sep_lock);
        init_completion(&lun->lun_ref_comp);
 
-       ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
-       if (ret < 0)
-               return ret;
-
        ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
-       if (ret < 0) {
-               percpu_ref_cancel_init(&lun->lun_ref);
+       if (ret < 0)
                return ret;
-       }
 
        return 0;
 }
index 2b86f8e0fb58f965f637c82e3206f3e4d83c6e51..71630a2af42ccf5f2eb48ea79793cadca86ab5c6 100644 (file)
@@ -1855,6 +1855,9 @@ static struct console sercons = {
  */
 static int __init amiserial_console_init(void)
 {
+       if (!MACH_IS_AMIGA)
+               return -ENODEV;
+
        register_console(&sercons);
        return 0;
 }
index 7cdd1eb9406c11ccb4870560490f0c6036f92032..34aacaaae14ab9b595ea41744504c2cbc65b9ff3 100644 (file)
@@ -93,6 +93,7 @@ struct n_tty_data {
        size_t canon_head;
        size_t echo_head;
        size_t echo_commit;
+       size_t echo_mark;
        DECLARE_BITMAP(char_map, 256);
 
        /* private to n_tty_receive_overrun (single-threaded) */
@@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
 {
        ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
        ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
+       ldata->echo_mark = 0;
        ldata->line_start = 0;
 
        ldata->erasing = 0;
@@ -768,7 +770,7 @@ static size_t __process_echoes(struct tty_struct *tty)
         * data at the tail to prevent a subsequent overrun */
        while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) {
                if (echo_buf(ldata, tail) == ECHO_OP_START) {
-                       if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB)
+                       if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB)
                                tail += 3;
                        else
                                tail += 2;
@@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
        size_t head;
 
        head = ldata->echo_head;
+       ldata->echo_mark = head;
        old = ldata->echo_commit - ldata->echo_tail;
 
        /* Process committed echoes if the accumulated # of bytes
@@ -810,10 +813,12 @@ static void process_echoes(struct tty_struct *tty)
        struct n_tty_data *ldata = tty->disc_data;
        size_t echoed;
 
-       if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail)
+       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
+           ldata->echo_mark == ldata->echo_tail)
                return;
 
        mutex_lock(&ldata->output_lock);
+       ldata->echo_commit = ldata->echo_mark;
        echoed = __process_echoes(tty);
        mutex_unlock(&ldata->output_lock);
 
@@ -821,11 +826,13 @@ static void process_echoes(struct tty_struct *tty)
                tty->ops->flush_chars(tty);
 }
 
+/* NB: echo_mark and echo_head should be equivalent here */
 static void flush_echoes(struct tty_struct *tty)
 {
        struct n_tty_data *ldata = tty->disc_data;
 
-       if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head)
+       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
+           ldata->echo_commit == ldata->echo_head)
                return;
 
        mutex_lock(&ldata->output_lock);
@@ -1998,7 +2005,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
                found = 1;
 
        size = N_TTY_BUF_SIZE - tail;
-       n = (found + eol + size) & (N_TTY_BUF_SIZE - 1);
+       n = eol - tail;
+       if (n > 4096)
+               n += 4096;
+       n += found;
        c = n;
 
        if (found && read_buf(ldata, eol) == __DISABLED_CHAR) {
@@ -2243,18 +2253,19 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
                if (time)
                        timeout = time;
        }
-       mutex_unlock(&ldata->atomic_read_lock);
-       remove_wait_queue(&tty->read_wait, &wait);
+       n_tty_set_room(tty);
+       up_read(&tty->termios_rwsem);
 
+       remove_wait_queue(&tty->read_wait, &wait);
        if (!waitqueue_active(&tty->read_wait))
                ldata->minimum_to_wake = minimum;
 
+       mutex_unlock(&ldata->atomic_read_lock);
+
        __set_current_state(TASK_RUNNING);
        if (b - buf)
                retval = b - buf;
 
-       n_tty_set_room(tty);
-       up_read(&tty->termios_rwsem);
        return retval;
 }
 
index 4658e3e0ec4256d9b2e31f890ea72822abf47f93..06525f10e3641bc2140b140a50d8b994acd662d3 100644 (file)
@@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
@@ -132,7 +133,8 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writel(value, p->membase + (UART_LCR << p->regshift));
@@ -455,6 +457,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT33C4", 0 },
        { "INT33C5", 0 },
+       { "INT3434", 0 },
+       { "INT3435", 0 },
        { "80860F0A", 0 },
        { },
 };
index f3b306efaa591d518b1b894253e0714ea3cba5c6..23329918f2292b088eac724156d743784460866c 100644 (file)
@@ -41,7 +41,7 @@ config SERIAL_8250_DEPRECATED_OPTIONS
          accept kernel parameters in both forms like 8250_core.nr_uarts=4 and
          8250.nr_uarts=4. We now renamed the module back to 8250, but if
          anybody noticed in 3.7 and changed their userspace we still have to
-         keep the 8350_core.* options around until they revert the changes
+         keep the 8250_core.* options around until they revert the changes
          they already did.
 
          If 8250 is built as a module, this adds 8250_core alias instead. 
index 481b781b26e370e23fea8d2088311562c15cde87..e9d420ff39310741212eb77e194c13fca2662b18 100644 (file)
@@ -2052,6 +2052,9 @@ static int __init pmz_console_init(void)
        /* Probe ports */
        pmz_probe();
 
+       if (pmz_ports_count == 0)
+               return -ENODEV;
+
        /* TODO: Autoprobe console based on OF */
        /* pmz_console.index = i; */
        register_console(&pmz_console);
index e46e9f3f19b90d34476b60a2e21aa656fc3c8fae..f619ad5b5eaefc891b6857c03edd942492198e18 100644 (file)
@@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                        continue;
                        }
 
+#ifdef SUPPORT_SYSRQ
                        /*
                         * uart_handle_sysrq_char() doesn't work if
                         * spinlocked, for some reason
@@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                }
                                spin_lock(&port->lock);
                        }
+#endif
 
                        port->icount.rx++;
 
index 3a1a01af9a805b38b05f1833eefa80400072f4f4..c74a00ad7add80254ddf98dbaf88ed0725a540e0 100644 (file)
@@ -2086,6 +2086,7 @@ retry_open:
                        filp->f_op = &tty_fops;
                goto retry_open;
        }
+       clear_bit(TTY_HUPPED, &tty->flags);
        tty_unlock(tty);
 
 
index 22fad8ad5ac206c4cf22f820e9a4cf5c3f6cd8bd..d8a55e87877f06f3141602e4f08cdcb668c465b0 100644 (file)
@@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem)
        return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
+/*
+ * ldsem_cmpxchg() updates @*old with the last-known sem->count value.
+ * Returns 1 if count was successfully changed; @*old will have @new value.
+ * Returns 0 if count was not changed; @*old will have most recent sem->count
+ */
 static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem)
 {
-       long tmp = *old;
-       *old = atomic_long_cmpxchg(&sem->count, *old, new);
-       return *old == tmp;
+       long tmp = atomic_long_cmpxchg(&sem->count, *old, new);
+       if (tmp == *old) {
+               *old = new;
+               return 1;
+       } else {
+               *old = tmp;
+               return 0;
+       }
 }
 
 /*
index 67beb84449304d987c68a544c02b9c6e428dce1a..f7beb6eb40c714ae71309807b94b55a643501a9f 100644 (file)
@@ -653,6 +653,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
                return -EINVAL;
        mem = idev->info->mem + mi;
 
+       if (mem->addr & ~PAGE_MASK)
+               return -ENODEV;
        if (vma->vm_end - vma->vm_start > mem->size)
                return -EINVAL;
 
index 5d8981c5235e50e42776cfb9f672977c11a61ef0..6e73f8cd60e513ca44de8d6bd00fe69085e4453f 100644 (file)
@@ -642,6 +642,10 @@ 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);
+
        ret = ci_role_start(ci, ci->role);
        if (ret) {
                dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
index 59e6020ea7539e5e331364ac067c9a16f27855ba..526cd77563d8a89c29f5444901ee3ba366b1575a 100644 (file)
@@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci)
        return ret;
 
 disable_reg:
-       regulator_disable(ci->platdata->reg_vbus);
+       if (ci->platdata->reg_vbus)
+               regulator_disable(ci->platdata->reg_vbus);
 
 put_hcd:
        usb_put_hcd(hcd);
index b34c81969cba672a7e880f405f2445adf36b7e6f..69d20fbb38a26a32357cc9f5d7fc4f81efa08cca 100644 (file)
@@ -1795,9 +1795,6 @@ static int udc_start(struct ci_hdrc *ci)
        pm_runtime_no_callbacks(&ci->gadget.dev);
        pm_runtime_enable(&ci->gadget.dev);
 
-       /* Update ci->vbus_active */
-       ci_handle_vbus_change(ci);
-
        return retval;
 
 destroy_eps:
index 3e7560f004f86d7153ed3ea0eeabed09dabf6b47..e8404319ca68b93d7b1d05b881b4d1bed8d1ded8 100644 (file)
@@ -1515,6 +1515,8 @@ static int acm_reset_resume(struct usb_interface *intf)
 
 static const struct usb_device_id acm_ids[] = {
        /* quirky and broken devices */
+       { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
+       .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
index 4d387596f3f0a6e531caa1a9049a383d605091b4..0b23a8639311b182ee9e2afddcec1cb888269257 100644 (file)
@@ -854,13 +854,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on)
 {
        /* need autopm_get/put here to ensure the usbcore sees the new value */
        int rv = usb_autopm_get_interface(intf);
-       if (rv < 0)
-               goto err;
 
        intf->needs_remote_wakeup = on;
-       usb_autopm_put_interface(intf);
-err:
-       return rv;
+       if (!rv)
+               usb_autopm_put_interface(intf);
+       return 0;
 }
 
 static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
index a7c04e24ca484deb233db5dcfd995b73427c4cc0..bd9dc3504b5149b2ff5091d67bb514a92cbc0a88 100644 (file)
@@ -4832,8 +4832,9 @@ static void hub_events(void)
                                        hub->ports[i - 1]->child;
 
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
-                               if (!udev || !(portstatus &
-                                               USB_PORT_STAT_CONNECTION)) {
+                               if (!udev ||
+                                   !(portstatus & USB_PORT_STAT_CONNECTION) ||
+                                   udev->state == USB_STATE_NOTATTACHED) {
                                        status = hub_port_reset(hub, i,
                                                        NULL, HUB_BH_RESET_TIME,
                                                        true);
index 74f9cf02da070a6d1c23b643a56f76e3264fb8cd..a49217ae35333846bb76912666f0efa12bca6813 100644 (file)
@@ -455,9 +455,6 @@ static int dwc3_probe(struct platform_device *pdev)
        if (IS_ERR(regs))
                return PTR_ERR(regs);
 
-       usb_phy_set_suspend(dwc->usb2_phy, 0);
-       usb_phy_set_suspend(dwc->usb3_phy, 0);
-
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
 
@@ -488,6 +485,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err0;
        }
 
+       usb_phy_set_suspend(dwc->usb2_phy, 0);
+       usb_phy_set_suspend(dwc->usb3_phy, 0);
+
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
@@ -569,6 +569,8 @@ err2:
        dwc3_event_buffers_cleanup(dwc);
 
 err1:
+       usb_phy_set_suspend(dwc->usb2_phy, 1);
+       usb_phy_set_suspend(dwc->usb3_phy, 1);
        dwc3_core_exit(dwc);
 
 err0:
index 95f7649c71a78745692a63bafd1527daacda52e3..21a352079bc25fdd0fe33ddba1a3191b29b812f0 100644 (file)
@@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                        dep = dwc3_wIndex_to_dep(dwc, wIndex);
                        if (!dep)
                                return -EINVAL;
+                       if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
+                               break;
                        ret = __dwc3_gadget_ep_set_halt(dep, set);
                        if (ret)
                                return -EINVAL;
index 5452c0fce36074d4238e3553bb00d879d8df9ac3..02e44fcaf205e3eaf4a69e706c41d6e081c6c1e5 100644 (file)
@@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               if (dep->flags & DWC3_EP_WEDGE)
-                       return 0;
-
                ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
                        DWC3_DEPCMD_CLEARSTALL, &params);
                if (ret)
@@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                                        value ? "set" : "clear",
                                        dep->name);
                else
-                       dep->flags &= ~DWC3_EP_STALL;
+                       dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
        }
 
        return ret;
index a91e6422f93021f912042298a99cdde36362b09b..f66d96ad1f51eb96d1806187dbb564675a02b8f0 100644 (file)
@@ -682,6 +682,7 @@ config USB_CONFIGFS_PHONET
 config USB_CONFIGFS_MASS_STORAGE
        boolean "Mass storage"
        depends on USB_CONFIGFS
+       depends on BLOCK
        select USB_F_MASS_STORAGE
        help
          The Mass Storage Gadget acts as a USB Mass Storage disk drive.
index 3e7ae707f691c4b0cf4b701024d8df0af4a5bb69..2018ba1a2172d4bb26faea20c34e44653070e91f 100644 (file)
@@ -593,6 +593,7 @@ static void reset_config(struct usb_composite_dev *cdev)
                bitmap_zero(f->endpoints, 32);
        }
        cdev->config = NULL;
+       cdev->delayed_status = 0;
 }
 
 static int set_config(struct usb_composite_dev *cdev,
index 774e8b89cdb593bf951b5c82e97c169f921a6130..241fc873ffa4569fcc98a3a93ff98e3f07339d72 100644 (file)
@@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void)
 {
        struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
        if (unlikely(!ffs))
-               return 0;
+               return NULL;
 
        ENTER();
 
index a03ba2c83589ee15f9c1880d17f1aa133eb47f29..b963939088606e7e9252ec1f55d42ff9fdd1dcd3 100644 (file)
@@ -523,7 +523,7 @@ static int fsg_setup(struct usb_function *f,
                 */
                DBG(fsg, "bulk reset request\n");
                raise_exception(fsg->common, FSG_STATE_RESET);
-               return DELAYED_STATUS;
+               return USB_GADGET_DELAYED_STATUS;
 
        case US_BULK_GET_MAX_LUN:
                if (ctrl->bRequestType !=
@@ -602,13 +602,14 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
        return true;
 }
 
-static int sleep_thread(struct fsg_common *common)
+static int sleep_thread(struct fsg_common *common, bool can_freeze)
 {
        int     rc = 0;
 
        /* Wait until a signal arrives or we are woken up */
        for (;;) {
-               try_to_freeze();
+               if (can_freeze)
+                       try_to_freeze();
                set_current_state(TASK_INTERRUPTIBLE);
                if (signal_pending(current)) {
                        rc = -EINTR;
@@ -682,7 +683,7 @@ static int do_read(struct fsg_common *common)
                /* Wait for the next buffer to become available */
                bh = common->next_buffhd_to_fill;
                while (bh->state != BUF_STATE_EMPTY) {
-                       rc = sleep_thread(common);
+                       rc = sleep_thread(common, false);
                        if (rc)
                                return rc;
                }
@@ -937,7 +938,7 @@ static int do_write(struct fsg_common *common)
                }
 
                /* Wait for something to happen */
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, false);
                if (rc)
                        return rc;
        }
@@ -1504,7 +1505,7 @@ static int throw_away_data(struct fsg_common *common)
                }
 
                /* Otherwise wait for something to happen */
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -1625,7 +1626,7 @@ static int send_status(struct fsg_common *common)
        /* Wait for the next buffer to become available */
        bh = common->next_buffhd_to_fill;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -1828,7 +1829,7 @@ static int do_scsi_command(struct fsg_common *common)
        bh = common->next_buffhd_to_fill;
        common->next_buffhd_to_drain = bh;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2174,7 +2175,7 @@ static int get_next_command(struct fsg_common *common)
        /* Wait for the next buffer to become available */
        bh = common->next_buffhd_to_fill;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2193,7 +2194,7 @@ static int get_next_command(struct fsg_common *common)
 
        /* Wait for the CBW to arrive */
        while (bh->state != BUF_STATE_FULL) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2379,7 +2380,7 @@ static void handle_exception(struct fsg_common *common)
                        }
                        if (num_active == 0)
                                break;
-                       if (sleep_thread(common))
+                       if (sleep_thread(common, true))
                                return;
                }
 
@@ -2516,7 +2517,7 @@ static int fsg_main_thread(void *common_)
                }
 
                if (!common->running) {
-                       sleep_thread(common);
+                       sleep_thread(common, true);
                        continue;
                }
 
@@ -3111,7 +3112,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
                                          fsg->common->can_stall);
                if (ret)
                        return ret;
-               fsg_common_set_inquiry_string(fsg->common, 0, 0);
+               fsg_common_set_inquiry_string(fsg->common, NULL, NULL);
                ret = fsg_common_run_thread(fsg->common);
                if (ret)
                        return ret;
index 0ac6064aa3b86b6cd2376324ac9996f8ece1c0a0..409a3c45a36af1ec596ad4d9bf2c117c9f493444 100644 (file)
@@ -54,6 +54,7 @@
  */
 #ifdef CONFIG_ARCH_PXA
 #include <mach/pxa25x-udc.h>
+#include <mach/hardware.h>
 #endif
 
 #ifdef CONFIG_ARCH_LUBBOCK
index 9875d9c0823f7c554744a40acb0a70897dde0bc6..e20bc109fdd70f43eec9e1572d3fa8f75e6ba423 100644 (file)
@@ -1180,6 +1180,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
 }
 
 static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
+static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
 
 /**
  * s3c_hsotg_process_control - process a control request
@@ -1221,6 +1222,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
        if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
                switch (ctrl->bRequest) {
                case USB_REQ_SET_ADDRESS:
+                       s3c_hsotg_disconnect(hsotg);
                        dcfg = readl(hsotg->regs + DCFG);
                        dcfg &= ~DCFG_DevAddr_MASK;
                        dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
@@ -1245,7 +1247,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
        /* as a fallback, try delivering it to the driver to deal with */
 
        if (ret == 0 && hsotg->driver) {
+               spin_unlock(&hsotg->lock);
                ret = hsotg->driver->setup(&hsotg->gadget, ctrl);
+               spin_lock(&hsotg->lock);
                if (ret < 0)
                        dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
        }
@@ -1308,10 +1312,12 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
                return;
        }
 
+       spin_lock(&hsotg->lock);
        if (req->actual == 0)
                s3c_hsotg_enqueue_setup(hsotg);
        else
                s3c_hsotg_process_control(hsotg, req->buf);
+       spin_unlock(&hsotg->lock);
 }
 
 /**
@@ -2533,7 +2539,6 @@ irq_retry:
                writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
 
                call_gadget(hsotg, suspend);
-               s3c_hsotg_disconnect(hsotg);
        }
 
        if (gintsts & GINTSTS_WkUpInt) {
index c74c2fdbd56eda5683a13995a96b6221711c30ef..70c891469f574ebd1d7719fc05bcf838d1d6e3cb 100644 (file)
@@ -119,10 +119,6 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
        return curlun->filp != NULL;
 }
 
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE    256
-#define DELAYED_STATUS (EP0_BUFSIZE + 999)     /* An impossibly large value */
-
 /* Default size of buffer length. */
 #define FSG_BUFLEN     ((u32)16384)
 
index 6c3d7950d2a9e56d5231938493127c0964f04221..0f8aad78b54f7095a26b6e413a22ff5ae1e016df 100644 (file)
@@ -370,7 +370,7 @@ err:
        return -ENOMEM;
 }
 
-void bot_cleanup_old_alt(struct f_uas *fu)
+static void bot_cleanup_old_alt(struct f_uas *fu)
 {
        if (!(fu->flags & USBG_ENABLED))
                return;
index 0dd07ae1555ddf066312e0ff4e8182a02f27a3d6..f49b0b61ecc8163941447e8ba5b719982951531e 100644 (file)
@@ -91,17 +91,17 @@ static struct usb_zero_options gzero_options = {
  * functional coverage for the "USBCV" test harness from USB-IF.
  * It's always set if OTG mode is enabled.
  */
-unsigned autoresume = DEFAULT_AUTORESUME;
+static unsigned autoresume = DEFAULT_AUTORESUME;
 module_param(autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
 
 /* Maximum Autoresume time */
-unsigned max_autoresume;
+static unsigned max_autoresume;
 module_param(max_autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup");
 
 /* Interval between two remote wakeups */
-unsigned autoresume_interval_ms;
+static unsigned autoresume_interval_ms;
 module_param(autoresume_interval_ms, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume_interval_ms,
                "milliseconds to increase successive wakeup delays");
index 418444ebb1b8bb1fd1862fc9233c7562c5c40d81..8c356af79409f9ef4647d141bc6aa5146791496b 100644 (file)
@@ -136,23 +136,27 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        struct ohci_hcd *ohci;
        int retval;
        struct usb_hcd *hcd = NULL;
-
-       if (pdev->num_resources != 2) {
-               pr_debug("hcd probe: invalid num_resources");
-               return -ENODEV;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int irq;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_dbg(dev, "hcd probe: missing memory resource\n");
+               return -ENXIO;
        }
 
-       if ((pdev->resource[0].flags != IORESOURCE_MEM)
-                       || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-               pr_debug("hcd probe: invalid resource type\n");
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_dbg(dev, "hcd probe: missing irq resource\n");
+               return irq;
        }
 
        hcd = usb_create_hcd(driver, &pdev->dev, "at91");
        if (!hcd)
                return -ENOMEM;
-       hcd->rsrc_start = pdev->resource[0].start;
-       hcd->rsrc_len = resource_size(&pdev->resource[0]);
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len = resource_size(res);
 
        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
                pr_debug("request_mem_region failed\n");
@@ -199,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        ohci->num_ports = board->ports;
        at91_start_hc(pdev);
 
-       retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval == 0)
                return retval;
 
index e89ac4d4b87e5be4d4a134e389dbdfa20931eb9c..9b7435f0dcd6b432f0c7fa9fcc096817e7141712 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index b8dffd59eb256e52786328e5e4f1919846a80d9c..73f5208714a4a4d8270bd85acd1ec625fb9abf71 100644 (file)
@@ -128,7 +128,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * any other sleep) on Haswell machines with LPT and LPT-LP
                 * with the new Intel BIOS
                 */
-               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+               /* Limit the quirk to only known vendors, as this triggers
+                * yet another BIOS bug on some other machines
+                * https://bugzilla.kernel.org/show_bug.cgi?id=66171
+                */
+               if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
+                       xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
index 1e2f3f4958436fb120b81d41632ad7e7c76fb5b5..53c2e296467fcabbb8139361f6b422829f97cae4 100644 (file)
@@ -2973,8 +2973,58 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
        }
 
        while (1) {
-               if (room_on_ring(xhci, ep_ring, num_trbs))
-                       break;
+               if (room_on_ring(xhci, ep_ring, num_trbs)) {
+                       union xhci_trb *trb = ep_ring->enqueue;
+                       unsigned int usable = ep_ring->enq_seg->trbs +
+                                       TRBS_PER_SEGMENT - 1 - trb;
+                       u32 nop_cmd;
+
+                       /*
+                        * Section 4.11.7.1 TD Fragments states that a link
+                        * TRB must only occur at the boundary between
+                        * data bursts (eg 512 bytes for 480M).
+                        * While it is possible to split a large fragment
+                        * we don't know the size yet.
+                        * Simplest solution is to fill the trb before the
+                        * LINK with nop commands.
+                        */
+                       if (num_trbs == 1 || num_trbs <= usable || usable == 0)
+                               break;
+
+                       if (ep_ring->type != TYPE_BULK)
+                               /*
+                                * While isoc transfers might have a buffer that
+                                * crosses a 64k boundary it is unlikely.
+                                * Since we can't add NOPs without generating
+                                * gaps in the traffic just hope it never
+                                * happens at the end of the ring.
+                                * This could be fixed by writing a LINK TRB
+                                * instead of the first NOP - however the
+                                * TRB_TYPE_LINK_LE32() calls would all need
+                                * changing to check the ring length.
+                                */
+                               break;
+
+                       if (num_trbs >= TRBS_PER_SEGMENT) {
+                               xhci_err(xhci, "Too many fragments %d, max %d\n",
+                                               num_trbs, TRBS_PER_SEGMENT - 1);
+                               return -ENOMEM;
+                       }
+
+                       nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) |
+                                       ep_ring->cycle_state);
+                       ep_ring->num_trbs_free -= usable;
+                       do {
+                               trb->generic.field[0] = 0;
+                               trb->generic.field[1] = 0;
+                               trb->generic.field[2] = 0;
+                               trb->generic.field[3] = nop_cmd;
+                               trb++;
+                       } while (--usable);
+                       ep_ring->enqueue = trb;
+                       if (room_on_ring(xhci, ep_ring, num_trbs))
+                               break;
+               }
 
                if (ep_ring == xhci->cmd_ring) {
                        xhci_err(xhci, "Do not support expand command ring\n");
index 0a43329569d178de72a5c8ee619e7206c360c51c..4d4499b8044971a8db410579f7965e9b6d862c38 100644 (file)
@@ -1809,7 +1809,6 @@ static void musb_free(struct musb *musb)
                        disable_irq_wake(musb->nIrq);
                free_irq(musb->nIrq, musb);
        }
-       cancel_work_sync(&musb->irq_work);
 
        musb_host_free(musb);
 }
@@ -1896,6 +1895,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_platform_disable(musb);
        musb_generic_disable(musb);
 
+       /* Init IRQ workqueue before request_irq */
+       INIT_WORK(&musb->irq_work, musb_irq_work);
+
        /* setup musb parts of the core (especially endpoints) */
        status = musb_core_init(plat->config->multipoint
                        ? MUSB_CONTROLLER_MHDRC
@@ -1905,9 +1907,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
 
-       /* Init IRQ workqueue before request_irq */
-       INIT_WORK(&musb->irq_work, musb_irq_work);
-
        /* attach to the IRQ */
        if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
                dev_err(dev, "request_irq %d failed!\n", nIrq);
@@ -1981,6 +1980,7 @@ fail4:
        musb_host_cleanup(musb);
 
 fail3:
+       cancel_work_sync(&musb->irq_work);
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 fail2_5:
@@ -2043,6 +2043,7 @@ static int musb_remove(struct platform_device *pdev)
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 
+       cancel_work_sync(&musb->irq_work);
        musb_free(musb);
        device_init_wakeup(dev, 0);
        return 0;
index ff9d6de2b7465c949d54ae4801108a3800f4be3f..a12bd30401e076fe0e502789e300c05ecc770bb1 100644 (file)
@@ -38,6 +38,7 @@ struct cppi41_dma_channel {
        u32 prog_len;
        u32 transferred;
        u32 packet_sz;
+       struct list_head tx_check;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -47,6 +48,8 @@ struct cppi41_dma_controller {
        struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS];
        struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS];
        struct musb *musb;
+       struct hrtimer early_tx;
+       struct list_head early_tx_list;
        u32 rx_mode;
        u32 tx_mode;
        u32 auto_req;
@@ -96,31 +99,27 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
        cppi41_channel->usb_toggle = toggle;
 }
 
-static void cppi41_dma_callback(void *private_data)
+static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
 {
-       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 musb *musb = hw_ep->musb;
-       unsigned long flags;
-       struct dma_tx_state txstate;
-       u32 transferred;
+       u8              epnum = hw_ep->epnum;
+       struct musb     *musb = hw_ep->musb;
+       void __iomem    *epio = musb->endpoints[epnum].regs;
+       u16             csr;
 
-       spin_lock_irqsave(&musb->lock, flags);
+       csr = musb_readw(epio, MUSB_TXCSR);
+       if (csr & MUSB_TXCSR_TXPKTRDY)
+               return false;
+       return true;
+}
 
-       dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
-                       &txstate);
-       transferred = cppi41_channel->prog_len - txstate.residue;
-       cppi41_channel->transferred += transferred;
+static void cppi41_dma_callback(void *private_data);
 
-       dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
-               hw_ep->epnum, cppi41_channel->transferred,
-               cppi41_channel->total_len);
+static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
+{
+       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+       struct musb *musb = hw_ep->musb;
 
-       update_rx_toggle(cppi41_channel);
-
-       if (cppi41_channel->transferred == cppi41_channel->total_len ||
-                       transferred < cppi41_channel->packet_sz) {
+       if (!cppi41_channel->prog_len) {
 
                /* done, complete */
                cppi41_channel->channel.actual_len =
@@ -150,13 +149,11 @@ static void cppi41_dma_callback(void *private_data)
                                remain_bytes,
                                direction,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (WARN_ON(!dma_desc)) {
-                       spin_unlock_irqrestore(&musb->lock, flags);
+               if (WARN_ON(!dma_desc))
                        return;
-               }
 
                dma_desc->callback = cppi41_dma_callback;
-               dma_desc->callback_param = channel;
+               dma_desc->callback_param = &cppi41_channel->channel;
                cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
                dma_async_issue_pending(dc);
 
@@ -166,6 +163,117 @@ static void cppi41_dma_callback(void *private_data)
                        musb_writew(epio, MUSB_RXCSR, csr);
                }
        }
+}
+
+static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
+{
+       struct cppi41_dma_controller *controller;
+       struct cppi41_dma_channel *cppi41_channel, *n;
+       struct musb *musb;
+       unsigned long flags;
+       enum hrtimer_restart ret = HRTIMER_NORESTART;
+
+       controller = container_of(timer, struct cppi41_dma_controller,
+                       early_tx);
+       musb = controller->musb;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list,
+                       tx_check) {
+               bool empty;
+               struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+
+               empty = musb_is_tx_fifo_empty(hw_ep);
+               if (empty) {
+                       list_del_init(&cppi41_channel->tx_check);
+                       cppi41_trans_done(cppi41_channel);
+               }
+       }
+
+       if (!list_empty(&controller->early_tx_list)) {
+               ret = HRTIMER_RESTART;
+               hrtimer_forward_now(&controller->early_tx,
+                               ktime_set(0, 150 * NSEC_PER_USEC));
+       }
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return ret;
+}
+
+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 musb *musb = hw_ep->musb;
+       unsigned long flags;
+       struct dma_tx_state txstate;
+       u32 transferred;
+       bool empty;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
+                       &txstate);
+       transferred = cppi41_channel->prog_len - txstate.residue;
+       cppi41_channel->transferred += transferred;
+
+       dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
+               hw_ep->epnum, cppi41_channel->transferred,
+               cppi41_channel->total_len);
+
+       update_rx_toggle(cppi41_channel);
+
+       if (cppi41_channel->transferred == cppi41_channel->total_len ||
+                       transferred < cppi41_channel->packet_sz)
+               cppi41_channel->prog_len = 0;
+
+       empty = musb_is_tx_fifo_empty(hw_ep);
+       if (empty) {
+               cppi41_trans_done(cppi41_channel);
+       } else {
+               struct cppi41_dma_controller *controller;
+               /*
+                * 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 (musb->g.speed == USB_SPEED_HIGH) {
+                       unsigned wait = 25;
+
+                       do {
+                               empty = musb_is_tx_fifo_empty(hw_ep);
+                               if (empty)
+                                       break;
+                               wait--;
+                               if (!wait)
+                                       break;
+                               udelay(1);
+                       } while (1);
+
+                       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_active(&controller->early_tx)) {
+                       hrtimer_start_range_ns(&controller->early_tx,
+                               ktime_set(0, 140 * NSEC_PER_USEC),
+                               40 * NSEC_PER_USEC,
+                               HRTIMER_MODE_REL);
+               }
+       }
+out:
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
@@ -364,6 +472,8 @@ static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
                WARN_ON(1);
                return 1;
        }
+       if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK)
+               return 0;
        if (cppi41_channel->is_tx)
                return 1;
        /* AM335x Advisory 1.0.13. No workaround for device RX mode */
@@ -388,6 +498,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
        if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
                return 0;
 
+       list_del_init(&cppi41_channel->tx_check);
        if (is_tx) {
                csr = musb_readw(epio, MUSB_TXCSR);
                csr &= ~MUSB_TXCSR_DMAENAB;
@@ -495,6 +606,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
                cppi41_channel->controller = controller;
                cppi41_channel->port_num = port;
                cppi41_channel->is_tx = is_tx;
+               INIT_LIST_HEAD(&cppi41_channel->tx_check);
 
                musb_dma = &cppi41_channel->channel;
                musb_dma->private_data = cppi41_channel;
@@ -520,6 +632,7 @@ void dma_controller_destroy(struct dma_controller *c)
        struct cppi41_dma_controller *controller = container_of(c,
                        struct cppi41_dma_controller, controller);
 
+       hrtimer_cancel(&controller->early_tx);
        cppi41_dma_controller_stop(controller);
        kfree(controller);
 }
@@ -539,6 +652,9 @@ struct dma_controller *dma_controller_create(struct musb *musb,
        if (!controller)
                goto kzalloc_fail;
 
+       hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       controller->early_tx.function = cppi41_recheck_tx_req;
+       INIT_LIST_HEAD(&controller->early_tx_list);
        controller->musb = musb;
 
        controller->controller.channel_alloc = cppi41_dma_channel_allocate;
index d2d3a173b31503b54f9071e9af48f4878567856f..32fb057c03f58e25f401bdb49755e2cdc2637e86 100644 (file)
@@ -1796,7 +1796,11 @@ int musb_gadget_setup(struct musb *musb)
 
        /* this "gadget" abstracts/virtualizes the controller */
        musb->g.name = musb_driver_name;
+#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE)
        musb->g.is_otg = 1;
+#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET)
+       musb->g.is_otg = 0;
+#endif
 
        musb_g_init_endpoints(musb);
 
index 08e2f39027ec00ae0a7c5ae07b46fdd1cdbfae8f..2b41c636a52a7a1ecf3ae0e3df622d141307c038 100644 (file)
@@ -19,8 +19,9 @@ config AB8500_USB
          in host mode, low speed.
 
 config FSL_USB2_OTG
-       bool "Freescale USB OTG Transceiver Driver"
+       tristate "Freescale USB OTG Transceiver Driver"
        depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
+       depends on USB
        select USB_OTG
        select USB_PHY
        help
@@ -29,6 +30,7 @@ config FSL_USB2_OTG
 config ISP1301_OMAP
        tristate "Philips ISP1301 with OMAP OTG"
        depends on I2C && ARCH_OMAP_OTG
+       depends on USB
        select USB_PHY
        help
          If you say yes here you get support for the Philips ISP1301
index 6370e50649d7f732c640fd65879c26d82ec5f994..0e3c60cb669a63c7a1d1bb7bd673f212f854c425 100644 (file)
@@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
                return am_phy->id;
        }
 
-       ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
-                       USB_PHY_TYPE_USB2, 0, false);
+       ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL);
        if (ret)
                return ret;
 
@@ -66,8 +65,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, am_phy);
 
        return 0;
-
-       return ret;
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
index fce3a9e9bb5d282ff6b1a64492ad6a55c90e654f..aa6d37b3378ad65ff26e336031173a9ae52d2287 100644 (file)
@@ -48,8 +48,9 @@ void usb_nop_xceiv_register(void)
        if (pd)
                return;
        pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
-       if (!pd) {
+       if (IS_ERR(pd)) {
                pr_err("Unable to register generic usb transceiver\n");
+               pd = NULL;
                return;
        }
 }
@@ -150,10 +151,40 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 }
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc)
+               struct usb_phy_gen_xceiv_platform_data *pdata)
 {
+       enum usb_phy_type type = USB_PHY_TYPE_USB2;
        int err;
 
+       u32 clk_rate = 0;
+       bool needs_vcc = false;
+
+       nop->reset_active_low = true;   /* default behaviour */
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+               enum of_gpio_flags flags = 0;
+
+               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+                       clk_rate = 0;
+
+               needs_vcc = of_property_read_bool(node, "vcc-supply");
+               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
+                                                               0, &flags);
+               if (nop->gpio_reset == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+       } else if (pdata) {
+               type = pdata->type;
+               clk_rate = pdata->clk_rate;
+               needs_vcc = pdata->needs_vcc;
+               nop->gpio_reset = pdata->gpio_reset;
+       } else {
+               nop->gpio_reset = -1;
+       }
+
        nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
                        GFP_KERNEL);
        if (!nop->phy.otg)
@@ -218,43 +249,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
 static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct usb_phy_gen_xceiv_platform_data *pdata =
-                       dev_get_platdata(&pdev->dev);
        struct usb_phy_gen_xceiv        *nop;
-       enum usb_phy_type       type = USB_PHY_TYPE_USB2;
        int err;
-       u32 clk_rate = 0;
-       bool needs_vcc = false;
 
        nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
        if (!nop)
                return -ENOMEM;
 
-       nop->reset_active_low = true;   /* default behaviour */
-
-       if (dev->of_node) {
-               struct device_node *node = dev->of_node;
-               enum of_gpio_flags flags;
-
-               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
-                       clk_rate = 0;
-
-               needs_vcc = of_property_read_bool(node, "vcc-supply");
-               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
-                                                               0, &flags);
-               if (nop->gpio_reset == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
-
-       } else if (pdata) {
-               type = pdata->type;
-               clk_rate = pdata->clk_rate;
-               needs_vcc = pdata->needs_vcc;
-               nop->gpio_reset = pdata->gpio_reset;
-       }
-
-       err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc);
+       err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev));
        if (err)
                return err;
 
@@ -271,8 +273,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, nop);
 
        return 0;
-
-       return err;
 }
 
 static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
index d2a220d81734ad5be296f56c3b416aa321bfb63e..38a81f307b8220bc5dfc81487a9fb420e397ccd1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PHY_GENERIC_H_
 #define _PHY_GENERIC_H_
 
+#include <linux/usb/usb_phy_gen_xceiv.h>
+
 struct usb_phy_gen_xceiv {
        struct usb_phy phy;
        struct device *dev;
@@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy);
 void usb_gen_phy_shutdown(struct usb_phy *phy);
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc);
+               struct usb_phy_gen_xceiv_platform_data *pdata);
 
 #endif
index fdd33b44dbd31b929eb13a2c0bd138570ccebc37..545844b7e7962f809f33812d9167f039b5fbc8d1 100644 (file)
@@ -164,7 +164,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 
        mxs_phy->clk = clk;
 
-       platform_set_drvdata(pdev, &mxs_phy->phy);
+       platform_set_drvdata(pdev, mxs_phy);
 
        ret = usb_add_phy_dev(&mxs_phy->phy);
        if (ret)
index a99a6953f11cc1988272b9ae2d4e917073eb458f..db3ab34cddb4cbc6be6df4e66596b11186235477 100644 (file)
@@ -107,10 +107,10 @@ static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv)
        clk_prepare_enable(priv->clk);
 
        /* Set USB channels in the USBHS UGCTRL2 register */
-       val = ioread32(priv->base);
+       val = ioread32(priv->base + USBHS_UGCTRL2_REG);
        val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS);
        val |= priv->ugctrl2;
-       iowrite32(val, priv->base);
+       iowrite32(val, priv->base + USBHS_UGCTRL2_REG);
 }
 
 /* Shutdown USB channels */
index 82232acf1ab61b17cfbe9d084c3ed2188d554b18..bbe4f8e6e8d7492be10cc54cfe2f37e8001f2db6 100644 (file)
@@ -876,7 +876,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
 
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                resource_size(res));
-       if (!tegra_phy->regs) {
+       if (!tegra_phy->pad_regs) {
                dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
                return -ENOMEM;
        }
index 30e8a61552d4d0526d999c0b49651593f04a5530..bad57ce77ba508e0f6ff8c07fa516e9477606a3c 100644 (file)
@@ -127,7 +127,8 @@ static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
 
 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 {
-       u8 data, ret = 0;
+       u8 data;
+       int ret;
 
        ret = twl_i2c_read_u8(module, &data, address);
        if (ret >= 0)
index 9ced8937a8f3a699dad340e1e9ea62c9d706dc69..fb0d537435eb221019babe694aafefd25b9e90cc 100644 (file)
@@ -2123,6 +2123,20 @@ static void ftdi_set_termios(struct tty_struct *tty,
                termios->c_cflag |= CRTSCTS;
        }
 
+       /*
+        * All FTDI UART chips are limited to CS7/8. We won't pretend to
+        * support CS5/6 and revert the CSIZE setting instead.
+        */
+       if ((C_CSIZE(tty) != CS8) && (C_CSIZE(tty) != CS7)) {
+               dev_warn(ddev, "requested CSIZE setting not supported\n");
+
+               termios->c_cflag &= ~CSIZE;
+               if (old_termios)
+                       termios->c_cflag |= old_termios->c_cflag & CSIZE;
+               else
+                       termios->c_cflag |= CS8;
+       }
+
        cflag = termios->c_cflag;
 
        if (!old_termios)
@@ -2159,19 +2173,16 @@ no_skip:
        } else {
                urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
        }
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS7:
-                       urb_value |= 7;
-                       dev_dbg(ddev, "Setting CS7\n");
-                       break;
-               case CS8:
-                       urb_value |= 8;
-                       dev_dbg(ddev, "Setting CS8\n");
-                       break;
-               default:
-                       dev_err(ddev, "CSIZE was set but not CS7-CS8\n");
-               }
+       switch (cflag & CSIZE) {
+       case CS7:
+               urb_value |= 7;
+               dev_dbg(ddev, "Setting CS7\n");
+               break;
+       default:
+       case CS8:
+               urb_value |= 8;
+               dev_dbg(ddev, "Setting CS8\n");
+               break;
        }
 
        /* This is needed by the break command since it uses the same command
index 2b01ec8651c296e3f016bf2421040da6f1bbbc98..b63ce023f96f1ab7284e218ca68219da5f952440 100644 (file)
@@ -173,16 +173,8 @@ retry:
                clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
                return result;
        }
-       /*
-        * Try sending off another urb, unless called from completion handler
-        * (in which case there will be no free urb or no data).
-        */
-       if (mem_flags != GFP_ATOMIC)
-               goto retry;
 
-       clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
-
-       return 0;
+       goto retry;     /* try sending off another urb */
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_start);
 
@@ -208,7 +200,7 @@ int usb_serial_generic_write(struct tty_struct *tty,
                return 0;
 
        count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
-       result = usb_serial_generic_write_start(port, GFP_KERNEL);
+       result = usb_serial_generic_write_start(port, GFP_ATOMIC);
        if (result)
                return result;
 
index e5bdd987b9e8f7e260fc95c48b142742026999fa..a69da83604c03da3219c2340264cff08b456a404 100644 (file)
@@ -1813,25 +1813,25 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
        iflag = tty->termios.c_iflag;
 
        /* Change the number of bits */
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       lData = LCR_BITS_5;
-                       break;
+       switch (cflag & CSIZE) {
+       case CS5:
+               lData = LCR_BITS_5;
+               break;
 
-               case CS6:
-                       lData = LCR_BITS_6;
-                       break;
+       case CS6:
+               lData = LCR_BITS_6;
+               break;
 
-               case CS7:
-                       lData = LCR_BITS_7;
-                       break;
-               default:
-               case CS8:
-                       lData = LCR_BITS_8;
-                       break;
-               }
+       case CS7:
+               lData = LCR_BITS_7;
+               break;
+
+       default:
+       case CS8:
+               lData = LCR_BITS_8;
+               break;
        }
+
        /* Change the Parity bit */
        if (cflag & PARENB) {
                if (cflag & PARODD) {
index c3d94853b4ab7a2dd13d8f6dea0009f55795ba56..cc7a24154490b29ebb39d4b9d3e72785c4320285 100644 (file)
@@ -85,6 +85,7 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4505                   0x1464
 #define HUAWEI_PRODUCT_K3765                   0x1465
 #define HUAWEI_PRODUCT_K4605                   0x14C6
+#define HUAWEI_PRODUCT_E173S6                  0x1C07
 
 #define QUANTA_VENDOR_ID                       0x0408
 #define QUANTA_PRODUCT_Q101                    0xEA02
@@ -250,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
 #define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AC2726                     0xfff1
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -572,6 +574,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) },
@@ -634,6 +638,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) },
@@ -688,6 +696,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
@@ -742,6 +754,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) },
@@ -796,6 +812,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) },
@@ -850,6 +870,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) },
@@ -904,6 +928,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) },
@@ -1426,6 +1454,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
index 1e6de4cd079d6a2c0e3b4b3c7679d6145bcf6f2c..1e3318dfa1cb569fcbd78ed2079ef026f33a8d16 100644 (file)
@@ -361,23 +361,21 @@ static void pl2303_set_termios(struct tty_struct *tty,
                            0, 0, buf, 7, 100);
        dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);
 
-       if (C_CSIZE(tty)) {
-               switch (C_CSIZE(tty)) {
-               case CS5:
-                       buf[6] = 5;
-                       break;
-               case CS6:
-                       buf[6] = 6;
-                       break;
-               case CS7:
-                       buf[6] = 7;
-                       break;
-               default:
-               case CS8:
-                       buf[6] = 8;
-               }
-               dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
+       switch (C_CSIZE(tty)) {
+       case CS5:
+               buf[6] = 5;
+               break;
+       case CS6:
+               buf[6] = 6;
+               break;
+       case CS7:
+               buf[6] = 7;
+               break;
+       default:
+       case CS8:
+               buf[6] = 8;
        }
+       dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
 
        /* For reference buf[0]:buf[3] baud rate value */
        pl2303_encode_baudrate(tty, port, &buf[0]);
index 4abac28b5992a1f128005f5f7df103118a39b081..5b793c352267751ecd43cce1c7fae9e5a7fac624 100644 (file)
@@ -348,22 +348,20 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
        }
 
        /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       buf[1] |= SET_UART_FORMAT_SIZE_5;
-                       break;
-               case CS6:
-                       buf[1] |= SET_UART_FORMAT_SIZE_6;
-                       break;
-               case CS7:
-                       buf[1] |= SET_UART_FORMAT_SIZE_7;
-                       break;
-               default:
-               case CS8:
-                       buf[1] |= SET_UART_FORMAT_SIZE_8;
-                       break;
-               }
+       switch (cflag & CSIZE) {
+       case CS5:
+               buf[1] |= SET_UART_FORMAT_SIZE_5;
+               break;
+       case CS6:
+               buf[1] |= SET_UART_FORMAT_SIZE_6;
+               break;
+       case CS7:
+               buf[1] |= SET_UART_FORMAT_SIZE_7;
+               break;
+       default:
+       case CS8:
+               buf[1] |= SET_UART_FORMAT_SIZE_8;
+               break;
        }
 
        /* Set Stop bit2 : 0:1bit 1:2bit */
index fca4c752a4ed233199d82a787c0ebfbfff32e71c..eae2c873b39ff7dbb2ecd8d7624a1e2aec14e8ca 100644 (file)
@@ -281,8 +281,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x19d2, 0xfffd) },
        { USB_DEVICE(0x19d2, 0xfffc) },
        { USB_DEVICE(0x19d2, 0xfffb) },
-       /* AC2726, AC8710_V3 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
+       /* AC8710_V3 */
        { USB_DEVICE(0x19d2, 0xfff6) },
        { USB_DEVICE(0x19d2, 0xfff7) },
        { USB_DEVICE(0x19d2, 0xfff8) },
index e538b72c4e3af2d09153614952e12101eac03520..f14e7929ba2278dae601788ab4f07ae657e2e2bb 100644 (file)
@@ -97,18 +97,12 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work);
 
 static void wusb_dev_free(struct wusb_dev *wusb_dev)
 {
-       if (wusb_dev) {
-               kfree(wusb_dev->set_gtk_req);
-               usb_free_urb(wusb_dev->set_gtk_urb);
-               kfree(wusb_dev);
-       }
+       kfree(wusb_dev);
 }
 
 static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 {
        struct wusb_dev *wusb_dev;
-       struct urb *urb;
-       struct usb_ctrlrequest *req;
 
        wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL);
        if (wusb_dev == NULL)
@@ -118,22 +112,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 
        INIT_WORK(&wusb_dev->devconnect_acked_work, wusbhc_devconnect_acked_work);
 
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (urb == NULL)
-               goto err;
-       wusb_dev->set_gtk_urb = urb;
-
-       req = kmalloc(sizeof(*req), GFP_KERNEL);
-       if (req == NULL)
-               goto err;
-       wusb_dev->set_gtk_req = req;
-
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-       req->bRequest = USB_REQ_SET_DESCRIPTOR;
-       req->wValue = cpu_to_le16(USB_DT_KEY << 8 | wusbhc->gtk_index);
-       req->wIndex = 0;
-       req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength);
-
        return wusb_dev;
 err:
        wusb_dev_free(wusb_dev);
@@ -411,9 +389,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
 /*
  * Refresh the list of keep alives to emit in the MMC
  *
- * Some devices don't respond to keep alives unless they've been
- * authenticated, so skip unauthenticated devices.
- *
  * We only publish the first four devices that have a coming timeout
  * condition. Then when we are done processing those, we go for the
  * next ones. We ignore the ones that have timed out already (they'll
@@ -448,7 +423,7 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc)
 
                if (wusb_dev == NULL)
                        continue;
-               if (wusb_dev->usb_dev == NULL || !wusb_dev->usb_dev->authenticated)
+               if (wusb_dev->usb_dev == NULL)
                        continue;
 
                if (time_after(jiffies, wusb_dev->entry_ts + tt)) {
@@ -524,11 +499,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr)
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
+static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr)
 {
+       struct wusb_dev *wusb_dev;
+
        mutex_lock(&wusbhc->mutex);
-       wusb_dev->entry_ts = jiffies;
-       __wusbhc_keep_alive(wusbhc);
+       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+       if (wusb_dev == NULL) {
+               dev_dbg(wusbhc->dev, "ignoring DN_Alive from unconnected device %02x\n",
+                       srcaddr);
+       } else {
+               wusb_dev->entry_ts = jiffies;
+               __wusbhc_keep_alive(wusbhc);
+       }
        mutex_unlock(&wusbhc->mutex);
 }
 
@@ -582,14 +565,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
+static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr)
 {
        struct device *dev = wusbhc->dev;
-
-       dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr);
+       struct wusb_dev *wusb_dev;
 
        mutex_lock(&wusbhc->mutex);
-       __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx));
+       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+       if (wusb_dev == NULL) {
+               dev_dbg(dev, "ignoring DN DISCONNECT from unconnected device %02x\n",
+                       srcaddr);
+       } else {
+               dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n",
+                       wusb_dev->addr);
+               __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc,
+                       wusb_dev->port_idx));
+       }
        mutex_unlock(&wusbhc->mutex);
 }
 
@@ -611,30 +602,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
                      struct wusb_dn_hdr *dn_hdr, size_t size)
 {
        struct device *dev = wusbhc->dev;
-       struct wusb_dev *wusb_dev;
 
        if (size < sizeof(struct wusb_dn_hdr)) {
                dev_err(dev, "DN data shorter than DN header (%d < %d)\n",
                        (int)size, (int)sizeof(struct wusb_dn_hdr));
                return;
        }
-
-       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
-       if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) {
-               dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n",
-                       dn_hdr->bType, srcaddr);
-               return;
-       }
-
        switch (dn_hdr->bType) {
        case WUSB_DN_CONNECT:
                wusbhc_handle_dn_connect(wusbhc, dn_hdr, size);
                break;
        case WUSB_DN_ALIVE:
-               wusbhc_handle_dn_alive(wusbhc, wusb_dev);
+               wusbhc_handle_dn_alive(wusbhc, srcaddr);
                break;
        case WUSB_DN_DISCONNECT:
-               wusbhc_handle_dn_disconnect(wusbhc, wusb_dev);
+               wusbhc_handle_dn_disconnect(wusbhc, srcaddr);
                break;
        case WUSB_DN_MASAVAILCHANGED:
        case WUSB_DN_RWAKE:
index dd88441c8f7891e0d242e1107d6ff585a30999e4..4c40d0dbf53d45c35ae5b05798f1f09566ffc29e 100644 (file)
 #include <linux/export.h>
 #include "wusbhc.h"
 
-static void wusbhc_set_gtk_callback(struct urb *urb);
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work);
+static void wusbhc_gtk_rekey_work(struct work_struct *work);
 
 int wusbhc_sec_create(struct wusbhc *wusbhc)
 {
        wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data);
        wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY;
        wusbhc->gtk.descr.bReserved = 0;
+       wusbhc->gtk_index = 0;
 
-       wusbhc->gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK,
-                                          WUSB_KEY_INDEX_ORIGINATOR_HOST);
-
-       INIT_WORK(&wusbhc->gtk_rekey_done_work, wusbhc_gtk_rekey_done_work);
+       INIT_WORK(&wusbhc->gtk_rekey_work, wusbhc_gtk_rekey_work);
 
        return 0;
 }
@@ -113,7 +110,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
        wusbhc_generate_gtk(wusbhc);
 
        result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
-                                &wusbhc->gtk.descr.bKeyData, key_size);
+                               &wusbhc->gtk.descr.bKeyData, key_size);
        if (result < 0)
                dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n",
                        result);
@@ -129,7 +126,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
  */
 void wusbhc_sec_stop(struct wusbhc *wusbhc)
 {
-       cancel_work_sync(&wusbhc->gtk_rekey_done_work);
+       cancel_work_sync(&wusbhc->gtk_rekey_work);
 }
 
 
@@ -185,12 +182,14 @@ static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value)
 static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
        struct usb_device *usb_dev = wusb_dev->usb_dev;
+       u8 key_index = wusb_key_index(wusbhc->gtk_index,
+               WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST);
 
        return usb_control_msg(
                usb_dev, usb_sndctrlpipe(usb_dev, 0),
                USB_REQ_SET_DESCRIPTOR,
                USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-               USB_DT_KEY << 8 | wusbhc->gtk_index, 0,
+               USB_DT_KEY << 8 | key_index, 0,
                &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
                1000);
 }
@@ -520,24 +519,55 @@ error_kzalloc:
  * Once all connected and authenticated devices have received the new
  * GTK, switch the host to using it.
  */
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work)
+static void wusbhc_gtk_rekey_work(struct work_struct *work)
 {
-       struct wusbhc *wusbhc = container_of(work, struct wusbhc, gtk_rekey_done_work);
+       struct wusbhc *wusbhc = container_of(work,
+                                       struct wusbhc, gtk_rekey_work);
        size_t key_size = sizeof(wusbhc->gtk.data);
+       int port_idx;
+       struct wusb_dev *wusb_dev, *wusb_dev_next;
+       LIST_HEAD(rekey_list);
 
        mutex_lock(&wusbhc->mutex);
+       /* generate the new key */
+       wusbhc_generate_gtk(wusbhc);
+       /* roll the gtk index. */
+       wusbhc->gtk_index = (wusbhc->gtk_index + 1) % (WUSB_KEY_INDEX_MAX + 1);
+       /*
+        * Save all connected devices on a list while holding wusbhc->mutex and
+        * take a reference to each one.  Then submit the set key request to
+        * them after releasing the lock in order to avoid a deadlock.
+        */
+       for (port_idx = 0; port_idx < wusbhc->ports_max; port_idx++) {
+               wusb_dev = wusbhc->port[port_idx].wusb_dev;
+               if (!wusb_dev || !wusb_dev->usb_dev
+                       || !wusb_dev->usb_dev->authenticated)
+                       continue;
 
-       if (--wusbhc->pending_set_gtks == 0)
-               wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size);
-
+               wusb_dev_get(wusb_dev);
+               list_add_tail(&wusb_dev->rekey_node, &rekey_list);
+       }
        mutex_unlock(&wusbhc->mutex);
-}
 
-static void wusbhc_set_gtk_callback(struct urb *urb)
-{
-       struct wusbhc *wusbhc = urb->context;
+       /* Submit the rekey requests without holding wusbhc->mutex. */
+       list_for_each_entry_safe(wusb_dev, wusb_dev_next, &rekey_list,
+               rekey_node) {
+               list_del_init(&wusb_dev->rekey_node);
+               dev_dbg(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d\n",
+                       __func__, wusb_dev->port_idx);
+
+               if (wusb_dev_set_gtk(wusbhc, wusb_dev) < 0) {
+                       dev_err(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d failed\n",
+                               __func__, wusb_dev->port_idx);
+               }
+               wusb_dev_put(wusb_dev);
+       }
 
-       queue_work(wusbd, &wusbhc->gtk_rekey_done_work);
+       /* Switch the host controller to use the new GTK. */
+       mutex_lock(&wusbhc->mutex);
+       wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
+               &wusbhc->gtk.descr.bKeyData, key_size);
+       mutex_unlock(&wusbhc->mutex);
 }
 
 /**
@@ -553,26 +583,12 @@ static void wusbhc_set_gtk_callback(struct urb *urb)
  */
 void wusbhc_gtk_rekey(struct wusbhc *wusbhc)
 {
-       static const size_t key_size = sizeof(wusbhc->gtk.data);
-       int p;
-
-       wusbhc_generate_gtk(wusbhc);
-
-       for (p = 0; p < wusbhc->ports_max; p++) {
-               struct wusb_dev *wusb_dev;
-
-               wusb_dev = wusbhc->port[p].wusb_dev;
-               if (!wusb_dev || !wusb_dev->usb_dev || !wusb_dev->usb_dev->authenticated)
-                       continue;
-
-               usb_fill_control_urb(wusb_dev->set_gtk_urb, wusb_dev->usb_dev,
-                                    usb_sndctrlpipe(wusb_dev->usb_dev, 0),
-                                    (void *)wusb_dev->set_gtk_req,
-                                    &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
-                                    wusbhc_set_gtk_callback, wusbhc);
-               if (usb_submit_urb(wusb_dev->set_gtk_urb, GFP_KERNEL) == 0)
-                       wusbhc->pending_set_gtks++;
-       }
-       if (wusbhc->pending_set_gtks == 0)
-               wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size);
+       /*
+        * We need to submit a URB to the downstream WUSB devices in order to
+        * change the group key.  This can't be done while holding the
+        * wusbhc->mutex since that is also taken in the urb_enqueue routine
+        * and will cause a deadlock.  Instead, queue a work item to do
+        * it when the lock is not held
+        */
+       queue_work(wusbd, &wusbhc->gtk_rekey_work);
 }
index 711b1952b114ab09322a2b11289cf7aa5fe0d433..6bd3b819a6b56b2c37f552ba5177f71df80cd626 100644 (file)
@@ -97,6 +97,7 @@ struct wusb_dev {
        struct kref refcnt;
        struct wusbhc *wusbhc;
        struct list_head cack_node;     /* Connect-Ack list */
+       struct list_head rekey_node;    /* GTK rekey list */
        u8 port_idx;
        u8 addr;
        u8 beacon_type:4;
@@ -107,8 +108,6 @@ struct wusb_dev {
        struct usb_wireless_cap_descriptor *wusb_cap_descr;
        struct uwb_mas_bm availability;
        struct work_struct devconnect_acked_work;
-       struct urb *set_gtk_urb;
-       struct usb_ctrlrequest *set_gtk_req;
        struct usb_device *usb_dev;
 };
 
@@ -296,8 +295,7 @@ struct wusbhc {
        } __attribute__((packed)) gtk;
        u8 gtk_index;
        u32 gtk_tkid;
-       struct work_struct gtk_rekey_done_work;
-       int pending_set_gtks;
+       struct work_struct gtk_rekey_work;
 
        struct usb_encryption_descriptor *ccm1_etd;
 };
index 8521051cf946f0025a9cab15e4f8f880ac841016..cd961622f9c1aac941f33fb0053f192010cd6c09 100644 (file)
@@ -131,6 +131,7 @@ static const struct platform_device_id atmel_lcdfb_devtypes[] = {
                /* terminator */
        }
 };
+MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes);
 
 static struct atmel_lcdfb_config *
 atmel_lcdfb_get_config(struct platform_device *pdev)
index 50c857477e4f1fff39527a4570fc4bf16a640c5e..65041e15fd598ec465c76369fe62cab480746655 100644 (file)
@@ -624,15 +624,15 @@ static int kyrofb_ioctl(struct fb_info *info,
                        return -EINVAL;
                }
        case KYRO_IOCTL_UVSTRIDE:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
                        return -EFAULT;
                break;
        case KYRO_IOCTL_STRIDE:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
                        return -EFAULT;
                break;
        case KYRO_IOCTL_OVERLAY_OFFSET:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
                        return -EFAULT;
                break;
        }
index 9dbea22234015b39845410dd1e651d61e06beb55..7d44d669d5b6decc8f986de2be5a120d408efb3a 100644 (file)
@@ -91,6 +91,15 @@ extern boot_infos_t *boot_infos;
 #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
 
+#define FB_RIGHT_POS(p, bpp)         (fb_be_math(p) ? 0 : (32 - (bpp)))
+
+static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value)
+{
+       u32 bpp = info->var.bits_per_pixel;
+
+       return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp);
+}
+
     /*
      *  Set a single color register. The values supplied are already
      *  rounded down to the hardware's capabilities (according to the
@@ -120,7 +129,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                        mask <<= info->var.transp.offset;
                        value |= mask;
                }
-               pal[regno] = value;
+               pal[regno] = offb_cmap_byteswap(info, value);
                return 0;
        }
 
@@ -301,7 +310,7 @@ static struct fb_ops offb_ops = {
 static void __iomem *offb_map_reg(struct device_node *np, int index,
                                  unsigned long offset, unsigned long size)
 {
-       const u32 *addrp;
+       const __be32 *addrp;
        u64 asize, taddr;
        unsigned int flags;
 
@@ -369,7 +378,11 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
                }
                of_node_put(pciparent);
        } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) {
-               const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#ifdef __BIG_ENDIAN
+               const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#else
+               const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 };
+#endif
                u64 io_addr = of_translate_address(dp, io_of_addr);
                if (io_addr != OF_BAD_ADDR) {
                        par->cmap_adr = ioremap(io_addr + 0x3c8, 2);
@@ -535,7 +548,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        unsigned int flags, rsize, addr_prop = 0;
        unsigned long max_size = 0;
        u64 rstart, address = OF_BAD_ADDR;
-       const u32 *pp, *addrp, *up;
+       const __be32 *pp, *addrp, *up;
        u64 asize;
        int foreign_endian = 0;
 
@@ -551,25 +564,25 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        if (pp == NULL)
                pp = of_get_property(dp, "depth", &len);
        if (pp && len == sizeof(u32))
-               depth = *pp;
+               depth = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-width", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "width", &len);
        if (pp && len == sizeof(u32))
-               width = *pp;
+               width = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-height", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "height", &len);
        if (pp && len == sizeof(u32))
-               height = *pp;
+               height = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-linebytes", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "linebytes", &len);
        if (pp && len == sizeof(u32) && (*pp != 0xffffffffu))
-               pitch = *pp;
+               pitch = be32_to_cpup(pp);
        else
                pitch = width * ((depth + 7) / 8);
 
index e6d56f714ae498ef896f77f1ece977cbf906c345..d94f35dbd5369e83a50265c78b421aac2ab300c7 100644 (file)
@@ -526,6 +526,8 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
        struct omap_dss_device *in = ddata->in;
        int r;
 
+       mutex_lock(&ddata->mutex);
+
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
        in->ops.sdi->set_timings(in, &ddata->videomode);
@@ -614,10 +616,7 @@ static int acx565akm_enable(struct omap_dss_device *dssdev)
        if (omapdss_device_is_enabled(dssdev))
                return 0;
 
-       mutex_lock(&ddata->mutex);
        r = acx565akm_panel_power_on(dssdev);
-       mutex_unlock(&ddata->mutex);
-
        if (r)
                return r;
 
index e0f098562a74b87eee790de505a8483a8a2024b7..a297de5cc859934209099e74fc54880a5f0620f3 100644 (file)
@@ -569,6 +569,7 @@ EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
  * Power management
  */
 
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
 static int sh_mobile_meram_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -611,6 +612,7 @@ static int sh_mobile_meram_resume(struct device *dev)
                meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */
 
 static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
                            sh_mobile_meram_suspend,
index b30e5a439d1f968679c4b0ce80eb918f7e1678b5..a8f2b280f796337df10aa430688f859bdf47b12f 100644 (file)
@@ -293,8 +293,7 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                        + sizeof(u32) * 16, GFP_KERNEL);
        if (!fbi) {
                dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-               ret = -ENOMEM;
-               goto failed;
+               return -ENOMEM;
        }
 
        strcpy(fbi->fb.fix.id, "VT8500 LCD");
@@ -327,15 +326,13 @@ static int vt8500lcd_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "no I/O memory resource defined\n");
-               ret = -ENODEV;
-               goto failed_fbi;
+               return -ENODEV;
        }
 
        res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
        if (res == NULL) {
                dev_err(&pdev->dev, "failed to request I/O memory\n");
-               ret = -EBUSY;
-               goto failed_fbi;
+               return -EBUSY;
        }
 
        fbi->regbase = ioremap(res->start, resource_size(res));
@@ -346,17 +343,19 @@ static int vt8500lcd_probe(struct platform_device *pdev)
        }
 
        disp_timing = of_get_display_timings(pdev->dev.of_node);
-       if (!disp_timing)
-               return -EINVAL;
+       if (!disp_timing) {
+               ret = -EINVAL;
+               goto failed_free_io;
+       }
 
        ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
                                                        OF_USE_NATIVE_MODE);
        if (ret)
-               return ret;
+               goto failed_free_io;
 
        ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
        if (ret)
-               return ret;
+               goto failed_free_io;
 
        /* try allocating the framebuffer */
        fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
@@ -364,7 +363,8 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                                GFP_KERNEL);
        if (!fb_mem_virt) {
                pr_err("%s: Failed to allocate framebuffer\n", __func__);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto failed_free_io;
        }
 
        fbi->fb.fix.smem_start  = fb_mem_phys;
@@ -447,9 +447,6 @@ failed_free_io:
        iounmap(fbi->regbase);
 failed_free_res:
        release_mem_region(res->start, resource_size(res));
-failed_fbi:
-       kfree(fbi);
-failed:
        return ret;
 }
 
index c444654fc33fb6f7e858824eb8ed816186bf3bda..5c4a95b516cf9e576884c8f84e566f03b396facb 100644 (file)
@@ -285,7 +285,7 @@ static void update_balloon_size(struct virtio_balloon *vb)
 {
        __le32 actual = cpu_to_le32(vb->num_pages);
 
-       virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages,
+       virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual,
                      &actual);
 }
 
index a6a2cebb25879242b8408b1537838a67d932b2b3..cafa973c43be7af984fb9d39456b1d36b8913ea8 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
-#include <linux/miscdevice.h>
 
 #define PM_RSTC                                0x1c
 #define PM_WDOG                                0x24
index 833e813118489216a8a27901f749f0765bd03e8f..d1d07f2f69df7cf61cd838feaa89650c22908098 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/module.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/timer.h>
 #include <linux/io.h>
index 70a240297c6d22f2a7d170a731f70320512f478a..07f88f54e5c03008159a5a276056340e65058086 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/watchdog.h>
-#include <linux/miscdevice.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
index 2de486a7eea18a058808cbb33a0ec0fa5f3a650b..3aa50cfa335fda1576950451a492a92336da41cd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index a1a3638c579c857c382ec9c253e5f69424e1dbbb..20dc73844737a99cf30aa6852f6bfceb06d04984 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
index 6d4f3998e1f6c08e7158fdf1068b3a94c3bad448..bdb3f4a5b27c760b5c7509f957213037e234e2be 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
index 44edca66d564195a8e20b54f20c8b4cc389eca2c..f7722a42467632030b4d36dc608e1af7cf497002 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
index 1bdcc313e1d9f713dc24c8b4cf7e2f7e9c312574..5bec20f5dc2db29ec5294bbdf03ee7b8106cb21a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 53d37fea183e1b5be5f2f18093a1c4021e632bc9..d92c2d5859ce9f67c4af0f2c61fcbe6c8c396e74 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/miscdevice.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 
index 3b9fff9dcf654ba6abfb09f970a7d288147d7083..131193a7acdfd0bb07660095e0ff57c500eed6cb 100644 (file)
@@ -409,8 +409,9 @@ static int __init sc1200wdt_init(void)
 #if defined CONFIG_PNP
        /* now that the user has specified an IO port and we haven't detected
         * any devices, disable pnp support */
+       if (isapnp)
+               pnp_unregister_driver(&scl200wdt_pnp_driver);
        isapnp = 0;
-       pnp_unregister_driver(&scl200wdt_pnp_driver);
 #endif
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
index f9b8e06f355808e763ca7a1f7f2e4511fe33c88f..af3528f84d65469196d2a409dbcfc531a09e57c6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/pm_runtime.h>
 #include <linux/fs.h>
index ef2638fee4a8f7037c1f7c342ec1be1347ee3957..c04a1aa158e25762fcbe2b161052beaf56897d7f 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
index d667f6b51d35f93aba02547f82653f3dbb189aa4..bb64ae3f47da58079ac816bde0d5c9abac5f0bff 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 #include <linux/stmp3xxx_rtc_wdt.h>
index 0fd0e8ae62a833b462b29bd09f8f5e7666e437bf..6a447e321dd0c3cf076169d7eac3c7b887a4b96b 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index e029b5768f2c1379279f034dc24c892b52fc0ec3..5aed9d7ad47e6ee81e96b4f16b15aa653a6a9482 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
 #include <linux/err.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
index 55ea73f7c70b52e49ca3b4f2b40f5baa064928e9..4c02e2b9410377d9e6b77fe1bc2b50d929774551 100644 (file)
@@ -350,17 +350,19 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
                pfn = page_to_pfn(page);
 
-               set_phys_to_machine(pfn, frame_list[i]);
-
 #ifdef CONFIG_XEN_HAVE_PVMMU
-               /* Link back into the page tables if not highmem. */
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       int ret;
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               mfn_pte(frame_list[i], PAGE_KERNEL),
-                               0);
-                       BUG_ON(ret);
+               if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+                       set_phys_to_machine(pfn, frame_list[i]);
+
+                       /* Link back into the page tables if not highmem. */
+                       if (!PageHighMem(page)) {
+                               int ret;
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               mfn_pte(frame_list[i], PAGE_KERNEL),
+                                               0);
+                               BUG_ON(ret);
+                       }
                }
 #endif
 
@@ -378,7 +380,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
        enum bp_state state = BP_DONE;
        unsigned long  pfn, i;
        struct page   *page;
-       struct page   *scratch_page;
        int ret;
        struct xen_memory_reservation reservation = {
                .address_bits = 0,
@@ -411,27 +412,29 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
                /*
                 * Ballooned out frames are effectively replaced with
                 * a scratch frame.  Ensure direct mappings and the
                 * p2m are consistent.
                 */
-               scratch_page = get_balloon_scratch_page();
-#ifdef CONFIG_XEN_HAVE_PVMMU
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               pfn_pte(page_to_pfn(scratch_page),
-                                       PAGE_KERNEL_RO), 0);
-                       BUG_ON(ret);
-               }
-#endif
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                        unsigned long p;
+                       struct page   *scratch_page = get_balloon_scratch_page();
+
+                       if (!PageHighMem(page)) {
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               pfn_pte(page_to_pfn(scratch_page),
+                                                       PAGE_KERNEL_RO), 0);
+                               BUG_ON(ret);
+                       }
                        p = page_to_pfn(scratch_page);
                        __set_phys_to_machine(pfn, pfn_to_mfn(p));
+
+                       put_balloon_scratch_page();
                }
-               put_balloon_scratch_page();
+#endif
 
                balloon_append(pfn_to_page(pfn));
        }
@@ -627,15 +630,17 @@ static int __init balloon_init(void)
        if (!xen_domain())
                return -ENODEV;
 
-       for_each_online_cpu(cpu)
-       {
-               per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
-               if (per_cpu(balloon_scratch_page, cpu) == NULL) {
-                       pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
-                       return -ENOMEM;
+       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+               for_each_online_cpu(cpu)
+               {
+                       per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
+                       if (per_cpu(balloon_scratch_page, cpu) == NULL) {
+                               pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
+                               return -ENOMEM;
+                       }
                }
+               register_cpu_notifier(&balloon_cpu_notifier);
        }
-       register_cpu_notifier(&balloon_cpu_notifier);
 
        pr_info("Initialising balloon driver\n");
 
index 62ccf5424ba857e0fe11bb22187bb7dd5d3dad6c..aa846a48f4009eaac8271a8a653716c27aa1dc01 100644 (file)
@@ -930,9 +930,10 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                ret = m2p_add_override(mfn, pages[i], kmap_ops ?
                                       &kmap_ops[i] : NULL);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+ out:
        if (lazy)
                arch_leave_lazy_mmu_mode();
 
@@ -969,9 +970,10 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                ret = m2p_remove_override(pages[i], kmap_ops ?
                                       &kmap_ops[i] : NULL);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+ out:
        if (lazy)
                arch_leave_lazy_mmu_mode();
 
@@ -1174,7 +1176,8 @@ static int gnttab_setup(void)
                gnttab_shared.addr = xen_remap(xen_hvm_resume_frames,
                                                PAGE_SIZE * max_nr_gframes);
                if (gnttab_shared.addr == NULL) {
-                       pr_warn("Failed to ioremap gnttab share frames!\n");
+                       pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n",
+                                       xen_hvm_resume_frames);
                        return -ENOMEM;
                }
        }
index 8e74590fa1bb5d9149e17550c3f4ec7b74142983..569a13b9e856de5c3900050d583844f401243e96 100644 (file)
@@ -533,12 +533,17 @@ static void privcmd_close(struct vm_area_struct *vma)
 {
        struct page **pages = vma->vm_private_data;
        int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       int rc;
 
        if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
                return;
 
-       xen_unmap_domain_mfn_range(vma, numpgs, pages);
-       free_xenballooned_pages(numpgs, pages);
+       rc = xen_unmap_domain_mfn_range(vma, numpgs, pages);
+       if (rc == 0)
+               free_xenballooned_pages(numpgs, pages);
+       else
+               pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n",
+                       numpgs, rc);
        kfree(pages);
 }
 
index a224bc74b6b9d34fa5c45f41408a3ed1138098f4..1eac0731c349f2067b42dea6e01f292453096d4b 100644 (file)
@@ -555,6 +555,11 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
                                sg_dma_len(sgl) = 0;
                                return 0;
                        }
+                       xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
+                                               map & ~PAGE_MASK,
+                                               sg->length,
+                                               dir,
+                                               attrs);
                        sg->dma_address = xen_phys_to_bus(map);
                } else {
                        /* we are not interested in the dma_addr returned by
index a29409c1ffe066b00684db073aa365997371e80f..b41c2c9792ff0dc9a68529219af40967421f797e 100644 (file)
@@ -91,7 +91,7 @@ more 2.4 fixes: [Roman Zippel]
 Version 3.11
 ------------
 
-- Converted to use 2.3.x page cache [Dave Jones <dave@powertweak.com>]
+- Converted to use 2.3.x page cache [Dave Jones]
 - Corruption in truncate() bugfix [Ken Tyler <kent@werple.net.au>]
 
 Version 3.10
index 08159ed13649cacbec1825065e24b2b5b61be267..062a5f6a1448c6cff1cd1dc09e84db3f0d59cc27 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -244,9 +244,14 @@ static void aio_free_ring(struct kioctx *ctx)
        int i;
 
        for (i = 0; i < ctx->nr_pages; i++) {
+               struct page *page;
                pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
                                page_count(ctx->ring_pages[i]));
-               put_page(ctx->ring_pages[i]);
+               page = ctx->ring_pages[i];
+               if (!page)
+                       continue;
+               ctx->ring_pages[i] = NULL;
+               put_page(page);
        }
 
        put_aio_ring_file(ctx);
@@ -280,18 +285,38 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
        unsigned long flags;
        int rc;
 
+       rc = 0;
+
+       /* Make sure the old page hasn't already been changed */
+       spin_lock(&mapping->private_lock);
+       ctx = mapping->private_data;
+       if (ctx) {
+               pgoff_t idx;
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               idx = old->index;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       if (ctx->ring_pages[idx] != old)
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
+               spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       } else
+               rc = -EINVAL;
+       spin_unlock(&mapping->private_lock);
+
+       if (rc != 0)
+               return rc;
+
        /* Writeback must be complete */
        BUG_ON(PageWriteback(old));
-       put_page(old);
+       get_page(new);
 
-       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1);
        if (rc != MIGRATEPAGE_SUCCESS) {
-               get_page(old);
+               put_page(new);
                return rc;
        }
 
-       get_page(new);
-
        /* We can potentially race against kioctx teardown here.  Use the
         * address_space's private data lock to protect the mapping's
         * private_data.
@@ -303,13 +328,24 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
                spin_lock_irqsave(&ctx->completion_lock, flags);
                migrate_page_copy(new, old);
                idx = old->index;
-               if (idx < (pgoff_t)ctx->nr_pages)
-                       ctx->ring_pages[idx] = new;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       /* And only do the move if things haven't changed */
+                       if (ctx->ring_pages[idx] == old)
+                               ctx->ring_pages[idx] = new;
+                       else
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
                spin_unlock_irqrestore(&ctx->completion_lock, flags);
        } else
                rc = -EBUSY;
        spin_unlock(&mapping->private_lock);
 
+       if (rc == MIGRATEPAGE_SUCCESS)
+               put_page(old);
+       else
+               put_page(new);
+
        return rc;
 }
 #endif
@@ -326,7 +362,7 @@ static int aio_setup_ring(struct kioctx *ctx)
        struct aio_ring *ring;
        unsigned nr_events = ctx->max_reqs;
        struct mm_struct *mm = current->mm;
-       unsigned long size, populate;
+       unsigned long size, unused;
        int nr_pages;
        int i;
        struct file *file;
@@ -347,6 +383,20 @@ static int aio_setup_ring(struct kioctx *ctx)
                return -EAGAIN;
        }
 
+       ctx->aio_ring_file = file;
+       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
+                       / sizeof(struct io_event);
+
+       ctx->ring_pages = ctx->internal_pages;
+       if (nr_pages > AIO_RING_PAGES) {
+               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
+                                         GFP_KERNEL);
+               if (!ctx->ring_pages) {
+                       put_aio_ring_file(ctx);
+                       return -ENOMEM;
+               }
+       }
+
        for (i = 0; i < nr_pages; i++) {
                struct page *page;
                page = find_or_create_page(file->f_inode->i_mapping,
@@ -358,17 +408,14 @@ static int aio_setup_ring(struct kioctx *ctx)
                SetPageUptodate(page);
                SetPageDirty(page);
                unlock_page(page);
+
+               ctx->ring_pages[i] = page;
        }
-       ctx->aio_ring_file = file;
-       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
-                       / sizeof(struct io_event);
+       ctx->nr_pages = i;
 
-       ctx->ring_pages = ctx->internal_pages;
-       if (nr_pages > AIO_RING_PAGES) {
-               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
-                                         GFP_KERNEL);
-               if (!ctx->ring_pages)
-                       return -ENOMEM;
+       if (unlikely(i != nr_pages)) {
+               aio_free_ring(ctx);
+               return -EAGAIN;
        }
 
        ctx->mmap_size = nr_pages * PAGE_SIZE;
@@ -377,9 +424,9 @@ static int aio_setup_ring(struct kioctx *ctx)
        down_write(&mm->mmap_sem);
        ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
                                       PROT_READ | PROT_WRITE,
-                                      MAP_SHARED | MAP_POPULATE, 0, &populate);
+                                      MAP_SHARED, 0, &unused);
+       up_write(&mm->mmap_sem);
        if (IS_ERR((void *)ctx->mmap_base)) {
-               up_write(&mm->mmap_sem);
                ctx->mmap_size = 0;
                aio_free_ring(ctx);
                return -EAGAIN;
@@ -387,27 +434,6 @@ static int aio_setup_ring(struct kioctx *ctx)
 
        pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
 
-       /* We must do this while still holding mmap_sem for write, as we
-        * need to be protected against userspace attempting to mremap()
-        * or munmap() the ring buffer.
-        */
-       ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages,
-                                      1, 0, ctx->ring_pages, NULL);
-
-       /* Dropping the reference here is safe as the page cache will hold
-        * onto the pages for us.  It is also required so that page migration
-        * can unmap the pages and get the right reference count.
-        */
-       for (i = 0; i < ctx->nr_pages; i++)
-               put_page(ctx->ring_pages[i]);
-
-       up_write(&mm->mmap_sem);
-
-       if (unlikely(ctx->nr_pages != nr_pages)) {
-               aio_free_ring(ctx);
-               return -EAGAIN;
-       }
-
        ctx->user_id = ctx->mmap_base;
        ctx->nr_events = nr_events; /* trusted copy */
 
@@ -645,12 +671,13 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
            aio_nr + nr_events < aio_nr) {
                spin_unlock(&aio_nr_lock);
                err = -EAGAIN;
-               goto err;
+               goto err_ctx;
        }
        aio_nr += ctx->max_reqs;
        spin_unlock(&aio_nr_lock);
 
-       percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->users);    /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->reqs);     /* free_ioctx_users() will drop this */
 
        err = ioctx_add_table(ctx, mm);
        if (err)
@@ -662,6 +689,8 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 
 err_cleanup:
        aio_nr_sub(ctx->max_reqs);
+err_ctx:
+       aio_free_ring(ctx);
 err:
        free_percpu(ctx->cpu);
        free_percpu(ctx->reqs.pcpu_count);
index b50764bef1410c2750b17d943ae3597899b3ee9e..131d82800b3af45778cb8651f5c559bd57cec437 100644 (file)
@@ -333,7 +333,6 @@ static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
 static int btrfsic_read_block(struct btrfsic_state *state,
                              struct btrfsic_block_data_ctx *block_ctx);
 static void btrfsic_dump_database(struct btrfsic_state *state);
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err);
 static int btrfsic_test_for_metadata(struct btrfsic_state *state,
                                     char **datav, unsigned int num_pages);
 static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
@@ -1687,7 +1686,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
        for (i = 0; i < num_pages;) {
                struct bio *bio;
                unsigned int j;
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
                if (!bio) {
@@ -1698,8 +1696,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                }
                bio->bi_bdev = block_ctx->dev->bdev;
                bio->bi_sector = dev_bytenr >> 9;
-               bio->bi_end_io = btrfsic_complete_bio_end_io;
-               bio->bi_private = &complete;
 
                for (j = i; j < num_pages; j++) {
                        ret = bio_add_page(bio, block_ctx->pagev[j],
@@ -1712,12 +1708,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                               "btrfsic: error, failed to add a single page!\n");
                        return -1;
                }
-               submit_bio(READ, bio);
-
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-
-               if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+               if (submit_bio_wait(READ, bio)) {
                        printk(KERN_INFO
                               "btrfsic: read error at logical %llu dev %s!\n",
                               block_ctx->start, block_ctx->dev->name);
@@ -1740,11 +1731,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
        return block_ctx->len;
 }
 
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static void btrfsic_dump_database(struct btrfsic_state *state)
 {
        struct list_head *elem_all;
@@ -3008,14 +2994,12 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh)
        return submit_bh(rw, bh);
 }
 
-void btrfsic_submit_bio(int rw, struct bio *bio)
+static void __btrfsic_submit_bio(int rw, struct bio *bio)
 {
        struct btrfsic_dev_state *dev_state;
 
-       if (!btrfsic_is_initialized) {
-               submit_bio(rw, bio);
+       if (!btrfsic_is_initialized)
                return;
-       }
 
        mutex_lock(&btrfsic_mutex);
        /* since btrfsic_submit_bio() is also called before
@@ -3106,10 +3090,20 @@ void btrfsic_submit_bio(int rw, struct bio *bio)
        }
 leave:
        mutex_unlock(&btrfsic_mutex);
+}
 
+void btrfsic_submit_bio(int rw, struct bio *bio)
+{
+       __btrfsic_submit_bio(rw, bio);
        submit_bio(rw, bio);
 }
 
+int btrfsic_submit_bio_wait(int rw, struct bio *bio)
+{
+       __btrfsic_submit_bio(rw, bio);
+       return submit_bio_wait(rw, bio);
+}
+
 int btrfsic_mount(struct btrfs_root *root,
                  struct btrfs_fs_devices *fs_devices,
                  int including_extent_data, u32 print_mask)
index 8b59175cc50243c7bd525c91b265fa0f329f6af1..13b8566c97ab433f7455eeb6762942d5e623d16a 100644 (file)
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
 int btrfsic_submit_bh(int rw, struct buffer_head *bh);
 void btrfsic_submit_bio(int rw, struct bio *bio);
+int btrfsic_submit_bio_wait(int rw, struct bio *bio);
 #else
 #define btrfsic_submit_bh submit_bh
 #define btrfsic_submit_bio submit_bio
+#define btrfsic_submit_bio_wait submit_bio_wait
 #endif
 
 int btrfsic_mount(struct btrfs_root *root,
index 45d98d01028f7cdac43461a7acd42f5e17599f32..9c01509dd8abfb0fddc5480b7f4cb3b73002aad4 100644 (file)
@@ -767,20 +767,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
        if (!path)
                return -ENOMEM;
 
-       if (metadata) {
-               key.objectid = bytenr;
-               key.type = BTRFS_METADATA_ITEM_KEY;
-               key.offset = offset;
-       } else {
-               key.objectid = bytenr;
-               key.type = BTRFS_EXTENT_ITEM_KEY;
-               key.offset = offset;
-       }
-
        if (!trans) {
                path->skip_locking = 1;
                path->search_commit_root = 1;
        }
+
+search_again:
+       key.objectid = bytenr;
+       key.offset = offset;
+       if (metadata)
+               key.type = BTRFS_METADATA_ITEM_KEY;
+       else
+               key.type = BTRFS_EXTENT_ITEM_KEY;
+
 again:
        ret = btrfs_search_slot(trans, root->fs_info->extent_root,
                                &key, path, 0, 0);
@@ -788,7 +787,6 @@ again:
                goto out_free;
 
        if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) {
-               metadata = 0;
                if (path->slots[0]) {
                        path->slots[0]--;
                        btrfs_item_key_to_cpu(path->nodes[0], &key,
@@ -855,7 +853,7 @@ again:
                        mutex_lock(&head->mutex);
                        mutex_unlock(&head->mutex);
                        btrfs_put_delayed_ref(&head->node);
-                       goto again;
+                       goto search_again;
                }
                if (head->extent_op && head->extent_op->update_flags)
                        extent_flags |= head->extent_op->flags_to_set;
index 8e457fca0a0ba5c04afb84414ccd640821a640d1..ff43802a7c886088e37c5c1c16427f2b522cad30 100644 (file)
@@ -1952,11 +1952,6 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec,
        return err;
 }
 
-static void repair_io_failure_callback(struct bio *bio, int err)
-{
-       complete(bio->bi_private);
-}
-
 /*
  * this bypasses the standard btrfs submit functions deliberately, as
  * the standard behavior is to write all copies in a raid setup. here we only
@@ -1973,7 +1968,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
 {
        struct bio *bio;
        struct btrfs_device *dev;
-       DECLARE_COMPLETION_ONSTACK(compl);
        u64 map_length = 0;
        u64 sector;
        struct btrfs_bio *bbio = NULL;
@@ -1990,8 +1984,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio)
                return -EIO;
-       bio->bi_private = &compl;
-       bio->bi_end_io = repair_io_failure_callback;
        bio->bi_size = 0;
        map_length = length;
 
@@ -2012,10 +2004,8 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        }
        bio->bi_bdev = dev->bdev;
        bio_add_page(bio, page, length, start - page_offset(page));
-       btrfsic_submit_bio(WRITE_SYNC, bio);
-       wait_for_completion(&compl);
 
-       if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+       if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
                /* try to remap that extent elsewhere? */
                bio_put(bio);
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
index a111622598b0b23f82c84352e6b782361e079526..21da5762b0b1b33d193f3bd7f664995a43062bd6 100644 (file)
@@ -2121,7 +2121,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
 
        err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
        if (err == -EINTR)
-               goto out;
+               goto out_drop_write;
        dentry = lookup_one_len(vol_args->name, parent, namelen);
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
@@ -2284,6 +2284,7 @@ out_dput:
        dput(dentry);
 out_unlock_dir:
        mutex_unlock(&dir->i_mutex);
+out_drop_write:
        mnt_drop_write_file(file);
 out:
        kfree(vol_args);
index ce459a7cb16dae48e233587cb28d271c4403f297..429c73c374b84f9bcd468067221bf99e0b9f67db 100644 (file)
@@ -571,7 +571,9 @@ static int is_cowonly_root(u64 root_objectid)
            root_objectid == BTRFS_CHUNK_TREE_OBJECTID ||
            root_objectid == BTRFS_DEV_TREE_OBJECTID ||
            root_objectid == BTRFS_TREE_LOG_OBJECTID ||
-           root_objectid == BTRFS_CSUM_TREE_OBJECTID)
+           root_objectid == BTRFS_CSUM_TREE_OBJECTID ||
+           root_objectid == BTRFS_UUID_TREE_OBJECTID ||
+           root_objectid == BTRFS_QUOTA_TREE_OBJECTID)
                return 1;
        return 0;
 }
@@ -1264,10 +1266,10 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
 }
 
 /*
- * helper to update/delete the 'address of tree root -> reloc tree'
+ * helper to delete the 'address of tree root -> reloc tree'
  * mapping
  */
-static int __update_reloc_root(struct btrfs_root *root, int del)
+static void __del_reloc_root(struct btrfs_root *root)
 {
        struct rb_node *rb_node;
        struct mapping_node *node = NULL;
@@ -1275,7 +1277,7 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
 
        spin_lock(&rc->reloc_root_tree.lock);
        rb_node = tree_search(&rc->reloc_root_tree.rb_root,
-                             root->commit_root->start);
+                             root->node->start);
        if (rb_node) {
                node = rb_entry(rb_node, struct mapping_node, rb_node);
                rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
@@ -1283,23 +1285,45 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
        spin_unlock(&rc->reloc_root_tree.lock);
 
        if (!node)
-               return 0;
+               return;
        BUG_ON((struct btrfs_root *)node->data != root);
 
-       if (!del) {
-               spin_lock(&rc->reloc_root_tree.lock);
-               node->bytenr = root->node->start;
-               rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
-                                     node->bytenr, &node->rb_node);
-               spin_unlock(&rc->reloc_root_tree.lock);
-               if (rb_node)
-                       backref_tree_panic(rb_node, -EEXIST, node->bytenr);
-       } else {
-               spin_lock(&root->fs_info->trans_lock);
-               list_del_init(&root->root_list);
-               spin_unlock(&root->fs_info->trans_lock);
-               kfree(node);
+       spin_lock(&root->fs_info->trans_lock);
+       list_del_init(&root->root_list);
+       spin_unlock(&root->fs_info->trans_lock);
+       kfree(node);
+}
+
+/*
+ * helper to update the 'address of tree root -> reloc tree'
+ * mapping
+ */
+static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
+{
+       struct rb_node *rb_node;
+       struct mapping_node *node = NULL;
+       struct reloc_control *rc = root->fs_info->reloc_ctl;
+
+       spin_lock(&rc->reloc_root_tree.lock);
+       rb_node = tree_search(&rc->reloc_root_tree.rb_root,
+                             root->node->start);
+       if (rb_node) {
+               node = rb_entry(rb_node, struct mapping_node, rb_node);
+               rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
        }
+       spin_unlock(&rc->reloc_root_tree.lock);
+
+       if (!node)
+               return 0;
+       BUG_ON((struct btrfs_root *)node->data != root);
+
+       spin_lock(&rc->reloc_root_tree.lock);
+       node->bytenr = new_bytenr;
+       rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
+                             node->bytenr, &node->rb_node);
+       spin_unlock(&rc->reloc_root_tree.lock);
+       if (rb_node)
+               backref_tree_panic(rb_node, -EEXIST, node->bytenr);
        return 0;
 }
 
@@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
 {
        struct btrfs_root *reloc_root;
        struct btrfs_root_item *root_item;
-       int del = 0;
        int ret;
 
        if (!root->reloc_root)
@@ -1432,11 +1455,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
        if (root->fs_info->reloc_ctl->merge_reloc_tree &&
            btrfs_root_refs(root_item) == 0) {
                root->reloc_root = NULL;
-               del = 1;
+               __del_reloc_root(reloc_root);
        }
 
-       __update_reloc_root(reloc_root, del);
-
        if (reloc_root->commit_root != reloc_root->node) {
                btrfs_set_root_node(root_item, reloc_root->node);
                free_extent_buffer(reloc_root->commit_root);
@@ -2287,7 +2308,7 @@ void free_reloc_roots(struct list_head *list)
        while (!list_empty(list)) {
                reloc_root = list_entry(list->next, struct btrfs_root,
                                        root_list);
-               __update_reloc_root(reloc_root, 1);
+               __del_reloc_root(reloc_root);
                free_extent_buffer(reloc_root->node);
                free_extent_buffer(reloc_root->commit_root);
                kfree(reloc_root);
@@ -2332,7 +2353,7 @@ again:
 
                        ret = merge_reloc_root(rc, root);
                        if (ret) {
-                               __update_reloc_root(reloc_root, 1);
+                               __del_reloc_root(reloc_root);
                                free_extent_buffer(reloc_root->node);
                                free_extent_buffer(reloc_root->commit_root);
                                kfree(reloc_root);
@@ -2388,6 +2409,13 @@ out:
                btrfs_std_error(root->fs_info, ret);
                if (!list_empty(&reloc_roots))
                        free_reloc_roots(&reloc_roots);
+
+               /* new reloc root may be added */
+               mutex_lock(&root->fs_info->reloc_mutex);
+               list_splice_init(&rc->reloc_roots, &reloc_roots);
+               mutex_unlock(&root->fs_info->reloc_mutex);
+               if (!list_empty(&reloc_roots))
+                       free_reloc_roots(&reloc_roots);
        }
 
        BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
@@ -4522,6 +4550,11 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
        BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
               root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
 
+       if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
+               if (buf == root->node)
+                       __update_reloc_root(root, cow->start);
+       }
+
        level = btrfs_header_level(buf);
        if (btrfs_header_generation(buf) <=
            btrfs_root_last_snapshot(&root->root_item))
index 561e2f16ba3e3ff3b0be72b12b4a052b86082d2a..1fd3f33c330abe930fbd03de1deb5968e32fd7b5 100644 (file)
@@ -208,7 +208,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                                         int is_metadata, int have_csum,
                                         const u8 *csum, u64 generation,
                                         u16 csum_size);
-static void scrub_complete_bio_end_io(struct bio *bio, int err);
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good,
                                             int force_write);
@@ -1294,7 +1293,6 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
        for (page_num = 0; page_num < sblock->page_count; page_num++) {
                struct bio *bio;
                struct scrub_page *page = sblock->pagev[page_num];
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                if (page->dev->bdev == NULL) {
                        page->io_error = 1;
@@ -1311,18 +1309,11 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
                }
                bio->bi_bdev = page->dev->bdev;
                bio->bi_sector = page->physical >> 9;
-               bio->bi_end_io = scrub_complete_bio_end_io;
-               bio->bi_private = &complete;
 
                bio_add_page(bio, page->page, PAGE_SIZE, 0);
-               btrfsic_submit_bio(READ, bio);
-
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-
-               page->io_error = !test_bit(BIO_UPTODATE, &bio->bi_flags);
-               if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+               if (btrfsic_submit_bio_wait(READ, bio))
                        sblock->no_io_error_seen = 0;
+
                bio_put(bio);
        }
 
@@ -1391,11 +1382,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                sblock->checksum_error = 1;
 }
 
-static void scrub_complete_bio_end_io(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good,
                                             int force_write)
@@ -1430,7 +1416,6 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
            sblock_bad->checksum_error || page_bad->io_error) {
                struct bio *bio;
                int ret;
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                if (!page_bad->dev->bdev) {
                        printk_ratelimited(KERN_WARNING
@@ -1443,19 +1428,14 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
                        return -EIO;
                bio->bi_bdev = page_bad->dev->bdev;
                bio->bi_sector = page_bad->physical >> 9;
-               bio->bi_end_io = scrub_complete_bio_end_io;
-               bio->bi_private = &complete;
 
                ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0);
                if (PAGE_SIZE != ret) {
                        bio_put(bio);
                        return -EIO;
                }
-               btrfsic_submit_bio(WRITE, bio);
 
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-               if (!bio_flagged(bio, BIO_UPTODATE)) {
+               if (btrfsic_submit_bio_wait(WRITE, bio)) {
                        btrfs_dev_stat_inc_and_print(page_bad->dev,
                                BTRFS_DEV_STAT_WRITE_ERRS);
                        btrfs_dev_replace_stats_inc(
@@ -3375,7 +3355,6 @@ static int write_page_nocow(struct scrub_ctx *sctx,
        struct bio *bio;
        struct btrfs_device *dev;
        int ret;
-       DECLARE_COMPLETION_ONSTACK(compl);
 
        dev = sctx->wr_ctx.tgtdev;
        if (!dev)
@@ -3392,8 +3371,6 @@ static int write_page_nocow(struct scrub_ctx *sctx,
                spin_unlock(&sctx->stat_lock);
                return -ENOMEM;
        }
-       bio->bi_private = &compl;
-       bio->bi_end_io = scrub_complete_bio_end_io;
        bio->bi_size = 0;
        bio->bi_sector = physical_for_dev_replace >> 9;
        bio->bi_bdev = dev->bdev;
@@ -3404,10 +3381,8 @@ leave_with_eio:
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
                return -EIO;
        }
-       btrfsic_submit_bio(WRITE_SYNC, bio);
-       wait_for_completion(&compl);
 
-       if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+       if (btrfsic_submit_bio_wait(WRITE_SYNC, bio))
                goto leave_with_eio;
 
        bio_put(bio);
index 6837fe87f3a6bb9f471f54c596e0d98fe67059a3..945d1db98f26968ec051a6ff6116f971f18e7303 100644 (file)
@@ -4723,8 +4723,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        }
 
        if (!access_ok(VERIFY_READ, arg->clone_sources,
-                       sizeof(*arg->clone_sources *
-                       arg->clone_sources_count))) {
+                       sizeof(*arg->clone_sources) *
+                       arg->clone_sources_count)) {
                ret = -EFAULT;
                goto out;
        }
index 2d8ac1bf0cf9b9d613215000758cbfa312b4962e..d71a11d13dfaa8b3065222c87ce964d8ba28e5b5 100644 (file)
@@ -432,7 +432,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        } else {
                                printk(KERN_INFO "btrfs: setting nodatacow\n");
                        }
-                       info->compress_type = BTRFS_COMPRESS_NONE;
                        btrfs_clear_opt(info->mount_opt, COMPRESS);
                        btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                        btrfs_set_opt(info->mount_opt, NODATACOW);
@@ -461,7 +460,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                btrfs_set_fs_incompat(info, COMPRESS_LZO);
                        } else if (strncmp(args[0].from, "no", 2) == 0) {
                                compress_type = "no";
-                               info->compress_type = BTRFS_COMPRESS_NONE;
                                btrfs_clear_opt(info->mount_opt, COMPRESS);
                                btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                                compress_force = false;
@@ -474,9 +472,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
                                pr_info("btrfs: force %s compression\n",
                                        compress_type);
-                       } else
+                       } else if (btrfs_test_opt(root, COMPRESS)) {
                                pr_info("btrfs: use %s compression\n",
                                        compress_type);
+                       }
                        break;
                case Opt_ssd:
                        printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
index 6df8bd481425379006912990ee6f9461eaf3cf1b..ec3ba43b9faae73fba6d6352da9515a812ec9f36 100644 (file)
@@ -210,13 +210,17 @@ static int readpage_nounlock(struct file *filp, struct page *page)
        if (err < 0) {
                SetPageError(page);
                goto out;
-       } else if (err < PAGE_CACHE_SIZE) {
+       } else {
+               if (err < PAGE_CACHE_SIZE) {
                /* zero fill remainder of page */
-               zero_user_segment(page, err, PAGE_CACHE_SIZE);
+                       zero_user_segment(page, err, PAGE_CACHE_SIZE);
+               } else {
+                       flush_dcache_page(page);
+               }
        }
        SetPageUptodate(page);
 
-       if (err == 0)
+       if (err >= 0)
                ceph_readpage_to_fscache(inode, page);
 
 out:
index 7db2e6ca4b8f0b07146c137a80e24567a03d3e43..8c44fdd4e1c39f836b2c8a9b2a7a025f1844d3b3 100644 (file)
@@ -324,6 +324,9 @@ void ceph_invalidate_fscache_page(struct inode* inode, struct page *page)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
 
+       if (!PageFsCache(page))
+               return;
+
        fscache_wait_on_page_write(ci->fscache, page);
        fscache_uncache_page(ci->fscache, page);
 }
index 13976c33332ec1fd7ca3999053b15b7079c5ab31..3c0a4bd7499645ca8bf90fd1a6ba16f6831c164c 100644 (file)
@@ -897,7 +897,7 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci)
  * caller should hold i_ceph_lock.
  * caller will not hold session s_mutex if called from destroy_inode.
  */
-void __ceph_remove_cap(struct ceph_cap *cap)
+void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
 {
        struct ceph_mds_session *session = cap->session;
        struct ceph_inode_info *ci = cap->ci;
@@ -909,6 +909,16 @@ void __ceph_remove_cap(struct ceph_cap *cap)
 
        /* remove from session list */
        spin_lock(&session->s_cap_lock);
+       /*
+        * s_cap_reconnect is protected by s_cap_lock. no one changes
+        * s_cap_gen while session is in the reconnect state.
+        */
+       if (queue_release &&
+           (!session->s_cap_reconnect ||
+            cap->cap_gen == session->s_cap_gen))
+               __queue_cap_release(session, ci->i_vino.ino, cap->cap_id,
+                                   cap->mseq, cap->issue_seq);
+
        if (session->s_cap_iterator == cap) {
                /* not yet, we are iterating over this very cap */
                dout("__ceph_remove_cap  delaying %p removal from session %p\n",
@@ -1023,7 +1033,6 @@ void __queue_cap_release(struct ceph_mds_session *session,
        struct ceph_mds_cap_release *head;
        struct ceph_mds_cap_item *item;
 
-       spin_lock(&session->s_cap_lock);
        BUG_ON(!session->s_num_cap_releases);
        msg = list_first_entry(&session->s_cap_releases,
                               struct ceph_msg, list_head);
@@ -1052,7 +1061,6 @@ void __queue_cap_release(struct ceph_mds_session *session,
                     (int)CEPH_CAPS_PER_RELEASE,
                     (int)msg->front.iov_len);
        }
-       spin_unlock(&session->s_cap_lock);
 }
 
 /*
@@ -1067,12 +1075,8 @@ void ceph_queue_caps_release(struct inode *inode)
        p = rb_first(&ci->i_caps);
        while (p) {
                struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
-               struct ceph_mds_session *session = cap->session;
-
-               __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
-                                   cap->mseq, cap->issue_seq);
                p = rb_next(p);
-               __ceph_remove_cap(cap);
+               __ceph_remove_cap(cap, true);
        }
 }
 
@@ -2791,7 +2795,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
                        }
                        spin_unlock(&mdsc->cap_dirty_lock);
                }
-               __ceph_remove_cap(cap);
+               __ceph_remove_cap(cap, false);
        }
        /* else, we already released it */
 
@@ -2931,9 +2935,12 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        if (!inode) {
                dout(" i don't have ino %llx\n", vino.ino);
 
-               if (op == CEPH_CAP_OP_IMPORT)
+               if (op == CEPH_CAP_OP_IMPORT) {
+                       spin_lock(&session->s_cap_lock);
                        __queue_cap_release(session, vino.ino, cap_id,
                                            mseq, seq);
+                       spin_unlock(&session->s_cap_lock);
+               }
                goto flush_cap_releases;
        }
 
index 868b61d56cac77f3a8328d5ba4851ec7947fe827..2a0bcaeb189acd18b124aff8d54619667fd97bf2 100644 (file)
@@ -352,8 +352,18 @@ more:
                }
 
                /* note next offset and last dentry name */
+               rinfo = &req->r_reply_info;
+               if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
+                       frag = le32_to_cpu(rinfo->dir_dir->frag);
+                       if (ceph_frag_is_leftmost(frag))
+                               fi->next_offset = 2;
+                       else
+                               fi->next_offset = 0;
+                       off = fi->next_offset;
+               }
                fi->offset = fi->next_offset;
                fi->last_readdir = req;
+               fi->frag = frag;
 
                if (req->r_reply_info.dir_end) {
                        kfree(fi->last_name);
@@ -363,7 +373,6 @@ more:
                        else
                                fi->next_offset = 0;
                } else {
-                       rinfo = &req->r_reply_info;
                        err = note_last_dentry(fi,
                                       rinfo->dir_dname[rinfo->dir_nr-1],
                                       rinfo->dir_dname_len[rinfo->dir_nr-1]);
index 8549a48115f71b23e1f35ef444caf3eb32dbced3..278fd28912880b5cc09989ed7dcb8e7fbbfcb3ef 100644 (file)
@@ -577,6 +577,8 @@ static int fill_inode(struct inode *inode,
        int issued = 0, implemented;
        struct timespec mtime, atime, ctime;
        u32 nsplits;
+       struct ceph_inode_frag *frag;
+       struct rb_node *rb_node;
        struct ceph_buffer *xattr_blob = NULL;
        int err = 0;
        int queue_trunc = 0;
@@ -751,15 +753,38 @@ no_change:
        /* FIXME: move me up, if/when version reflects fragtree changes */
        nsplits = le32_to_cpu(info->fragtree.nsplits);
        mutex_lock(&ci->i_fragtree_mutex);
+       rb_node = rb_first(&ci->i_fragtree);
        for (i = 0; i < nsplits; i++) {
                u32 id = le32_to_cpu(info->fragtree.splits[i].frag);
-               struct ceph_inode_frag *frag = __get_or_create_frag(ci, id);
-
-               if (IS_ERR(frag))
-                       continue;
+               frag = NULL;
+               while (rb_node) {
+                       frag = rb_entry(rb_node, struct ceph_inode_frag, node);
+                       if (ceph_frag_compare(frag->frag, id) >= 0) {
+                               if (frag->frag != id)
+                                       frag = NULL;
+                               else
+                                       rb_node = rb_next(rb_node);
+                               break;
+                       }
+                       rb_node = rb_next(rb_node);
+                       rb_erase(&frag->node, &ci->i_fragtree);
+                       kfree(frag);
+                       frag = NULL;
+               }
+               if (!frag) {
+                       frag = __get_or_create_frag(ci, id);
+                       if (IS_ERR(frag))
+                               continue;
+               }
                frag->split_by = le32_to_cpu(info->fragtree.splits[i].by);
                dout(" frag %x split by %d\n", frag->frag, frag->split_by);
        }
+       while (rb_node) {
+               frag = rb_entry(rb_node, struct ceph_inode_frag, node);
+               rb_node = rb_next(rb_node);
+               rb_erase(&frag->node, &ci->i_fragtree);
+               kfree(frag);
+       }
        mutex_unlock(&ci->i_fragtree_mutex);
 
        /* were we issued a capability? */
@@ -953,7 +978,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
        struct ceph_mds_reply_inode *ininfo;
        struct ceph_vino vino;
        struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
-       int i = 0;
        int err = 0;
 
        dout("fill_trace %p is_dentry %d is_target %d\n", req,
@@ -1014,6 +1038,29 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                }
        }
 
+       if (rinfo->head->is_target) {
+               vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
+               vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
+
+               in = ceph_get_inode(sb, vino);
+               if (IS_ERR(in)) {
+                       err = PTR_ERR(in);
+                       goto done;
+               }
+               req->r_target_inode = in;
+
+               err = fill_inode(in, &rinfo->targeti, NULL,
+                               session, req->r_request_started,
+                               (le32_to_cpu(rinfo->head->result) == 0) ?
+                               req->r_fmode : -1,
+                               &req->r_caps_reservation);
+               if (err < 0) {
+                       pr_err("fill_inode badness %p %llx.%llx\n",
+                               in, ceph_vinop(in));
+                       goto done;
+               }
+       }
+
        /*
         * ignore null lease/binding on snapdir ENOENT, or else we
         * will have trouble splicing in the virtual snapdir later
@@ -1083,7 +1130,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                             ceph_dentry(req->r_old_dentry)->offset);
 
                        dn = req->r_old_dentry;  /* use old_dentry */
-                       in = dn->d_inode;
                }
 
                /* null dentry? */
@@ -1105,44 +1151,28 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                }
 
                /* attach proper inode */
-               ininfo = rinfo->targeti.in;
-               vino.ino = le64_to_cpu(ininfo->ino);
-               vino.snap = le64_to_cpu(ininfo->snapid);
-               in = dn->d_inode;
-               if (!in) {
-                       in = ceph_get_inode(sb, vino);
-                       if (IS_ERR(in)) {
-                               pr_err("fill_trace bad get_inode "
-                                      "%llx.%llx\n", vino.ino, vino.snap);
-                               err = PTR_ERR(in);
-                               d_drop(dn);
-                               goto done;
-                       }
+               if (!dn->d_inode) {
+                       ihold(in);
                        dn = splice_dentry(dn, in, &have_lease, true);
                        if (IS_ERR(dn)) {
                                err = PTR_ERR(dn);
                                goto done;
                        }
                        req->r_dentry = dn;  /* may have spliced */
-                       ihold(in);
-               } else if (ceph_ino(in) == vino.ino &&
-                          ceph_snap(in) == vino.snap) {
-                       ihold(in);
-               } else {
+               } else if (dn->d_inode && dn->d_inode != in) {
                        dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
-                            dn, in, ceph_ino(in), ceph_snap(in),
-                            vino.ino, vino.snap);
+                            dn, dn->d_inode, ceph_vinop(dn->d_inode),
+                            ceph_vinop(in));
                        have_lease = false;
-                       in = NULL;
                }
 
                if (have_lease)
                        update_dentry_lease(dn, rinfo->dlease, session,
                                            req->r_request_started);
                dout(" final dn %p\n", dn);
-               i++;
-       } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
-                  req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) {
+       } else if (!req->r_aborted &&
+                  (req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
+                   req->r_op == CEPH_MDS_OP_MKSNAP)) {
                struct dentry *dn = req->r_dentry;
 
                /* fill out a snapdir LOOKUPSNAP dentry */
@@ -1152,52 +1182,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                ininfo = rinfo->targeti.in;
                vino.ino = le64_to_cpu(ininfo->ino);
                vino.snap = le64_to_cpu(ininfo->snapid);
-               in = ceph_get_inode(sb, vino);
-               if (IS_ERR(in)) {
-                       pr_err("fill_inode get_inode badness %llx.%llx\n",
-                              vino.ino, vino.snap);
-                       err = PTR_ERR(in);
-                       d_delete(dn);
-                       goto done;
-               }
                dout(" linking snapped dir %p to dn %p\n", in, dn);
+               ihold(in);
                dn = splice_dentry(dn, in, NULL, true);
                if (IS_ERR(dn)) {
                        err = PTR_ERR(dn);
                        goto done;
                }
                req->r_dentry = dn;  /* may have spliced */
-               ihold(in);
-               rinfo->head->is_dentry = 1;  /* fool notrace handlers */
-       }
-
-       if (rinfo->head->is_target) {
-               vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
-               vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
-
-               if (in == NULL || ceph_ino(in) != vino.ino ||
-                   ceph_snap(in) != vino.snap) {
-                       in = ceph_get_inode(sb, vino);
-                       if (IS_ERR(in)) {
-                               err = PTR_ERR(in);
-                               goto done;
-                       }
-               }
-               req->r_target_inode = in;
-
-               err = fill_inode(in,
-                                &rinfo->targeti, NULL,
-                                session, req->r_request_started,
-                                (le32_to_cpu(rinfo->head->result) == 0) ?
-                                req->r_fmode : -1,
-                                &req->r_caps_reservation);
-               if (err < 0) {
-                       pr_err("fill_inode badness %p %llx.%llx\n",
-                              in, ceph_vinop(in));
-                       goto done;
-               }
        }
-
 done:
        dout("fill_trace done err=%d\n", err);
        return err;
@@ -1247,11 +1240,23 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
        struct qstr dname;
        struct dentry *dn;
        struct inode *in;
-       int err = 0, i;
+       int err = 0, ret, i;
        struct inode *snapdir = NULL;
        struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
-       u64 frag = le32_to_cpu(rhead->args.readdir.frag);
        struct ceph_dentry_info *di;
+       u64 r_readdir_offset = req->r_readdir_offset;
+       u32 frag = le32_to_cpu(rhead->args.readdir.frag);
+
+       if (rinfo->dir_dir &&
+           le32_to_cpu(rinfo->dir_dir->frag) != frag) {
+               dout("readdir_prepopulate got new frag %x -> %x\n",
+                    frag, le32_to_cpu(rinfo->dir_dir->frag));
+               frag = le32_to_cpu(rinfo->dir_dir->frag);
+               if (ceph_frag_is_leftmost(frag))
+                       r_readdir_offset = 2;
+               else
+                       r_readdir_offset = 0;
+       }
 
        if (req->r_aborted)
                return readdir_prepopulate_inodes_only(req, session);
@@ -1268,6 +1273,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                        ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir);
        }
 
+       /* FIXME: release caps/leases if error occurs */
        for (i = 0; i < rinfo->dir_nr; i++) {
                struct ceph_vino vino;
 
@@ -1292,9 +1298,10 @@ retry_lookup:
                                err = -ENOMEM;
                                goto out;
                        }
-                       err = ceph_init_dentry(dn);
-                       if (err < 0) {
+                       ret = ceph_init_dentry(dn);
+                       if (ret < 0) {
                                dput(dn);
+                               err = ret;
                                goto out;
                        }
                } else if (dn->d_inode &&
@@ -1314,9 +1321,6 @@ retry_lookup:
                        spin_unlock(&parent->d_lock);
                }
 
-               di = dn->d_fsdata;
-               di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset);
-
                /* inode */
                if (dn->d_inode) {
                        in = dn->d_inode;
@@ -1329,26 +1333,39 @@ retry_lookup:
                                err = PTR_ERR(in);
                                goto out;
                        }
-                       dn = splice_dentry(dn, in, NULL, false);
-                       if (IS_ERR(dn))
-                               dn = NULL;
                }
 
                if (fill_inode(in, &rinfo->dir_in[i], NULL, session,
                               req->r_request_started, -1,
                               &req->r_caps_reservation) < 0) {
                        pr_err("fill_inode badness on %p\n", in);
+                       if (!dn->d_inode)
+                               iput(in);
+                       d_drop(dn);
                        goto next_item;
                }
-               if (dn)
-                       update_dentry_lease(dn, rinfo->dir_dlease[i],
-                                           req->r_session,
-                                           req->r_request_started);
+
+               if (!dn->d_inode) {
+                       dn = splice_dentry(dn, in, NULL, false);
+                       if (IS_ERR(dn)) {
+                               err = PTR_ERR(dn);
+                               dn = NULL;
+                               goto next_item;
+                       }
+               }
+
+               di = dn->d_fsdata;
+               di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
+
+               update_dentry_lease(dn, rinfo->dir_dlease[i],
+                                   req->r_session,
+                                   req->r_request_started);
 next_item:
                if (dn)
                        dput(dn);
        }
-       req->r_did_prepopulate = true;
+       if (err == 0)
+               req->r_did_prepopulate = true;
 
 out:
        if (snapdir) {
index b7bda5d9611da031aaf6f104ece9fa6351993070..d90861f452107cc47b7242e8ea66dc1257f7c235 100644 (file)
@@ -43,6 +43,7 @@
  */
 
 struct ceph_reconnect_state {
+       int nr_caps;
        struct ceph_pagelist *pagelist;
        bool flock;
 };
@@ -443,6 +444,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        INIT_LIST_HEAD(&s->s_waiting);
        INIT_LIST_HEAD(&s->s_unsafe);
        s->s_num_cap_releases = 0;
+       s->s_cap_reconnect = 0;
        s->s_cap_iterator = NULL;
        INIT_LIST_HEAD(&s->s_cap_releases);
        INIT_LIST_HEAD(&s->s_cap_releases_done);
@@ -642,6 +644,8 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
                req->r_unsafe_dir = NULL;
        }
 
+       complete_all(&req->r_safe_completion);
+
        ceph_mdsc_put_request(req);
 }
 
@@ -986,7 +990,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
        dout("removing cap %p, ci is %p, inode is %p\n",
             cap, ci, &ci->vfs_inode);
        spin_lock(&ci->i_ceph_lock);
-       __ceph_remove_cap(cap);
+       __ceph_remove_cap(cap, false);
        if (!__ceph_is_any_real_caps(ci)) {
                struct ceph_mds_client *mdsc =
                        ceph_sb_to_client(inode->i_sb)->mdsc;
@@ -1231,9 +1235,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
        session->s_trim_caps--;
        if (oissued) {
                /* we aren't the only cap.. just remove us */
-               __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
-                                   cap->mseq, cap->issue_seq);
-               __ceph_remove_cap(cap);
+               __ceph_remove_cap(cap, true);
        } else {
                /* try to drop referring dentries */
                spin_unlock(&ci->i_ceph_lock);
@@ -1416,7 +1418,6 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
        unsigned num;
 
        dout("discard_cap_releases mds%d\n", session->s_mds);
-       spin_lock(&session->s_cap_lock);
 
        /* zero out the in-progress message */
        msg = list_first_entry(&session->s_cap_releases,
@@ -1443,8 +1444,6 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
                msg->front.iov_len = sizeof(*head);
                list_add(&msg->list_head, &session->s_cap_releases);
        }
-
-       spin_unlock(&session->s_cap_lock);
 }
 
 /*
@@ -1875,8 +1874,11 @@ static int __do_request(struct ceph_mds_client *mdsc,
        int mds = -1;
        int err = -EAGAIN;
 
-       if (req->r_err || req->r_got_result)
+       if (req->r_err || req->r_got_result) {
+               if (req->r_aborted)
+                       __unregister_request(mdsc, req);
                goto out;
+       }
 
        if (req->r_timeout &&
            time_after_eq(jiffies, req->r_started + req->r_timeout)) {
@@ -2186,7 +2188,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        if (head->safe) {
                req->r_got_safe = true;
                __unregister_request(mdsc, req);
-               complete_all(&req->r_safe_completion);
 
                if (req->r_got_unsafe) {
                        /*
@@ -2238,8 +2239,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
                if (result == 0 && (req->r_op == CEPH_MDS_OP_READDIR ||
-                                   req->r_op == CEPH_MDS_OP_LSSNAP) &&
-                   rinfo->dir_nr)
+                                   req->r_op == CEPH_MDS_OP_LSSNAP))
                        ceph_readdir_prepopulate(req, req->r_session);
                ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
        }
@@ -2490,6 +2490,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
        cap->seq = 0;        /* reset cap seq */
        cap->issue_seq = 0;  /* and issue_seq */
        cap->mseq = 0;       /* and migrate_seq */
+       cap->cap_gen = cap->session->s_cap_gen;
 
        if (recon_state->flock) {
                rec.v2.cap_id = cpu_to_le64(cap->cap_id);
@@ -2552,6 +2553,8 @@ encode_again:
        } else {
                err = ceph_pagelist_append(pagelist, &rec, reclen);
        }
+
+       recon_state->nr_caps++;
 out_free:
        kfree(path);
 out_dput:
@@ -2579,6 +2582,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
        struct rb_node *p;
        int mds = session->s_mds;
        int err = -ENOMEM;
+       int s_nr_caps;
        struct ceph_pagelist *pagelist;
        struct ceph_reconnect_state recon_state;
 
@@ -2610,20 +2614,38 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
        dout("session %p state %s\n", session,
             session_state_name(session->s_state));
 
+       spin_lock(&session->s_gen_ttl_lock);
+       session->s_cap_gen++;
+       spin_unlock(&session->s_gen_ttl_lock);
+
+       spin_lock(&session->s_cap_lock);
+       /*
+        * notify __ceph_remove_cap() that we are composing cap reconnect.
+        * If a cap get released before being added to the cap reconnect,
+        * __ceph_remove_cap() should skip queuing cap release.
+        */
+       session->s_cap_reconnect = 1;
        /* drop old cap expires; we're about to reestablish that state */
        discard_cap_releases(mdsc, session);
+       spin_unlock(&session->s_cap_lock);
 
        /* traverse this session's caps */
-       err = ceph_pagelist_encode_32(pagelist, session->s_nr_caps);
+       s_nr_caps = session->s_nr_caps;
+       err = ceph_pagelist_encode_32(pagelist, s_nr_caps);
        if (err)
                goto fail;
 
+       recon_state.nr_caps = 0;
        recon_state.pagelist = pagelist;
        recon_state.flock = session->s_con.peer_features & CEPH_FEATURE_FLOCK;
        err = iterate_session_caps(session, encode_caps_cb, &recon_state);
        if (err < 0)
                goto fail;
 
+       spin_lock(&session->s_cap_lock);
+       session->s_cap_reconnect = 0;
+       spin_unlock(&session->s_cap_lock);
+
        /*
         * snaprealms.  we provide mds with the ino, seq (version), and
         * parent for all of our realms.  If the mds has any newer info,
@@ -2646,11 +2668,18 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
 
        if (recon_state.flock)
                reply->hdr.version = cpu_to_le16(2);
-       if (pagelist->length) {
-               /* set up outbound data if we have any */
-               reply->hdr.data_len = cpu_to_le32(pagelist->length);
-               ceph_msg_data_add_pagelist(reply, pagelist);
+
+       /* raced with cap release? */
+       if (s_nr_caps != recon_state.nr_caps) {
+               struct page *page = list_first_entry(&pagelist->head,
+                                                    struct page, lru);
+               __le32 *addr = kmap_atomic(page);
+               *addr = cpu_to_le32(recon_state.nr_caps);
+               kunmap_atomic(addr);
        }
+
+       reply->hdr.data_len = cpu_to_le32(pagelist->length);
+       ceph_msg_data_add_pagelist(reply, pagelist);
        ceph_con_send(&session->s_con, reply);
 
        mutex_unlock(&session->s_mutex);
index c2a19fbbe5177b619b7a3d7e6132b626df8c8508..4c053d099ae4e60400dbcbdcce21844138ba8a47 100644 (file)
@@ -132,6 +132,7 @@ struct ceph_mds_session {
        struct list_head  s_caps;     /* all caps issued by this session */
        int               s_nr_caps, s_trim_caps;
        int               s_num_cap_releases;
+       int               s_cap_reconnect;
        struct list_head  s_cap_releases; /* waiting cap_release messages */
        struct list_head  s_cap_releases_done; /* ready to send */
        struct ceph_cap  *s_cap_iterator;
index 6014b0a3c405cb12dfb62fdac7887f83a4977b96..ef4ac38bb614a911680668fe52f6e7fa272d94ce 100644 (file)
@@ -741,13 +741,7 @@ extern int ceph_add_cap(struct inode *inode,
                        int fmode, unsigned issued, unsigned wanted,
                        unsigned cap, unsigned seq, u64 realmino, int flags,
                        struct ceph_cap_reservation *caps_reservation);
-extern void __ceph_remove_cap(struct ceph_cap *cap);
-static inline void ceph_remove_cap(struct ceph_cap *cap)
-{
-       spin_lock(&cap->ci->i_ceph_lock);
-       __ceph_remove_cap(cap);
-       spin_unlock(&cap->ci->i_ceph_lock);
-}
+extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
 extern void ceph_put_cap(struct ceph_mds_client *mdsc,
                         struct ceph_cap *cap);
 
index d9ea7ada1378f95e48b08e286e38e2d080893993..f918a998a08758caac54bf8205cd7da7705c1efc 100644 (file)
@@ -384,6 +384,7 @@ struct smb_version_operations {
        int (*clone_range)(const unsigned int, struct cifsFileInfo *src_file,
                        struct cifsFileInfo *target_file, u64 src_off, u64 len,
                        u64 dest_off);
+       int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
 };
 
 struct smb_version_values {
index 409b45eefe7086899ae4da636b96cd8c07794dd5..77492301cc2b16c0f82ecea64de7bfb02fe31db5 100644 (file)
 #include <linux/mount.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <linux/btrfs.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifsfs.h"
 
+#define CIFS_IOCTL_MAGIC       0xCF
+#define CIFS_IOC_COPYCHUNK_FILE        _IOW(CIFS_IOCTL_MAGIC, 3, int)
+
 static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
                        unsigned long srcfd, u64 off, u64 len, u64 destoff)
 {
@@ -213,7 +215,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                cifs_dbg(FYI, "set compress flag rc %d\n", rc);
                        }
                        break;
-               case BTRFS_IOC_CLONE:
+               case CIFS_IOC_COPYCHUNK_FILE:
                        rc = cifs_ioctl_clone(xid, filep, arg, 0, 0, 0);
                        break;
                default:
index 11dde4b24f8aa1dce05354cef65fa93feb82735f..757da3e54d3dce601b71b97883f3430556040107 100644 (file)
@@ -532,7 +532,10 @@ smb2_clone_range(const unsigned int xid,
        int rc;
        unsigned int ret_data_len;
        struct copychunk_ioctl *pcchunk;
-       char *retbuf = NULL;
+       struct copychunk_ioctl_rsp *retbuf = NULL;
+       struct cifs_tcon *tcon;
+       int chunks_copied = 0;
+       bool chunk_sizes_updated = false;
 
        pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
 
@@ -547,27 +550,96 @@ smb2_clone_range(const unsigned int xid,
 
        /* Note: request_res_key sets res_key null only if rc !=0 */
        if (rc)
-               return rc;
+               goto cchunk_out;
 
        /* For now array only one chunk long, will make more flexible later */
        pcchunk->ChunkCount = __constant_cpu_to_le32(1);
        pcchunk->Reserved = 0;
-       pcchunk->SourceOffset = cpu_to_le64(src_off);
-       pcchunk->TargetOffset = cpu_to_le64(dest_off);
-       pcchunk->Length = cpu_to_le32(len);
        pcchunk->Reserved2 = 0;
 
-       /* Request that server copy to target from src file identified by key */
-       rc = SMB2_ioctl(xid, tlink_tcon(trgtfile->tlink),
-                       trgtfile->fid.persistent_fid,
-                       trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
-                       true /* is_fsctl */, (char *)pcchunk,
-                       sizeof(struct copychunk_ioctl), &retbuf, &ret_data_len);
+       tcon = tlink_tcon(trgtfile->tlink);
 
-       /* BB need to special case rc = EINVAL to alter chunk size */
+       while (len > 0) {
+               pcchunk->SourceOffset = cpu_to_le64(src_off);
+               pcchunk->TargetOffset = cpu_to_le64(dest_off);
+               pcchunk->Length =
+                       cpu_to_le32(min_t(u32, len, tcon->max_bytes_chunk));
 
-       cifs_dbg(FYI, "rc %d data length out %d\n", rc, ret_data_len);
+               /* Request server copy to target from src identified by key */
+               rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
+                       trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
+                       true /* is_fsctl */, (char *)pcchunk,
+                       sizeof(struct copychunk_ioctl), (char **)&retbuf,
+                       &ret_data_len);
+               if (rc == 0) {
+                       if (ret_data_len !=
+                                       sizeof(struct copychunk_ioctl_rsp)) {
+                               cifs_dbg(VFS, "invalid cchunk response size\n");
+                               rc = -EIO;
+                               goto cchunk_out;
+                       }
+                       if (retbuf->TotalBytesWritten == 0) {
+                               cifs_dbg(FYI, "no bytes copied\n");
+                               rc = -EIO;
+                               goto cchunk_out;
+                       }
+                       /*
+                        * Check if server claimed to write more than we asked
+                        */
+                       if (le32_to_cpu(retbuf->TotalBytesWritten) >
+                           le32_to_cpu(pcchunk->Length)) {
+                               cifs_dbg(VFS, "invalid copy chunk response\n");
+                               rc = -EIO;
+                               goto cchunk_out;
+                       }
+                       if (le32_to_cpu(retbuf->ChunksWritten) != 1) {
+                               cifs_dbg(VFS, "invalid num chunks written\n");
+                               rc = -EIO;
+                               goto cchunk_out;
+                       }
+                       chunks_copied++;
+
+                       src_off += le32_to_cpu(retbuf->TotalBytesWritten);
+                       dest_off += le32_to_cpu(retbuf->TotalBytesWritten);
+                       len -= le32_to_cpu(retbuf->TotalBytesWritten);
+
+                       cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %d\n",
+                               le32_to_cpu(retbuf->ChunksWritten),
+                               le32_to_cpu(retbuf->ChunkBytesWritten),
+                               le32_to_cpu(retbuf->TotalBytesWritten));
+               } else if (rc == -EINVAL) {
+                       if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
+                               goto cchunk_out;
+
+                       cifs_dbg(FYI, "MaxChunks %d BytesChunk %d MaxCopy %d\n",
+                               le32_to_cpu(retbuf->ChunksWritten),
+                               le32_to_cpu(retbuf->ChunkBytesWritten),
+                               le32_to_cpu(retbuf->TotalBytesWritten));
+
+                       /*
+                        * Check if this is the first request using these sizes,
+                        * (ie check if copy succeed once with original sizes
+                        * and check if the server gave us different sizes after
+                        * we already updated max sizes on previous request).
+                        * if not then why is the server returning an error now
+                        */
+                       if ((chunks_copied != 0) || chunk_sizes_updated)
+                               goto cchunk_out;
+
+                       /* Check that server is not asking us to grow size */
+                       if (le32_to_cpu(retbuf->ChunkBytesWritten) <
+                                       tcon->max_bytes_chunk)
+                               tcon->max_bytes_chunk =
+                                       le32_to_cpu(retbuf->ChunkBytesWritten);
+                       else
+                               goto cchunk_out; /* server gave us bogus size */
+
+                       /* No need to change MaxChunks since already set to 1 */
+                       chunk_sizes_updated = true;
+               }
+       }
 
+cchunk_out:
        kfree(pcchunk);
        return rc;
 }
@@ -1247,6 +1319,7 @@ struct smb_version_operations smb30_operations = {
        .create_lease_buf = smb3_create_lease_buf,
        .parse_lease_buf = smb3_parse_lease_buf,
        .clone_range = smb2_clone_range,
+       .validate_negotiate = smb3_validate_negotiate,
 };
 
 struct smb_version_values smb20_values = {
index d65270c290a1b488157e14b316b7de59fe9bac54..2013234b73adc47a5a34cb907ce0b818f65a16f5 100644 (file)
@@ -454,6 +454,81 @@ neg_exit:
        return rc;
 }
 
+int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
+{
+       int rc = 0;
+       struct validate_negotiate_info_req vneg_inbuf;
+       struct validate_negotiate_info_rsp *pneg_rsp;
+       u32 rsplen;
+
+       cifs_dbg(FYI, "validate negotiate\n");
+
+       /*
+        * validation ioctl must be signed, so no point sending this if we
+        * can not sign it.  We could eventually change this to selectively
+        * sign just this, the first and only signed request on a connection.
+        * This is good enough for now since a user who wants better security
+        * would also enable signing on the mount. Having validation of
+        * negotiate info for signed connections helps reduce attack vectors
+        */
+       if (tcon->ses->server->sign == false)
+               return 0; /* validation requires signing */
+
+       vneg_inbuf.Capabilities =
+                       cpu_to_le32(tcon->ses->server->vals->req_capabilities);
+       memcpy(vneg_inbuf.Guid, cifs_client_guid, SMB2_CLIENT_GUID_SIZE);
+
+       if (tcon->ses->sign)
+               vneg_inbuf.SecurityMode =
+                       cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
+       else if (global_secflags & CIFSSEC_MAY_SIGN)
+               vneg_inbuf.SecurityMode =
+                       cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
+       else
+               vneg_inbuf.SecurityMode = 0;
+
+       vneg_inbuf.DialectCount = cpu_to_le16(1);
+       vneg_inbuf.Dialects[0] =
+               cpu_to_le16(tcon->ses->server->vals->protocol_id);
+
+       rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+               FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
+               (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req),
+               (char **)&pneg_rsp, &rsplen);
+
+       if (rc != 0) {
+               cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc);
+               return -EIO;
+       }
+
+       if (rsplen != sizeof(struct validate_negotiate_info_rsp)) {
+               cifs_dbg(VFS, "invalid size of protocol negotiate response\n");
+               return -EIO;
+       }
+
+       /* check validate negotiate info response matches what we got earlier */
+       if (pneg_rsp->Dialect !=
+                       cpu_to_le16(tcon->ses->server->vals->protocol_id))
+               goto vneg_out;
+
+       if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode))
+               goto vneg_out;
+
+       /* do not validate server guid because not saved at negprot time yet */
+
+       if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND |
+             SMB2_LARGE_FILES) != tcon->ses->server->capabilities)
+               goto vneg_out;
+
+       /* validate negotiate successful */
+       cifs_dbg(FYI, "validate negotiate info successful\n");
+       return 0;
+
+vneg_out:
+       cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
+       return -EIO;
+}
+
 int
 SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
                const struct nls_table *nls_cp)
@@ -829,6 +904,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
            ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
                cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");
        init_copy_chunk_defaults(tcon);
+       if (tcon->ses->server->ops->validate_negotiate)
+               rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
 tcon_exit:
        free_rsp_buf(resp_buftype, rsp);
        kfree(unc_path);
@@ -1214,10 +1291,17 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
        rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base;
 
-       if (rc != 0) {
+       if ((rc != 0) && (rc != -EINVAL)) {
                if (tcon)
                        cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
                goto ioctl_exit;
+       } else if (rc == -EINVAL) {
+               if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) &&
+                   (opcode != FSCTL_SRV_COPYCHUNK)) {
+                       if (tcon)
+                               cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
+                       goto ioctl_exit;
+               }
        }
 
        /* check if caller wants to look at return data or just return rc */
@@ -2154,11 +2238,9 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
        rc = SendReceive2(xid, ses, iov, num, &resp_buftype, 0);
        rsp = (struct smb2_set_info_rsp *)iov[0].iov_base;
 
-       if (rc != 0) {
+       if (rc != 0)
                cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE);
-               goto out;
-       }
-out:
+
        free_rsp_buf(resp_buftype, rsp);
        kfree(iov);
        return rc;
index f88320bbb47772923fe81f89b1a2352d783b89c0..2022c542ea3aa65ddf15cf511ee652d3040b73a2 100644 (file)
@@ -577,13 +577,19 @@ struct copychunk_ioctl_rsp {
        __le32 TotalBytesWritten;
 } __packed;
 
-/* Response and Request are the same format */
-struct validate_negotiate_info {
+struct validate_negotiate_info_req {
        __le32 Capabilities;
        __u8   Guid[SMB2_CLIENT_GUID_SIZE];
        __le16 SecurityMode;
        __le16 DialectCount;
-       __le16 Dialect[1];
+       __le16 Dialects[1]; /* dialect (someday maybe list) client asked for */
+} __packed;
+
+struct validate_negotiate_info_rsp {
+       __le32 Capabilities;
+       __u8   Guid[SMB2_CLIENT_GUID_SIZE];
+       __le16 SecurityMode;
+       __le16 Dialect; /* Dialect in use for the connection */
 } __packed;
 
 #define RSS_CAPABLE    0x00000001
index b4eea105b08cf96b22444d19181ee500a437787f..93adc64666f310345b4c6d76bba628741aa4e634 100644 (file)
@@ -162,5 +162,6 @@ extern int smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
                      struct smb2_lock_element *buf);
 extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
                            __u8 *lease_key, const __le32 lease_state);
+extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
 
 #endif                 /* _SMB2PROTO_H */
index a4b2391fe66e4e11cea93e7396b987c335d43823..0e538b5c96221f61f55f9a8bff58d6d88cfc836b 100644 (file)
@@ -90,7 +90,7 @@
 #define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4 /* BB add struct */
 #define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
 #define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
-#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204 /* BB add struct */
+#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
 /* Perform server-side data movement */
 #define FSCTL_SRV_COPYCHUNK 0x001440F2
 #define FSCTL_SRV_COPYCHUNK_WRITE 0x001480F2
index 4bdb300b16e2e940bab8eeb07417b7f87914815f..6055d61811d30f6d037daed87ffb11924b0ac5e5 100644 (file)
@@ -192,7 +192,7 @@ static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char
                if (!tcount)
                        return 0;
        }
-       mask = ~(~0ul << tcount*8);
+       mask = bytemask_from_count(tcount);
        return unlikely(!!((a ^ b) & mask));
 }
 
index 79b65c3b9e876f1087ccbcf7908a47c18efbbad9..8b5e2584c840903bc9aeffab1a31aa0a2149b595 100644 (file)
@@ -1852,8 +1852,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                goto error_tgt_fput;
 
        /* Check if EPOLLWAKEUP is allowed */
-       if ((epds.events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
-               epds.events &= ~EPOLLWAKEUP;
+       ep_take_care_of_epollwakeup(&epds);
 
        /*
         * We have to check that the file structure underneath the file descriptor
index 288534920fe5cc4960f99ae636777344c5d42db6..20d6697bd6386560a679dda5e8b8592a65d63798 100644 (file)
@@ -1493,6 +1493,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
                                sb->s_blocksize - offset : towrite;
 
                tmp_bh.b_state = 0;
+               tmp_bh.b_size = sb->s_blocksize;
                err = ext2_get_block(inode, blk, &tmp_bh, 1);
                if (err < 0)
                        goto out;
index e6185031c1ccb5d7ef6c35185d77e5b06d648a5d..ece55565b9cd35575c454d44656c63321d89e0f9 100644 (file)
@@ -268,6 +268,16 @@ struct ext4_io_submit {
 /* Translate # of blks to # of clusters */
 #define EXT4_NUM_B2C(sbi, blks)        (((blks) + (sbi)->s_cluster_ratio - 1) >> \
                                 (sbi)->s_cluster_bits)
+/* Mask out the low bits to get the starting block of the cluster */
+#define EXT4_PBLK_CMASK(s, pblk) ((pblk) &                             \
+                                 ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_CMASK(s, lblk) ((lblk) &                             \
+                                 ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
+/* Get the cluster offset */
+#define EXT4_PBLK_COFF(s, pblk) ((pblk) &                              \
+                                ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_COFF(s, lblk) ((lblk) &                              \
+                                ((ext4_lblk_t) (s)->s_cluster_ratio - 1))
 
 /*
  * Structure of a blocks group descriptor
index 17ac112ab1012bd88ff32d145f27a29f025efdde..3fe29de832c825e390b8d59d818b5ec37a8eb61f 100644 (file)
@@ -259,6 +259,15 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                if (WARN_ON_ONCE(err)) {
                        ext4_journal_abort_handle(where, line, __func__, bh,
                                                  handle, err);
+                       ext4_error_inode(inode, where, line,
+                                        bh->b_blocknr,
+                                        "journal_dirty_metadata failed: "
+                                        "handle type %u started at line %u, "
+                                        "credits %u/%u, errcode %d",
+                                        handle->h_type,
+                                        handle->h_line_no,
+                                        handle->h_requested_credits,
+                                        handle->h_buffer_credits, err);
                }
        } else {
                if (inode)
index 35f65cf4f318d72bce4e79995ddbc85d0e4bbfa3..4410cc3d6ee2cc817f947e09475e565cebb07211 100644 (file)
@@ -360,8 +360,10 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
 {
        ext4_fsblk_t block = ext4_ext_pblock(ext);
        int len = ext4_ext_get_actual_len(ext);
+       ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
+       ext4_lblk_t last = lblock + len - 1;
 
-       if (len == 0)
+       if (lblock > last)
                return 0;
        return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -387,11 +389,26 @@ static int ext4_valid_extent_entries(struct inode *inode,
        if (depth == 0) {
                /* leaf entries */
                struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+               struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+               ext4_fsblk_t pblock = 0;
+               ext4_lblk_t lblock = 0;
+               ext4_lblk_t prev = 0;
+               int len = 0;
                while (entries) {
                        if (!ext4_valid_extent(inode, ext))
                                return 0;
+
+                       /* Check for overlapping extents */
+                       lblock = le32_to_cpu(ext->ee_block);
+                       len = ext4_ext_get_actual_len(ext);
+                       if ((lblock <= prev) && prev) {
+                               pblock = ext4_ext_pblock(ext);
+                               es->s_last_error_block = cpu_to_le64(pblock);
+                               return 0;
+                       }
                        ext++;
                        entries--;
+                       prev = lblock + len - 1;
                }
        } else {
                struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
@@ -1834,8 +1851,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
        depth = ext_depth(inode);
        if (!path[depth].p_ext)
                goto out;
-       b2 = le32_to_cpu(path[depth].p_ext->ee_block);
-       b2 &= ~(sbi->s_cluster_ratio - 1);
+       b2 = EXT4_LBLK_CMASK(sbi, le32_to_cpu(path[depth].p_ext->ee_block));
 
        /*
         * get the next allocated block if the extent in the path
@@ -1845,7 +1861,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
                b2 = ext4_ext_next_allocated_block(path);
                if (b2 == EXT_MAX_BLOCKS)
                        goto out;
-               b2 &= ~(sbi->s_cluster_ratio - 1);
+               b2 = EXT4_LBLK_CMASK(sbi, b2);
        }
 
        /* check for wrap through zero on extent logical start block*/
@@ -2504,7 +2520,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
                 * extent, we have to mark the cluster as used (store negative
                 * cluster number in partial_cluster).
                 */
-               unaligned = pblk & (sbi->s_cluster_ratio - 1);
+               unaligned = EXT4_PBLK_COFF(sbi, pblk);
                if (unaligned && (ee_len == num) &&
                    (*partial_cluster != -((long long)EXT4_B2C(sbi, pblk))))
                        *partial_cluster = EXT4_B2C(sbi, pblk);
@@ -2598,7 +2614,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                         * accidentally freeing it later on
                         */
                        pblk = ext4_ext_pblock(ex);
-                       if (pblk & (sbi->s_cluster_ratio - 1))
+                       if (EXT4_PBLK_COFF(sbi, pblk))
                                *partial_cluster =
                                        -((long long)EXT4_B2C(sbi, pblk));
                        ex--;
@@ -3753,7 +3769,7 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        ext4_lblk_t lblk_start, lblk_end;
-       lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
+       lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
        lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
 
        return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
@@ -3812,9 +3828,9 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
 
        /* Check towards left side */
-       c_offset = lblk_start & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start);
        if (c_offset) {
-               lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
+               lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start);
                lblk_to = lblk_from + c_offset - 1;
 
                if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
@@ -3822,7 +3838,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        }
 
        /* Now check towards right. */
-       c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start + num_blks);
        if (allocated_clusters && c_offset) {
                lblk_from = lblk_start + num_blks;
                lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
@@ -4030,7 +4046,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
                                     struct ext4_ext_path *path)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       ext4_lblk_t c_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ext4_lblk_t ex_cluster_start, ex_cluster_end;
        ext4_lblk_t rr_cluster_start;
        ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
@@ -4048,8 +4064,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
            (rr_cluster_start == ex_cluster_start)) {
                if (rr_cluster_start == ex_cluster_end)
                        ee_start += ee_len - 1;
-               map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
-                       c_offset;
+               map->m_pblk = EXT4_PBLK_CMASK(sbi, ee_start) + c_offset;
                map->m_len = min(map->m_len,
                                 (unsigned) sbi->s_cluster_ratio - c_offset);
                /*
@@ -4203,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         */
        map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
        newex.ee_block = cpu_to_le32(map->m_lblk);
-       cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       cluster_offset = EXT4_LBLK_CMASK(sbi, map->m_lblk);
 
        /*
         * If we are doing bigalloc, check to see if the extent returned
@@ -4271,7 +4286,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         * needed so that future calls to get_implied_cluster_alloc()
         * work correctly.
         */
-       offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
+       offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
        ar.goal -= offset;
        ar.logical -= offset;
index 0757634741187a568cc2255187bcd2cf250d852b..61d49ff22c81f844cb8bc6324ad3aa70d649fb7b 100644 (file)
@@ -1206,7 +1206,6 @@ static int ext4_journalled_write_end(struct file *file,
  */
 static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1218,7 +1217,6 @@ static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1238,10 +1236,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                return -ENOSPC;
        }
        ei->i_reserved_meta_blocks += md_needed;
@@ -1255,7 +1249,6 @@ repeat:
  */
 static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1277,7 +1270,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1297,10 +1289,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
                return -ENOSPC;
        }
index 4d113efa024c8439f4000a0fa59ed643f2489166..04a5c7504be9d6dbe55174d451f559064a7a05cf 100644 (file)
@@ -3442,6 +3442,9 @@ static void ext4_mb_pa_callback(struct rcu_head *head)
 {
        struct ext4_prealloc_space *pa;
        pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu);
+
+       BUG_ON(atomic_read(&pa->pa_count));
+       BUG_ON(pa->pa_deleted == 0);
        kmem_cache_free(ext4_pspace_cachep, pa);
 }
 
@@ -3455,11 +3458,13 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
        ext4_group_t grp;
        ext4_fsblk_t grp_blk;
 
-       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
-               return;
-
        /* in this short window concurrent discard can set pa_deleted */
        spin_lock(&pa->pa_lock);
+       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
+               spin_unlock(&pa->pa_lock);
+               return;
+       }
+
        if (pa->pa_deleted == 1) {
                spin_unlock(&pa->pa_lock);
                return;
@@ -4121,7 +4126,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
        ext4_get_group_no_and_offset(sb, goal, &group, &block);
 
        /* set up allocation goals */
-       ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
+       ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);
        ac->ac_status = AC_STATUS_CONTINUE;
        ac->ac_sb = sb;
        ac->ac_inode = ar->inode;
@@ -4663,7 +4668,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
         * blocks at the beginning or the end unless we are explicitly
         * requested to avoid doing so.
         */
-       overflow = block & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_PBLK_COFF(sbi, block);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
                        overflow = sbi->s_cluster_ratio - overflow;
@@ -4677,7 +4682,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
                        count += overflow;
                }
        }
-       overflow = count & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_LBLK_COFF(sbi, count);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
                        if (count > overflow)
index c977f4e4e63be6c4cf3b477f628e4fc7d323d1f5..1f7784de05b6c6afad4d7437202ceb6efeec3399 100644 (file)
@@ -792,7 +792,7 @@ static void ext4_put_super(struct super_block *sb)
        }
 
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        ext4_release_system_zone(sb);
        ext4_mb_release(sb);
        ext4_ext_release(sb);
@@ -3316,10 +3316,18 @@ int ext4_calculate_overhead(struct super_block *sb)
 }
 
 
-static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
+static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
 
+       /*
+        * There's no need to reserve anything when we aren't using extents.
+        * The space estimates are exact, there are no unwritten extents,
+        * hole punching doesn't need new metadata... This is needed especially
+        * to keep ext2/3 backward compatibility.
+        */
+       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+               return 0;
        /*
         * By default we reserve 2% or 4096 clusters, whichever is smaller.
         * This should cover the situations where we can not afford to run
@@ -3328,7 +3336,8 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
         * allocation would require 1, or 2 blocks, higher numbers are
         * very rare.
         */
-       resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
+       resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
+                       EXT4_SB(sb)->s_cluster_bits;
 
        do_div(resv_clusters, 50);
        resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
@@ -4071,10 +4080,10 @@ no_journal:
                         "available");
        }
 
-       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi));
+       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
-                        "reserved pool", ext4_calculate_resv_clusters(sbi));
+                        "reserved pool", ext4_calculate_resv_clusters(sb));
                goto failed_mount4a;
        }
 
@@ -4184,7 +4193,7 @@ failed_mount_wq:
        }
 failed_mount3:
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        if (sbi->s_flex_groups)
                ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
index b51a6079108d1d4fa4a696b222a63c6634b0a36c..e9a97a0d431480616043410a51567730bebafda3 100644 (file)
@@ -24,13 +24,6 @@ struct hfsplus_wd {
        u16 embed_count;
 };
 
-static void hfsplus_end_io_sync(struct bio *bio, int err)
-{
-       if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       complete(bio->bi_private);
-}
-
 /*
  * hfsplus_submit_bio - Perfrom block I/O
  * @sb: super block of volume for I/O
@@ -53,7 +46,6 @@ static void hfsplus_end_io_sync(struct bio *bio, int err)
 int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
                void *buf, void **data, int rw)
 {
-       DECLARE_COMPLETION_ONSTACK(wait);
        struct bio *bio;
        int ret = 0;
        u64 io_size;
@@ -73,8 +65,6 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
        bio = bio_alloc(GFP_NOIO, 1);
        bio->bi_sector = sector;
        bio->bi_bdev = sb->s_bdev;
-       bio->bi_end_io = hfsplus_end_io_sync;
-       bio->bi_private = &wait;
 
        if (!(rw & WRITE) && data)
                *data = (u8 *)buf + offset;
@@ -93,12 +83,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
                buf = (u8 *)buf + len;
        }
 
-       submit_bio(rw, bio);
-       wait_for_completion(&wait);
-
-       if (!bio_flagged(bio, BIO_UPTODATE))
-               ret = -EIO;
-
+       ret = submit_bio_wait(rw, bio);
 out:
        bio_put(bio);
        return ret < 0 ? ret : 0;
index 52032647dd4a32f7c8efaea95227634071f8d7d3..5fa344afb49ae8642be889ce2b3f69d176af548e 100644 (file)
@@ -702,7 +702,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        read_lock(&journal->j_state_lock);
 #ifdef CONFIG_JBD2_DEBUG
        if (!tid_geq(journal->j_commit_request, tid)) {
-               printk(KERN_EMERG
+               printk(KERN_ERR
                       "%s: error: j_commit_request=%d, tid=%d\n",
                       __func__, journal->j_commit_request, tid);
        }
@@ -718,10 +718,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        }
        read_unlock(&journal->j_state_lock);
 
-       if (unlikely(is_journal_aborted(journal))) {
-               printk(KERN_EMERG "journal commit I/O error\n");
+       if (unlikely(is_journal_aborted(journal)))
                err = -EIO;
-       }
        return err;
 }
 
@@ -1527,13 +1525,13 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
            JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                /* Can't have checksum v1 and v2 on at the same time! */
-               printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
+               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
                       "at the same time!\n");
                goto out;
        }
 
        if (!jbd2_verify_csum_type(journal, sb)) {
-               printk(KERN_ERR "JBD: Unknown checksum type\n");
+               printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
        }
 
@@ -1541,7 +1539,7 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
                if (IS_ERR(journal->j_chksum_driver)) {
-                       printk(KERN_ERR "JBD: Cannot load crc32c driver.\n");
+                       printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
                        err = PTR_ERR(journal->j_chksum_driver);
                        journal->j_chksum_driver = NULL;
                        goto out;
@@ -1550,7 +1548,7 @@ static int journal_get_superblock(journal_t *journal)
 
        /* Check superblock checksum */
        if (!jbd2_superblock_csum_verify(journal, sb)) {
-               printk(KERN_ERR "JBD: journal checksum error\n");
+               printk(KERN_ERR "JBD2: journal checksum error\n");
                goto out;
        }
 
@@ -1836,7 +1834,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                        journal->j_chksum_driver = crypto_alloc_shash("crc32c",
                                                                      0, 0);
                        if (IS_ERR(journal->j_chksum_driver)) {
-                               printk(KERN_ERR "JBD: Cannot load crc32c "
+                               printk(KERN_ERR "JBD2: Cannot load crc32c "
                                       "driver.\n");
                                journal->j_chksum_driver = NULL;
                                return 0;
@@ -2645,7 +2643,7 @@ static void __exit journal_exit(void)
 #ifdef CONFIG_JBD2_DEBUG
        int n = atomic_read(&nr_journal_heads);
        if (n)
-               printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
+               printk(KERN_ERR "JBD2: leaked %d journal_heads!\n", n);
 #endif
        jbd2_remove_jbd_stats_proc_entry();
        jbd2_journal_destroy_caches();
index 3929c50428b1a289d4024fcbe673276f63ff97c0..3b6bb19d60b17abceadec4c38df5d3570c0fcba9 100644 (file)
@@ -594,7 +594,7 @@ static int do_one_pass(journal_t *journal,
                                                be32_to_cpu(tmp->h_sequence))) {
                                                brelse(obh);
                                                success = -EIO;
-                                               printk(KERN_ERR "JBD: Invalid "
+                                               printk(KERN_ERR "JBD2: Invalid "
                                                       "checksum recovering "
                                                       "block %llu in log\n",
                                                       blocknr);
index 7aa9a32573bba885d166e484c367bffc06bcd9e2..8360674c85bcb98af88d6aaff3ee4c46fe6f31bf 100644 (file)
@@ -932,7 +932,7 @@ repeat:
                                        jbd2_alloc(jh2bh(jh)->b_size,
                                                         GFP_NOFS);
                                if (!frozen_buffer) {
-                                       printk(KERN_EMERG
+                                       printk(KERN_ERR
                                               "%s: OOM for frozen_buffer\n",
                                               __func__);
                                        JBUFFER_TRACE(jh, "oom!");
@@ -1166,7 +1166,7 @@ repeat:
        if (!jh->b_committed_data) {
                committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
-                       printk(KERN_EMERG "%s: No memory for committed data\n",
+                       printk(KERN_ERR "%s: No memory for committed data\n",
                                __func__);
                        err = -ENOMEM;
                        goto out;
@@ -1290,7 +1290,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                 * once a transaction -bzzz
                 */
                jh->b_modified = 1;
-               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+               if (handle->h_buffer_credits <= 0) {
+                       ret = -ENOSPC;
+                       goto out_unlock_bh;
+               }
                handle->h_buffer_credits--;
        }
 
@@ -1305,7 +1308,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "fastpath");
                if (unlikely(jh->b_transaction !=
                             journal->j_running_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_running_transaction (%p, %u)",
                               journal->j_devname,
@@ -1332,7 +1335,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "already on other transaction");
                if (unlikely(jh->b_transaction !=
                             journal->j_committing_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_committing_transaction (%p, %u)",
                               journal->j_devname,
@@ -1345,7 +1348,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                        ret = -EINVAL;
                }
                if (unlikely(jh->b_next_transaction != transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_next_transaction (%llu, %p, %u) != "
                               "transaction (%p, %u)",
                               journal->j_devname,
@@ -1373,7 +1376,6 @@ out_unlock_bh:
        jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
-       WARN_ON(ret);   /* All errors are bugs, so dump the stack */
        return ret;
 }
 
index 550475ca6a0e0ec35c82d90b10372f2e4434fe90..0f95f0d0b3133e9b3129e3807a842438e162a245 100644 (file)
 
 #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
 
-static void request_complete(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static int sync_request(struct page *page, struct block_device *bdev, int rw)
 {
        struct bio bio;
        struct bio_vec bio_vec;
-       struct completion complete;
 
        bio_init(&bio);
        bio.bi_max_vecs = 1;
@@ -35,13 +29,8 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw)
        bio.bi_size = PAGE_SIZE;
        bio.bi_bdev = bdev;
        bio.bi_sector = page->index * (PAGE_SIZE >> 9);
-       init_completion(&complete);
-       bio.bi_private = &complete;
-       bio.bi_end_io = request_complete;
 
-       submit_bio(rw, &bio);
-       wait_for_completion(&complete);
-       return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+       return submit_bio_wait(rw, &bio);
 }
 
 static int bdev_readpage(void *_sb, struct page *page)
index 8f77a8cea289350b9d0e427b284cc01a2df4691d..3531deebad3084104e6a9fca7116ba68890ad5af 100644 (file)
@@ -513,8 +513,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
 
        if (!lockref_get_not_dead(&parent->d_lockref)) {
                nd->path.dentry = NULL; 
-               rcu_read_unlock();
-               return -ECHILD;
+               goto out;
        }
 
        /*
@@ -1599,11 +1598,6 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
  *   do a "get_unaligned()" if this helps and is sufficiently
  *   fast.
  *
- * - Little-endian machines (so that we can generate the mask
- *   of low bytes efficiently). Again, we *could* do a byte
- *   swapping load on big-endian architectures if that is not
- *   expensive enough to make the optimization worthless.
- *
  * - non-CONFIG_DEBUG_PAGEALLOC configurations (so that we
  *   do not trap on the (extremely unlikely) case of a page
  *   crossing operation.
@@ -1647,7 +1641,7 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
                if (!len)
                        goto done;
        }
-       mask = ~(~0ul << len*8);
+       mask = bytemask_from_count(len);
        hash += mask & a;
 done:
        return fold_hash(hash);
index 8485978993e85bcbda9772b55a2ed26f5442a228..9838fb020473c935817b34da4a1127b4c75af3fe 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
+#include "../nfs4_fs.h"
 #include "../pnfs.h"
 #include "../netns.h"
 
index 9c3e117c3ed1f04c5dd1650f70a3aa4ca2fd7d8c..4d01614425658adade20f579ec7f10e44c5d5a15 100644 (file)
@@ -44,7 +44,7 @@
 static inline sector_t normalize(sector_t s, int base)
 {
        sector_t tmp = s; /* Since do_div modifies its argument */
-       return s - do_div(tmp, base);
+       return s - sector_div(tmp, base);
 }
 
 static inline sector_t normalize_up(sector_t s, int base)
index fc0f95ec73587f9fbcfa7fca24438da29012b5b9..d25f10fb4926b09dc39ac3f6f62a433d4bcdc58b 100644 (file)
@@ -46,7 +46,9 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
 #include <linux/sunrpc/cache.h>
 #include <linux/sunrpc/svcauth.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
+#include <linux/nfs_fs.h>
 
+#include "nfs4_fs.h"
 #include "dns_resolve.h"
 #include "cache_lib.h"
 #include "netns.h"
index 18ab2da4eeb65dbf7c8f7d7b578a35fc5251b0b6..00ad1c2b217ded2338c0ac4154681f83963581ab 100644 (file)
@@ -312,7 +312,7 @@ struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags)
 }
 EXPORT_SYMBOL_GPL(nfs4_label_alloc);
 #else
-void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        struct nfs4_label *label)
 {
 }
index bca6a3e3c49ce58e9cdfa1552e25afce2158584e..8b5cc04a86115e05f0a2e98e9b02a0b307b1b910 100644 (file)
@@ -269,6 +269,21 @@ extern const u32 nfs41_maxgetdevinfo_overhead;
 extern struct rpc_procinfo nfs4_procedures[];
 #endif
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
+static inline void nfs4_label_free(struct nfs4_label *label)
+{
+       if (label) {
+               kfree(label->label);
+               kfree(label);
+       }
+       return;
+}
+#else
+static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
+static inline void nfs4_label_free(void *label) {}
+#endif /* CONFIG_NFS_V4_SECURITY_LABEL */
+
 /* proc.c */
 void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
 extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
index 3ce79b04522eb19b2ecee294c3a59a2b0c49b4b9..5609edc742a0fc42568c73e7d26b4c2feb336c33 100644 (file)
@@ -9,6 +9,14 @@
 #ifndef __LINUX_FS_NFS_NFS4_FS_H
 #define __LINUX_FS_NFS_NFS4_FS_H
 
+#if defined(CONFIG_NFS_V4_2)
+#define NFS4_MAX_MINOR_VERSION 2
+#elif defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MINOR_VERSION 1
+#else
+#define NFS4_MAX_MINOR_VERSION 0
+#endif
+
 #if IS_ENABLED(CONFIG_NFS_V4)
 
 #define NFS4_MAX_LOOP_ON_RECOVER (10)
index 659990c0109e3173298b92385d585be566e161de..15052b81df4245e4f797adb0d0b2e523338b23cc 100644 (file)
@@ -2518,9 +2518,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                                                     calldata->roc_barrier);
                        nfs_set_open_stateid(state, &calldata->res.stateid, 0);
                        renew_lease(server, calldata->timestamp);
-                       nfs4_close_clear_stateid_flags(state,
-                                       calldata->arg.fmode);
                        break;
+               case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_OLD_STATEID:
                case -NFS4ERR_BAD_STATEID:
@@ -2528,9 +2527,13 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                        if (calldata->arg.fmode == 0)
                                break;
                default:
-                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
+                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
                                rpc_restart_call_prepare(task);
+                               goto out_release;
+                       }
        }
+       nfs4_close_clear_stateid_flags(state, calldata->arg.fmode);
+out_release:
        nfs_release_seqid(calldata->arg.seqid);
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
        dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
@@ -4802,7 +4805,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        dprintk("%s ERROR %d, Reset session\n", __func__,
                                task->tk_status);
                        nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
-                       goto restart_call;
+                       goto wait_on_recovery;
 #endif /* CONFIG_NFS_V4_1 */
                case -NFS4ERR_DELAY:
                        nfs_inc_server_stats(server, NFSIOS_DELAY);
@@ -4987,11 +4990,17 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 
        trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
        switch (task->tk_status) {
-       case -NFS4ERR_STALE_STATEID:
-       case -NFS4ERR_EXPIRED:
        case 0:
                renew_lease(data->res.server, data->timestamp);
                break;
+       case -NFS4ERR_ADMIN_REVOKED:
+       case -NFS4ERR_DELEG_REVOKED:
+       case -NFS4ERR_BAD_STATEID:
+       case -NFS4ERR_OLD_STATEID:
+       case -NFS4ERR_STALE_STATEID:
+       case -NFS4ERR_EXPIRED:
+               task->tk_status = 0;
+               break;
        default:
                if (nfs4_async_handle_error(task, data->res.server, NULL) ==
                                -EAGAIN) {
@@ -7589,7 +7598,14 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
                return;
 
        server = NFS_SERVER(lrp->args.inode);
-       if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+       switch (task->tk_status) {
+       default:
+               task->tk_status = 0;
+       case 0:
+               break;
+       case -NFS4ERR_DELAY:
+               if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN)
+                       break;
                rpc_restart_call_prepare(task);
                return;
        }
index 9186c7ce0b141b187a8b127a6608005a05ad53d1..b6af150c96b8cdf616950c1bd0f4f8403eeae5c8 100644 (file)
@@ -131,6 +131,13 @@ nfsd_reply_cache_alloc(void)
        return rp;
 }
 
+static void
+nfsd_reply_cache_unhash(struct svc_cacherep *rp)
+{
+       hlist_del_init(&rp->c_hash);
+       list_del_init(&rp->c_lru);
+}
+
 static void
 nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
 {
@@ -417,7 +424,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
                rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
                if (nfsd_cache_entry_expired(rp) ||
                    num_drc_entries >= max_drc_entries) {
-                       lru_put_end(rp);
+                       nfsd_reply_cache_unhash(rp);
                        prune_cache_entries();
                        goto search_cache;
                }
index d2c45e14e6d8126e41bc6c463a509e68946e9fa4..0e0752ef27159f6183dabc1749e49fca8494319a 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -726,11 +726,25 @@ pipe_poll(struct file *filp, poll_table *wait)
        return mask;
 }
 
+static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
+{
+       int kill = 0;
+
+       spin_lock(&inode->i_lock);
+       if (!--pipe->files) {
+               inode->i_pipe = NULL;
+               kill = 1;
+       }
+       spin_unlock(&inode->i_lock);
+
+       if (kill)
+               free_pipe_info(pipe);
+}
+
 static int
 pipe_release(struct inode *inode, struct file *file)
 {
-       struct pipe_inode_info *pipe = inode->i_pipe;
-       int kill = 0;
+       struct pipe_inode_info *pipe = file->private_data;
 
        __pipe_lock(pipe);
        if (file->f_mode & FMODE_READ)
@@ -743,17 +757,9 @@ pipe_release(struct inode *inode, struct file *file)
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
-       spin_lock(&inode->i_lock);
-       if (!--pipe->files) {
-               inode->i_pipe = NULL;
-               kill = 1;
-       }
-       spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
 
-       if (kill)
-               free_pipe_info(pipe);
-
+       put_pipe_info(inode, pipe);
        return 0;
 }
 
@@ -1014,7 +1020,6 @@ static int fifo_open(struct inode *inode, struct file *filp)
 {
        struct pipe_inode_info *pipe;
        bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
-       int kill = 0;
        int ret;
 
        filp->f_version = 0;
@@ -1130,15 +1135,9 @@ err_wr:
        goto err;
 
 err:
-       spin_lock(&inode->i_lock);
-       if (!--pipe->files) {
-               inode->i_pipe = NULL;
-               kill = 1;
-       }
-       spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
-       if (kill)
-               free_pipe_info(pipe);
+
+       put_pipe_info(inode, pipe);
        return ret;
 }
 
index 28955d4b7218e95a6ba7666111459b0382450786..124fc43c709088a46b26c90a16e251a2fd7c4f66 100644 (file)
@@ -292,16 +292,20 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
 {
        struct proc_dir_entry *pde = PDE(file_inode(file));
        unsigned long rv = -EIO;
-       unsigned long (*get_area)(struct file *, unsigned long, unsigned long,
-                                 unsigned long, unsigned long) = NULL;
+
        if (use_pde(pde)) {
+               typeof(proc_reg_get_unmapped_area) *get_area;
+
+               get_area = pde->proc_fops->get_unmapped_area;
 #ifdef CONFIG_MMU
-               get_area = current->mm->get_unmapped_area;
+               if (!get_area)
+                       get_area = current->mm->get_unmapped_area;
 #endif
-               if (pde->proc_fops->get_unmapped_area)
-                       get_area = pde->proc_fops->get_unmapped_area;
+
                if (get_area)
                        rv = get_area(file, orig_addr, len, pgoff, flags);
+               else
+                       rv = orig_addr;
                unuse_pde(pde);
        }
        return rv;
index b8e93a40a5d3342767a26959858d24f2a24274c0..78c3c2097787a1be2ea2bd1757a6c6e5554df72c 100644 (file)
@@ -443,8 +443,11 @@ int pstore_register(struct pstore_info *psi)
                pstore_get_records(0);
 
        kmsg_dump_register(&pstore_dumper);
-       pstore_register_console();
-       pstore_register_ftrace();
+
+       if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
+               pstore_register_console();
+               pstore_register_ftrace();
+       }
 
        if (pstore_update_ms >= 0) {
                pstore_timer.expires = jiffies +
index 2943b2bfae482ac83d352f317af4c074ce6597ae..62a0de6632e1aa3c8de599e19db3f8d7e2a383e2 100644 (file)
@@ -84,6 +84,9 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
                 */
                res = squashfs_read_cache(target_page, block, bsize, pages,
                                                                page);
+               if (res < 0)
+                       goto mark_errored;
+
                goto out;
        }
 
@@ -119,7 +122,7 @@ mark_errored:
         * dealt with by the caller
         */
        for (i = 0; i < pages; i++) {
-               if (page[i] == target_page)
+               if (page[i] == NULL || page[i] == target_page)
                        continue;
                flush_dcache_page(page[i]);
                SetPageError(page[i]);
index 79b5da2acbe184353475f53ccb03793404bd3563..35e7d08fe629dfcb79553bcdcdf39af03b5e4960 100644 (file)
@@ -649,7 +649,23 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        if (!of)
                goto err_out;
 
-       mutex_init(&of->mutex);
+       /*
+        * The following is done to give a different lockdep key to
+        * @of->mutex for files which implement mmap.  This is a rather
+        * crude way to avoid false positive lockdep warning around
+        * mm->mmap_sem - mmap nests @of->mutex under mm->mmap_sem and
+        * reading /sys/block/sda/trace/act_mask grabs sr_mutex, under
+        * which mm->mmap_sem nests, while holding @of->mutex.  As each
+        * open file has a separate mutex, it's okay as long as those don't
+        * happen on the same file.  At this point, we can't easily give
+        * each file a separate locking class.  Let's differentiate on
+        * whether the file is bin or not for now.
+        */
+       if (sysfs_is_bin(attr_sd))
+               mutex_init(&of->mutex);
+       else
+               mutex_init(&of->mutex);
+
        of->sd = attr_sd;
        of->file = file;
 
index 3ef11b22e7505c380feb6597113d5b150f7b1afb..3b2c14b6f0fb13efd7a3aa89abc05d0a8334a5ff 100644 (file)
@@ -1635,7 +1635,7 @@ xfs_bmap_last_extent(
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
  * at, or past the EOF.
  */
 STATIC int
@@ -1650,9 +1650,14 @@ xfs_bmap_isaeof(
        bma->aeof = 0;
        error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
                                     &is_empty);
-       if (error || is_empty)
+       if (error)
                return error;
 
+       if (is_empty) {
+               bma->aeof = 1;
+               return 0;
+       }
+
        /*
         * Check if we are allocation or past the last extent, or at least into
         * the last delayed allocated extent.
@@ -3643,10 +3648,19 @@ xfs_bmap_btalloc(
        int             isaligned;
        int             tryagain;
        int             error;
+       int             stripe_align;
 
        ASSERT(ap->length);
 
        mp = ap->ip->i_mount;
+
+       /* stripe alignment for allocation is determined by mount parameters */
+       stripe_align = 0;
+       if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+               stripe_align = mp->m_swidth;
+       else if (mp->m_dalign)
+               stripe_align = mp->m_dalign;
+
        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
        if (unlikely(align)) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3655,6 +3669,8 @@ xfs_bmap_btalloc(
                ASSERT(!error);
                ASSERT(ap->length);
        }
+
+
        nullfb = *ap->firstblock == NULLFSBLOCK;
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
        if (nullfb) {
@@ -3730,7 +3746,7 @@ xfs_bmap_btalloc(
         */
        if (!ap->flist->xbf_low && ap->aeof) {
                if (!ap->offset) {
-                       args.alignment = mp->m_dalign;
+                       args.alignment = stripe_align;
                        atype = args.type;
                        isaligned = 1;
                        /*
@@ -3755,13 +3771,13 @@ xfs_bmap_btalloc(
                         * of minlen+alignment+slop doesn't go up
                         * between the calls.
                         */
-                       if (blen > mp->m_dalign && blen <= args.maxlen)
-                               nextminlen = blen - mp->m_dalign;
+                       if (blen > stripe_align && blen <= args.maxlen)
+                               nextminlen = blen - stripe_align;
                        else
                                nextminlen = args.minlen;
-                       if (nextminlen + mp->m_dalign > args.minlen + 1)
+                       if (nextminlen + stripe_align > args.minlen + 1)
                                args.minalignslop =
-                                       nextminlen + mp->m_dalign -
+                                       nextminlen + stripe_align -
                                        args.minlen - 1;
                        else
                                args.minalignslop = 0;
@@ -3783,7 +3799,7 @@ xfs_bmap_btalloc(
                 */
                args.type = atype;
                args.fsbno = ap->blkno;
-               args.alignment = mp->m_dalign;
+               args.alignment = stripe_align;
                args.minlen = nextminlen;
                args.minalignslop = 0;
                isaligned = 1;
index 5887e41c0323ae85f867cc9bc83bbdf8c1e41cd1..1394106ed22db9db61542f5183023f98ef1ca817 100644 (file)
@@ -1187,7 +1187,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNWRITE(bp);
                XFS_BUF_READ(bp);
                XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
@@ -1200,7 +1205,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNDONE(bp);
                XFS_BUF_UNREAD(bp);
                XFS_BUF_WRITE(bp);
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
index c7f0b77dcb0090046b84eda27c68d870af25d45a..afe7645e4b2b8b7746665ed35a0d55da6ce11e3b 100644 (file)
@@ -698,7 +698,11 @@ xfs_buf_read_uncached(
        bp->b_flags |= XBF_READ;
        bp->b_ops = ops;
 
-       xfsbdstrat(target->bt_mount, bp);
+       if (XFS_FORCED_SHUTDOWN(target->bt_mount)) {
+               xfs_buf_relse(bp);
+               return NULL;
+       }
+       xfs_buf_iorequest(bp);
        xfs_buf_iowait(bp);
        return bp;
 }
@@ -1089,7 +1093,7 @@ xfs_bioerror(
  * This is meant for userdata errors; metadata bufs come with
  * iodone functions attached, so that we can track down errors.
  */
-STATIC int
+int
 xfs_bioerror_relse(
        struct xfs_buf  *bp)
 {
@@ -1152,7 +1156,7 @@ xfs_bwrite(
        ASSERT(xfs_buf_islocked(bp));
 
        bp->b_flags |= XBF_WRITE;
-       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
+       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL);
 
        xfs_bdstrat_cb(bp);
 
@@ -1164,25 +1168,6 @@ xfs_bwrite(
        return error;
 }
 
-/*
- * Wrapper around bdstrat so that we can stop data from going to disk in case
- * we are shutting down the filesystem.  Typically user data goes thru this
- * path; one of the exceptions is the superblock.
- */
-void
-xfsbdstrat(
-       struct xfs_mount        *mp,
-       struct xfs_buf          *bp)
-{
-       if (XFS_FORCED_SHUTDOWN(mp)) {
-               trace_xfs_bdstrat_shut(bp, _RET_IP_);
-               xfs_bioerror_relse(bp);
-               return;
-       }
-
-       xfs_buf_iorequest(bp);
-}
-
 STATIC void
 _xfs_buf_ioend(
        xfs_buf_t               *bp,
@@ -1516,6 +1501,12 @@ xfs_wait_buftarg(
                        struct xfs_buf *bp;
                        bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
                        list_del_init(&bp->b_lru);
+                       if (bp->b_flags & XBF_WRITE_FAIL) {
+                               xfs_alert(btp->bt_mount,
+"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
+"Please run xfs_repair to determine the extent of the problem.",
+                                       (long long)bp->b_bn);
+                       }
                        xfs_buf_rele(bp);
                }
                if (loop++ != 0)
@@ -1799,7 +1790,7 @@ __xfs_buf_delwri_submit(
 
        blk_start_plug(&plug);
        list_for_each_entry_safe(bp, n, io_list, b_list) {
-               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC);
+               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL);
                bp->b_flags |= XBF_WRITE;
 
                if (!wait) {
index e65683361017745eff61e245ee72896d2e6ff8df..1cf21a4a9f221de465299bf820fa710c3b3aa40e 100644 (file)
@@ -45,6 +45,7 @@ typedef enum {
 #define XBF_ASYNC       (1 << 4) /* initiator will not wait for completion */
 #define XBF_DONE        (1 << 5) /* all pages in the buffer uptodate */
 #define XBF_STALE       (1 << 6) /* buffer has been staled, do not find it */
+#define XBF_WRITE_FAIL  (1 << 24)/* async writes have failed on this buffer */
 
 /* I/O hints for the BIO layer */
 #define XBF_SYNCIO      (1 << 10)/* treat this buffer as synchronous I/O */
@@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t;
        { XBF_ASYNC,            "ASYNC" }, \
        { XBF_DONE,             "DONE" }, \
        { XBF_STALE,            "STALE" }, \
+       { XBF_WRITE_FAIL,       "WRITE_FAIL" }, \
        { XBF_SYNCIO,           "SYNCIO" }, \
        { XBF_FUA,              "FUA" }, \
        { XBF_FLUSH,            "FLUSH" }, \
@@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t;
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
        { _XBF_COMPOUND,        "COMPOUND" }
 
+
 /*
  * Internal state flags.
  */
@@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *);
 
 /* Buffer Read and Write Routines */
 extern int xfs_bwrite(struct xfs_buf *bp);
-
-extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
-
 extern void xfs_buf_ioend(xfs_buf_t *, int);
 extern void xfs_buf_ioerror(xfs_buf_t *, int);
 extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
@@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 #define xfs_buf_zero(bp, off, len) \
            xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
 
+extern int xfs_bioerror_relse(struct xfs_buf *);
+
 static inline int xfs_buf_geterror(xfs_buf_t *bp)
 {
        return bp ? bp->b_error : ENOMEM;
@@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void);
 
 #define XFS_BUF_ZEROFLAGS(bp) \
        ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \
-                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
+                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \
+                           XBF_WRITE_FAIL))
 
 void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNSTALE(bp)    ((bp)->b_flags &= ~XBF_STALE)
index a64f67ba25d3c99c748e1d4a8f84f7648e3dd651..2227b9b050bb30248d986b343dd33e42c7978529 100644 (file)
@@ -496,6 +496,14 @@ xfs_buf_item_unpin(
        }
 }
 
+/*
+ * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30
+ * seconds so as to not spam logs too much on repeated detection of the same
+ * buffer being bad..
+ */
+
+DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
+
 STATIC uint
 xfs_buf_item_push(
        struct xfs_log_item     *lip,
@@ -524,6 +532,14 @@ xfs_buf_item_push(
 
        trace_xfs_buf_item_push(bip);
 
+       /* has a previous flush failed due to IO errors? */
+       if ((bp->b_flags & XBF_WRITE_FAIL) &&
+           ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
+               xfs_warn(bp->b_target->bt_mount,
+"Detected failing async write on buffer block 0x%llx. Retrying async write.\n",
+                        (long long)bp->b_bn);
+       }
+
        if (!xfs_buf_delwri_queue(bp, buffer_list))
                rval = XFS_ITEM_FLUSHING;
        xfs_buf_unlock(bp);
@@ -1096,8 +1112,9 @@ xfs_buf_iodone_callbacks(
 
                xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
 
-               if (!XFS_BUF_ISSTALE(bp)) {
-                       bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE;
+               if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) {
+                       bp->b_flags |= XBF_WRITE | XBF_ASYNC |
+                                      XBF_DONE | XBF_WRITE_FAIL;
                        xfs_buf_iorequest(bp);
                } else {
                        xfs_buf_relse(bp);
index 56369d4509d5603cff44adeb17902324a547f48b..48c7d18f68c3fb23a89a31a955fc9250fbd63108 100644 (file)
@@ -2067,12 +2067,12 @@ xfs_dir2_node_lookup(
  */
 int                                            /* error */
 xfs_dir2_node_removename(
-       xfs_da_args_t           *args)          /* operation arguments */
+       struct xfs_da_args      *args)          /* operation arguments */
 {
-       xfs_da_state_blk_t      *blk;           /* leaf block */
+       struct xfs_da_state_blk *blk;           /* leaf block */
        int                     error;          /* error return value */
        int                     rval;           /* operation return value */
-       xfs_da_state_t          *state;         /* btree cursor */
+       struct xfs_da_state     *state;         /* btree cursor */
 
        trace_xfs_dir2_node_removename(args);
 
@@ -2084,19 +2084,18 @@ xfs_dir2_node_removename(
        state->mp = args->dp->i_mount;
        state->blocksize = state->mp->m_dirblksize;
        state->node_ents = state->mp->m_dir_node_ents;
-       /*
-        * Look up the entry we're deleting, set up the cursor.
-        */
+
+       /* Look up the entry we're deleting, set up the cursor. */
        error = xfs_da3_node_lookup_int(state, &rval);
        if (error)
-               rval = error;
-       /*
-        * Didn't find it, upper layer screwed up.
-        */
+               goto out_free;
+
+       /* Didn't find it, upper layer screwed up. */
        if (rval != EEXIST) {
-               xfs_da_state_free(state);
-               return rval;
+               error = rval;
+               goto out_free;
        }
+
        blk = &state->path.blk[state->path.active - 1];
        ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
        ASSERT(state->extravalid);
@@ -2107,7 +2106,7 @@ xfs_dir2_node_removename(
        error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
                &state->extrablk, &rval);
        if (error)
-               return error;
+               goto out_free;
        /*
         * Fix the hash values up the btree.
         */
@@ -2122,6 +2121,7 @@ xfs_dir2_node_removename(
         */
        if (!error)
                error = xfs_dir2_node_to_leaf(state);
+out_free:
        xfs_da_state_free(state);
        return error;
 }
index 8367d6dc18c9df7f51cd565e11395cba24929a53..4f11ef0111395bbb7775407e9039e92cad0a932d 100644 (file)
@@ -157,7 +157,7 @@ xfs_ioc_trim(
        struct xfs_mount                *mp,
        struct fstrim_range __user      *urange)
 {
-       struct request_queue    *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
+       struct request_queue    *q = bdev_get_queue(mp->m_ddev_targp->bt_bdev);
        unsigned int            granularity = q->limits.discard_granularity;
        struct fstrim_range     range;
        xfs_daddr_t             start, end, minlen;
@@ -180,7 +180,8 @@ xfs_ioc_trim(
         * matter as trimming blocks is an advisory interface.
         */
        if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) ||
-           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)))
+           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)) ||
+           range.len < mp->m_sb.sb_blocksize)
                return -XFS_ERROR(EINVAL);
 
        start = BTOBB(range.start);
index a6e54b3319bd0f5deb573623f332486590fbe165..02fb943cbf22b36b4e6da8c66b03be8839dc03d4 100644 (file)
@@ -220,6 +220,8 @@ xfs_growfs_data_private(
         */
        nfree = 0;
        for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
+               __be32  *agfl_bno;
+
                /*
                 * AG freespace header block
                 */
@@ -279,8 +281,10 @@ xfs_growfs_data_private(
                        agfl->agfl_seqno = cpu_to_be32(agno);
                        uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid);
                }
+
+               agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, bp);
                for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
-                       agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
+                       agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
 
                error = xfs_bwrite(bp);
                xfs_buf_relse(bp);
index 4d613401a5e056a08dd2f8b21b77833bfe14cbc6..33ad9a77791f7ebbf3f8762e0c9df1af637c5328 100644 (file)
@@ -442,7 +442,8 @@ xfs_attrlist_by_handle(
                return -XFS_ERROR(EPERM);
        if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
                return -XFS_ERROR(EFAULT);
-       if (al_hreq.buflen > XATTR_LIST_MAX)
+       if (al_hreq.buflen < sizeof(struct attrlist) ||
+           al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
        /*
index e8fb1231db8124dc08b2ffbcc551d6bfa1bc21f5..a7992f8de9d3fa53a63ab2d3250f0c4933caded9 100644 (file)
@@ -356,7 +356,8 @@ xfs_compat_attrlist_by_handle(
        if (copy_from_user(&al_hreq, arg,
                           sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
                return -XFS_ERROR(EFAULT);
-       if (al_hreq.buflen > XATTR_LIST_MAX)
+       if (al_hreq.buflen < sizeof(struct attrlist) ||
+           al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
        /*
index 27e0e544e9635ba47281279c68670f7e568a7a58..104455b8046c4bd9ea11855c917b7b46c4573361 100644 (file)
@@ -618,7 +618,8 @@ xfs_setattr_nonsize(
                }
                if (!gid_eq(igid, gid)) {
                        if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
-                               ASSERT(!XFS_IS_PQUOTA_ON(mp));
+                               ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
+                                      !XFS_IS_PQUOTA_ON(mp));
                                ASSERT(mask & ATTR_GID);
                                ASSERT(gdqp);
                                olddquot2 = xfs_qm_vop_chown(tp, ip,
index b6b669df40f3ab335e75cd3a67903601be0128a4..eae16920655b4569af25e9567682019ba301533d 100644 (file)
@@ -193,7 +193,10 @@ xlog_bread_noalign(
        bp->b_io_length = nbblks;
        bp->b_error = 0;
 
-       xfsbdstrat(log->l_mp, bp);
+       if (XFS_FORCED_SHUTDOWN(log->l_mp))
+               return XFS_ERROR(EIO);
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error)
                xfs_buf_ioerror_alert(bp, __func__);
@@ -4397,7 +4400,13 @@ xlog_do_recover(
        XFS_BUF_READ(bp);
        XFS_BUF_UNASYNC(bp);
        bp->b_ops = &xfs_sb_buf_ops;
-       xfsbdstrat(log->l_mp, bp);
+
+       if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
+               xfs_buf_relse(bp);
+               return XFS_ERROR(EIO);
+       }
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error) {
                xfs_buf_ioerror_alert(bp, __func__);
index 14a4996cfec6cb4fbeaa1d3f8432548ebb57d48b..dd88f0e27bd8ce1119d2606c256117d4d2488b9c 100644 (file)
@@ -134,8 +134,6 @@ xfs_qm_dqpurge(
 {
        struct xfs_mount        *mp = dqp->q_mount;
        struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       struct xfs_dquot        *gdqp = NULL;
-       struct xfs_dquot        *pdqp = NULL;
 
        xfs_dqlock(dqp);
        if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -143,21 +141,6 @@ xfs_qm_dqpurge(
                return EAGAIN;
        }
 
-       /*
-        * If this quota has a hint attached, prepare for releasing it now.
-        */
-       gdqp = dqp->q_gdquot;
-       if (gdqp) {
-               xfs_dqlock(gdqp);
-               dqp->q_gdquot = NULL;
-       }
-
-       pdqp = dqp->q_pdquot;
-       if (pdqp) {
-               xfs_dqlock(pdqp);
-               dqp->q_pdquot = NULL;
-       }
-
        dqp->dq_flags |= XFS_DQ_FREEING;
 
        xfs_dqflock(dqp);
@@ -206,11 +189,47 @@ xfs_qm_dqpurge(
        XFS_STATS_DEC(xs_qm_dquot_unused);
 
        xfs_qm_dqdestroy(dqp);
+       return 0;
+}
+
+/*
+ * Release the group or project dquot pointers the user dquots maybe carrying
+ * around as a hint, and proceed to purge the user dquot cache if requested.
+*/
+STATIC int
+xfs_qm_dqpurge_hints(
+       struct xfs_dquot        *dqp,
+       void                    *data)
+{
+       struct xfs_dquot        *gdqp = NULL;
+       struct xfs_dquot        *pdqp = NULL;
+       uint                    flags = *((uint *)data);
+
+       xfs_dqlock(dqp);
+       if (dqp->dq_flags & XFS_DQ_FREEING) {
+               xfs_dqunlock(dqp);
+               return EAGAIN;
+       }
+
+       /* If this quota has a hint attached, prepare for releasing it now */
+       gdqp = dqp->q_gdquot;
+       if (gdqp)
+               dqp->q_gdquot = NULL;
+
+       pdqp = dqp->q_pdquot;
+       if (pdqp)
+               dqp->q_pdquot = NULL;
+
+       xfs_dqunlock(dqp);
 
        if (gdqp)
-               xfs_qm_dqput(gdqp);
+               xfs_qm_dqrele(gdqp);
        if (pdqp)
-               xfs_qm_dqput(pdqp);
+               xfs_qm_dqrele(pdqp);
+
+       if (flags & XFS_QMOPT_UQUOTA)
+               return xfs_qm_dqpurge(dqp, NULL);
+
        return 0;
 }
 
@@ -222,8 +241,18 @@ xfs_qm_dqpurge_all(
        struct xfs_mount        *mp,
        uint                    flags)
 {
-       if (flags & XFS_QMOPT_UQUOTA)
-               xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL);
+       /*
+        * We have to release group/project dquot hint(s) from the user dquot
+        * at first if they are there, otherwise we would run into an infinite
+        * loop while walking through radix tree to purge other type of dquots
+        * since their refcount is not zero if the user dquot refers to them
+        * as hint.
+        *
+        * Call the special xfs_qm_dqpurge_hints() will end up go through the
+        * general xfs_qm_dqpurge() against user dquot cache if requested.
+        */
+       xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags);
+
        if (flags & XFS_QMOPT_GQUOTA)
                xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL);
        if (flags & XFS_QMOPT_PQUOTA)
@@ -2082,24 +2111,21 @@ xfs_qm_vop_create_dqattach(
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
-       if (udqp) {
+       if (udqp && XFS_IS_UQUOTA_ON(mp)) {
                ASSERT(ip->i_udquot == NULL);
-               ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
 
                ip->i_udquot = xfs_qm_dqhold(udqp);
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (gdqp) {
+       if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
                ASSERT(ip->i_gdquot == NULL);
-               ASSERT(XFS_IS_GQUOTA_ON(mp));
                ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
                ip->i_gdquot = xfs_qm_dqhold(gdqp);
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (pdqp) {
+       if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(ip->i_pdquot == NULL);
-               ASSERT(XFS_IS_PQUOTA_ON(mp));
                ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
 
                ip->i_pdquot = xfs_qm_dqhold(pdqp);
index c035d11b7734196c4fd689121d945e598a8d6d7a..647b6f1d8923fee484ada5eea3e2e68d47df8286 100644 (file)
@@ -314,7 +314,18 @@ xfs_trans_read_buf_map(
                        ASSERT(bp->b_iodone == NULL);
                        XFS_BUF_READ(bp);
                        bp->b_ops = ops;
-                       xfsbdstrat(tp->t_mountp, bp);
+
+                       /*
+                        * XXX(hch): clean up the error handling here to be less
+                        * of a mess..
+                        */
+                       if (XFS_FORCED_SHUTDOWN(mp)) {
+                               trace_xfs_bdstrat_shut(bp, _RET_IP_);
+                               xfs_bioerror_relse(bp);
+                       } else {
+                               xfs_buf_iorequest(bp);
+                       }
+
                        error = xfs_buf_iowait(bp);
                        if (error) {
                                xfs_buf_ioerror_alert(bp, __func__);
index d98c67001840b705db746e4a1bc89ccba209652b..3ea214cff349c87482d4d3a29b0370bb6c90cd42 100644 (file)
@@ -83,7 +83,9 @@
  * Should the subsystem abort the loading of an ACPI table if the
  * table checksum is incorrect?
  */
+#ifndef ACPI_CHECKSUM_ABORT
 #define ACPI_CHECKSUM_ABORT             FALSE
+#endif
 
 /*
  * Generate a version of ACPICA that only supports "reduced hardware"
index 7b2de026a4f3db11c730d9d3abfa8b903ba5713f..c602c7718421ded2f2bbe50f1e76edc39ac2b6f2 100644 (file)
@@ -100,6 +100,7 @@ enum acpi_hotplug_mode {
 struct acpi_hotplug_profile {
        struct kobject kobj;
        bool enabled:1;
+       bool ignore:1;
        enum acpi_hotplug_mode mode;
 };
 
index d8f9457755b4168787a66f903c15cb9d6506af25..4278aba9650381c932a687ca871a47f874b6aa1e 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20130927
+#define ACPI_CA_VERSION                 0x20131115
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index f330d28e4d0eaf4d8e681bb905f52ff72465bea7..db09234589409760b91cb9e696472a3e828476f9 100644 (file)
@@ -217,7 +217,7 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #endif
 
 #ifndef pte_accessible
-# define pte_accessible(pte)           ((void)(pte),1)
+# define pte_accessible(mm, pte)       ((void)(pte), 1)
 #endif
 
 #ifndef flush_tlb_fix_spurious_fault
@@ -599,11 +599,10 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        barrier();
 #endif
-       if (pmd_none(pmdval))
+       if (pmd_none(pmdval) || pmd_trans_huge(pmdval))
                return 1;
        if (unlikely(pmd_bad(pmdval))) {
-               if (!pmd_trans_huge(pmdval))
-                       pmd_clear_bad(pmd);
+               pmd_clear_bad(pmd);
                return 1;
        }
        return 0;
index ddf2b420ac8f81621ec9dd088e8379f8b686cd94..1cd3f5d767a81b18b8c3950701506e3f8bfcfc6c 100644 (file)
@@ -3,13 +3,11 @@
 
 #include <linux/thread_info.h>
 
-/*
- * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
- * that think a non-zero value indicates we cannot preempt.
- */
+#define PREEMPT_ENABLED        (0)
+
 static __always_inline int preempt_count(void)
 {
-       return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED;
+       return current_thread_info()->preempt_count;
 }
 
 static __always_inline int *preempt_count_ptr(void)
@@ -17,11 +15,6 @@ static __always_inline int *preempt_count_ptr(void)
        return &current_thread_info()->preempt_count;
 }
 
-/*
- * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the
- * alternative is loosing a reschedule. Better schedule too often -- also this
- * should be a very rare operation.
- */
 static __always_inline void preempt_count_set(int pc)
 {
        *preempt_count_ptr() = pc;
@@ -41,28 +34,17 @@ static __always_inline void preempt_count_set(int pc)
        task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
 } while (0)
 
-/*
- * We fold the NEED_RESCHED bit into the preempt count such that
- * preempt_enable() can decrement and test for needing to reschedule with a
- * single instruction.
- *
- * We invert the actual bit, so that when the decrement hits 0 we know we both
- * need to resched (the bit is cleared) and can resched (no preempt count).
- */
-
 static __always_inline void set_preempt_need_resched(void)
 {
-       *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED;
 }
 
 static __always_inline void clear_preempt_need_resched(void)
 {
-       *preempt_count_ptr() |= PREEMPT_NEED_RESCHED;
 }
 
 static __always_inline bool test_preempt_need_resched(void)
 {
-       return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED);
+       return false;
 }
 
 /*
@@ -81,7 +63,12 @@ static __always_inline void __preempt_count_sub(int val)
 
 static __always_inline bool __preempt_count_dec_and_test(void)
 {
-       return !--*preempt_count_ptr();
+       /*
+        * Because of load-store architectures cannot do per-cpu atomic
+        * operations; we cannot use PREEMPT_NEED_RESCHED because it might get
+        * lost.
+        */
+       return !--*preempt_count_ptr() && tif_need_resched();
 }
 
 /*
@@ -89,7 +76,7 @@ static __always_inline bool __preempt_count_dec_and_test(void)
  */
 static __always_inline bool should_resched(void)
 {
-       return unlikely(!*preempt_count_ptr());
+       return unlikely(!preempt_count() && tif_need_resched());
 }
 
 #ifdef CONFIG_PREEMPT
diff --git a/include/asm-generic/simd.h b/include/asm-generic/simd.h
new file mode 100644 (file)
index 0000000..f57eb7b
--- /dev/null
@@ -0,0 +1,14 @@
+
+#include <linux/hardirq.h>
+
+/*
+ * may_use_simd - whether it is allowable at this time to issue SIMD
+ *                instructions or access the SIMD register file
+ *
+ * As architectures typically don't preserve the SIMD register file when
+ * taking an interrupt, !in_interrupt() should be a reasonable default.
+ */
+static __must_check inline bool may_use_simd(void)
+{
+       return !in_interrupt();
+}
index 3f21f1b72e45db6db5e8ef7ec75fb790ce6184a9..d3909effd7256ee1334910f72ab57becccff93f9 100644 (file)
@@ -49,4 +49,12 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct
        return (val + c->high_bits) & ~rhs;
 }
 
+#ifndef zero_bytemask
+#ifdef CONFIG_64BIT
+#define zero_bytemask(mask)    (~0ul << fls64(mask))
+#else
+#define zero_bytemask(mask)    (~0ul << fls(mask))
+#endif /* CONFIG_64BIT */
+#endif /* zero_bytemask */
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
index 418d270e18063517750f39c68490f56fb7cd24c3..e73c19e90e38f49e9ebdff10bfed3cdca90a9f9a 100644 (file)
@@ -386,5 +386,21 @@ static inline int crypto_requires_sync(u32 type, u32 mask)
        return (type ^ CRYPTO_ALG_ASYNC) & mask & CRYPTO_ALG_ASYNC;
 }
 
-#endif /* _CRYPTO_ALGAPI_H */
+noinline unsigned long __crypto_memneq(const void *a, const void *b, size_t size);
+
+/**
+ * crypto_memneq - Compare two areas of memory without leaking
+ *                timing information.
+ *
+ * @a: One area of memory
+ * @b: Another area of memory
+ * @size: The size of the area.
+ *
+ * Returns 0 when data is equal, 1 otherwise.
+ */
+static inline int crypto_memneq(const void *a, const void *b, size_t size)
+{
+       return __crypto_memneq(a, b, size) != 0UL ? 1 : 0;
+}
 
+#endif /* _CRYPTO_ALGAPI_H */
index e47b044929a84b7cd1e54fb17b8e87de3020d7b6..6775059539b56f2ffe870d28c4d2ab35821c013a 100644 (file)
@@ -23,5 +23,15 @@ struct crypto_authenc_key_param {
        __be32 enckeylen;
 };
 
-#endif /* _CRYPTO_AUTHENC_H */
+struct crypto_authenc_keys {
+       const u8 *authkey;
+       const u8 *enckey;
+
+       unsigned int authkeylen;
+       unsigned int enckeylen;
+};
 
+int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
+                              unsigned int keylen);
+
+#endif /* _CRYPTO_AUTHENC_H */
index 13621cc8cf4c454f546a6fbb33fb5e85e8b1b1aa..6a626a507b8ca2d9c1a167b0758c7d7d3604013e 100644 (file)
@@ -36,6 +36,7 @@ static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num,
 {
        sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0);
        sg1[num - 1].page_link &= ~0x02;
+       sg1[num - 1].page_link |= 0x01;
 }
 
 static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
@@ -43,7 +44,7 @@ static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
        if (sg_is_last(sg))
                return NULL;
 
-       return (++sg)->length ? sg : (void *)sg_page(sg);
+       return (++sg)->length ? sg : sg_chain_ptr(sg);
 }
 
 static inline void scatterwalk_crypto_chain(struct scatterlist *head,
index 9a193b84238a30c97814fcee82148739a5a82b30..a89df3be16863302dcedde84da6f0dbc278fde8c 100644 (file)
@@ -41,10 +41,10 @@ struct assoc_array_ops {
        /* Is this the object we're looking for? */
        bool (*compare_object)(const void *object, const void *index_key);
 
-       /* How different are two objects, to a bit position in their keys? (or
-        * -1 if they're the same)
+       /* How different is an object from an index key, to a bit position in
+        * their keys? (or -1 if they're the same)
         */
-       int (*diff_objects)(const void *a, const void *b);
+       int (*diff_objects)(const void *object, const void *index_key);
 
        /* Method to free an object. */
        void (*free_object)(void *object);
index 669fef5c745a3fe98145a87d21a588cb64835c15..3e0fbe44176328193cf849fd039d70e91694a4ca 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <uapi/linux/auxvec.h>
 
-#define AT_VECTOR_SIZE_BASE 19 /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 20 /* NEW_AUX_ENT entries in auxiliary table */
   /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
 #endif /* _LINUX_AUXVEC_H */
index 973ce10c40b651faa5d9e06f41eb49fefa492eab..dc1bd3dcf11fd6b72f93c5d3d9b674957bb705a0 100644 (file)
@@ -28,8 +28,6 @@
 
 #endif
 
-#define uninitialized_var(x) x
-
 #ifndef __HAVE_BUILTIN_BSWAP16__
 /* icc has this, but it's called _bswap16 */
 #define __HAVE_BUILTIN_BSWAP16__
index 57e87e749a484cbf09a2f9f21fac3d3f52574df9..bf72e9ac6de01d1b1783b0b4adfd441c9c9ac58c 100644 (file)
@@ -29,8 +29,10 @@ struct vfsmount;
 /* The hash is always the low bits of hash_len */
 #ifdef __LITTLE_ENDIAN
  #define HASH_LEN_DECLARE u32 hash; u32 len;
+ #define bytemask_from_count(cnt)      (~(~0ul << (cnt)*8))
 #else
  #define HASH_LEN_DECLARE u32 len; u32 hash;
+ #define bytemask_from_count(cnt)      (~(~0ul >> (cnt)*8))
 #endif
 
 /*
index 41cf0c399288e022edf32f7e65c6f151004829d9..ba5f96db07540dc2897399d98a1b7085cc16a63a 100644 (file)
@@ -22,6 +22,7 @@
 #define LINUX_DMAENGINE_H
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/uio.h>
 #include <linux/bug.h>
 #include <linux/scatterlist.h>
@@ -363,6 +364,32 @@ struct dma_slave_config {
        unsigned int slave_id;
 };
 
+/**
+ * enum dma_residue_granularity - Granularity of the reported transfer residue
+ * @DMA_RESIDUE_GRANULARITY_DESCRIPTOR: Residue reporting is not support. The
+ *  DMA channel is only able to tell whether a descriptor has been completed or
+ *  not, which means residue reporting is not supported by this channel. The
+ *  residue field of the dma_tx_state field will always be 0.
+ * @DMA_RESIDUE_GRANULARITY_SEGMENT: Residue is updated after each successfully
+ *  completed segment of the transfer (For cyclic transfers this is after each
+ *  period). This is typically implemented by having the hardware generate an
+ *  interrupt after each transferred segment and then the drivers updates the
+ *  outstanding residue by the size of the segment. Another possibility is if
+ *  the hardware supports scatter-gather and the segment descriptor has a field
+ *  which gets set after the segment has been completed. The driver then counts
+ *  the number of segments without the flag set to compute the residue.
+ * @DMA_RESIDUE_GRANULARITY_BURST: Residue is updated after each transferred
+ *  burst. This is typically only supported if the hardware has a progress
+ *  register of some sort (E.g. a register with the current read/write address
+ *  or a register with the amount of bursts/beats/bytes that have been
+ *  transferred or still need to be transferred).
+ */
+enum dma_residue_granularity {
+       DMA_RESIDUE_GRANULARITY_DESCRIPTOR = 0,
+       DMA_RESIDUE_GRANULARITY_SEGMENT = 1,
+       DMA_RESIDUE_GRANULARITY_BURST = 2,
+};
+
 /* struct dma_slave_caps - expose capabilities of a slave channel only
  *
  * @src_addr_widths: bit mask of src addr widths the channel supports
@@ -373,6 +400,7 @@ struct dma_slave_config {
  *     should be checked by controller as well
  * @cmd_pause: true, if pause and thereby resume is supported
  * @cmd_terminate: true, if terminate cmd is supported
+ * @residue_granularity: granularity of the reported transfer residue
  */
 struct dma_slave_caps {
        u32 src_addr_widths;
@@ -380,6 +408,7 @@ struct dma_slave_caps {
        u32 directions;
        bool cmd_pause;
        bool cmd_terminate;
+       enum dma_residue_granularity residue_granularity;
 };
 
 static inline const char *dma_chan_name(struct dma_chan *chan)
@@ -1040,6 +1069,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
 struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
                                        dma_filter_fn fn, void *fn_param);
+struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
+                                                 const char *name);
 struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
 void dma_release_channel(struct dma_chan *chan);
 #else
@@ -1063,6 +1094,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
 {
        return NULL;
 }
+static inline struct dma_chan *dma_request_slave_channel_reason(
+                                       struct device *dev, const char *name)
+{
+       return ERR_PTR(-ENODEV);
+}
 static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
                                                         const char *name)
 {
index bc5687d0f3157c9d8d39342d4e69db1734baff16..11ce6784a196c2a40710080ee5464cbf9ed557a0 100644 (file)
@@ -801,6 +801,8 @@ struct efivar_entry {
        struct efi_variable var;
        struct list_head list;
        struct kobject kobj;
+       bool scanning;
+       bool deleting;
 };
 
 
@@ -866,6 +868,8 @@ void efivar_run_worker(void);
 #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
 int efivars_sysfs_init(void);
 
+#define EFIVARS_DATA_SIZE_MAX 1024
+
 #endif /* CONFIG_EFI_VARS */
 
 #endif /* _LINUX_EFI_H */
index 9abbe630c456775b19cc999f36887efa94bbdd41..8c9b7a1c4138b87a79833bc400370a13e94cf270 100644 (file)
@@ -248,6 +248,9 @@ struct ftrace_event_call {
 #ifdef CONFIG_PERF_EVENTS
        int                             perf_refcount;
        struct hlist_head __percpu      *perf_events;
+
+       int     (*perf_perm)(struct ftrace_event_call *,
+                            struct perf_event *);
 #endif
 };
 
@@ -317,6 +320,19 @@ struct ftrace_event_file {
        }                                                               \
        early_initcall(trace_init_flags_##name);
 
+#define __TRACE_EVENT_PERF_PERM(name, expr...)                         \
+       static int perf_perm_##name(struct ftrace_event_call *tp_event, \
+                                   struct perf_event *p_event)         \
+       {                                                               \
+               return ({ expr; });                                     \
+       }                                                               \
+       static int __init trace_init_perf_perm_##name(void)             \
+       {                                                               \
+               event_##name.perf_perm = &perf_perm_##name;             \
+               return 0;                                               \
+       }                                                               \
+       early_initcall(trace_init_perf_perm_##name);
+
 #define PERF_MAX_TRACE_SIZE    2048
 
 #define MAX_FILTER_STR_VAL     256     /* Should handle KSYM_SYMBOL_LEN */
index 656a27efb2c8cdd755cd78e20a36e5dd028e5310..3ea2cf6b0e6ce444f732e489fbf97c8a44969515 100644 (file)
@@ -2,9 +2,12 @@
 #define __LINUX_GPIO_DRIVER_H
 
 #include <linux/types.h>
+#include <linux/module.h>
 
 struct device;
 struct gpio_desc;
+struct of_phandle_args;
+struct device_node;
 struct seq_file;
 
 /**
@@ -125,6 +128,13 @@ extern struct gpio_chip *gpiochip_find(void *data,
 int gpiod_lock_as_irq(struct gpio_desc *desc);
 void gpiod_unlock_as_irq(struct gpio_desc *desc);
 
+enum gpio_lookup_flags {
+       GPIO_ACTIVE_HIGH = (0 << 0),
+       GPIO_ACTIVE_LOW = (1 << 0),
+       GPIO_OPEN_DRAIN = (1 << 1),
+       GPIO_OPEN_SOURCE = (1 << 2),
+};
+
 /**
  * Lookup table for associating GPIOs to specific devices and functions using
  * platform data.
@@ -152,9 +162,9 @@ struct gpiod_lookup {
         */
        unsigned int idx;
        /*
-        * mask of GPIOF_* values
+        * mask of GPIO_* values
         */
-       unsigned long flags;
+       enum gpio_lookup_flags flags;
 };
 
 /*
index a265af294ea49a28c0384af71aa5ee1a249b3be8..b914ca3f57ba4469264034cd521bf2cdc43b0cfb 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <linux/hid.h>
 #include <linux/hid-sensor-ids.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
 
 /**
  * struct hid_sensor_hub_attribute_info - Attribute info
@@ -40,6 +42,8 @@ struct hid_sensor_hub_attribute_info {
        s32 units;
        s32 unit_expo;
        s32 size;
+       s32 logical_minimum;
+       s32 logical_maximum;
 };
 
 /**
@@ -184,6 +188,7 @@ struct hid_sensor_common {
        struct platform_device *pdev;
        unsigned usage_id;
        bool data_ready;
+       struct iio_trigger *trigger;
        struct hid_sensor_hub_attribute_info poll;
        struct hid_sensor_hub_attribute_info report_state;
        struct hid_sensor_hub_attribute_info power_state;
index 4f945d3ed49fc7a511affdc307ea84aff60565cb..8323775ac21d0a86d2bda5a9ee93d2cfad181f78 100644 (file)
 #define HID_USAGE_SENSOR_PROP_REPORT_STATE                     0x200316
 #define HID_USAGE_SENSOR_PROY_POWER_STATE                      0x200319
 
+/* Power state enumerations */
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM               0x00
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM           0x01
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM            0x02
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM    0x03
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM      0x04
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM            0x05
+
+/* Report State enumerations */
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM           0x00
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM          0x01
+
 #endif
index 9649ff0c63f8d0bb5253cd08b3f32499986b4cfd..bd7e987522221f42b7042cc242abc8ca31a72996 100644 (file)
@@ -142,7 +142,10 @@ static inline int dequeue_hwpoisoned_huge_page(struct page *page)
        return 0;
 }
 
-#define isolate_huge_page(p, l) false
+static inline bool isolate_huge_page(struct page *page, struct list_head *list)
+{
+       return false;
+}
 #define putback_active_hugepage(p)     do {} while (0)
 #define is_hugepage_active(x)  false
 
index 673a3ce67f311df6567aa780dfdbf3d7adbe0cf9..ade1c06d4cebed9c30b47ea98c69fe51df89508c 100644 (file)
@@ -175,6 +175,9 @@ static inline int twl_class_is_ ##class(void)       \
 TWL_CLASS_IS(4030, TWL4030_CLASS_ID)
 TWL_CLASS_IS(6030, TWL6030_CLASS_ID)
 
+/* Set the regcache bypass for the regmap associated with the nodule */
+int twl_set_regcache_bypass(u8 mod_no, bool enable);
+
 /*
  * Read and write several 8-bit registers at once.
  */
@@ -667,8 +670,6 @@ struct twl4030_codec_data {
        unsigned int digimic_delay; /* in ms */
        unsigned int ramp_delay_value;
        unsigned int offset_cncl_path;
-       unsigned int check_defaults:1;
-       unsigned int reset_registers:1;
        unsigned int hs_extmute:1;
        int hs_extmute_gpio;
 };
index 5d89d1b808a6cc896f22332c477126c3d2f2b563..c56c350324e4b4670ef8d31397a1a777b9c08578 100644 (file)
@@ -4,6 +4,7 @@
 #include <uapi/linux/ipv6.h>
 
 #define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
+#define ipv6_authlen(p) (((p)->hdrlen+2) << 2)
 /*
  * This structure contains configuration options per IPv6 link.
  */
index 714ba08dc09265922fe8ab81dee1caadc12a9100..e374e369fb2f4c9eb5ace48679376550d5ee633c 100644 (file)
@@ -14,6 +14,6 @@ enum irqreturn {
 };
 
 typedef enum irqreturn irqreturn_t;
-#define IRQ_RETVAL(x)  ((x) != IRQ_NONE)
+#define IRQ_RETVAL(x)  ((x) ? IRQ_HANDLED : IRQ_NONE)
 
 #endif
index d4e98d13eff4bda01b08313986b63135cc80ee2b..ecb87544cc5d888be056d903a2e0b227dd24c461 100644 (file)
@@ -193,7 +193,8 @@ extern int _cond_resched(void);
                (__x < 0) ? -__x : __x;         \
        })
 
-#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP)
+#if defined(CONFIG_MMU) && \
+       (defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP))
 void might_fault(void);
 #else
 static inline void might_fault(void) { }
index d78d28a733b15afdc25a620ca5925f6619f82a2c..5fd33dc1fe3ad265d352ed48f3a8cdeec0ca646e 100644 (file)
@@ -198,6 +198,9 @@ extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 extern size_t vmcoreinfo_size;
 extern size_t vmcoreinfo_max_size;
 
+/* flag to track if kexec reboot is in progress */
+extern bool kexec_in_progress;
+
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
                unsigned long long *crash_size, unsigned long long *crash_base);
 int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
index 0e23c26485f457cf2380818a18b00c1175bc02ae..9b503376738fac8e25e9fa71b286b4c341295d76 100644 (file)
@@ -418,6 +418,7 @@ enum {
        ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
        ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
        ATA_HORKAGE_ATAPI_DMADIR = (1 << 18),   /* device requires dmadir */
+       ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19),    /* don't use queued TRIM */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index c8929c3832db26d00d80f96e524afbb0e75c4df1..4bfde0e99ed5169d7220204c39070faa387f57ab 100644 (file)
@@ -19,7 +19,7 @@
 
 #define USE_CMPXCHG_LOCKREF \
        (IS_ENABLED(CONFIG_ARCH_USE_CMPXCHG_LOCKREF) && \
-        IS_ENABLED(CONFIG_SMP) && !BLOATED_SPINLOCKS)
+        IS_ENABLED(CONFIG_SMP) && SPINLOCK_SIZE <= 4)
 
 struct lockref {
        union {
index 69ed5f5e9f6e4a83f8c9226cb92d6ba7eafa17bd..c45c089bfdaca9a91f32832102ff32291444884f 100644 (file)
@@ -133,4 +133,34 @@ __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
        return ret;
 }
 
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+       return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+       u32 ah, al;
+       u64 ret;
+
+       al = a;
+       ah = a >> 32;
+
+       ret = ((u64)al * mul) >> shift;
+       if (ah)
+               ret += ((u64)ah * mul) << (32 - shift);
+
+       return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#endif
+
 #endif /* _LINUX_MATH64_H */
index cb49417f8ba9261ba436fef11851274f9df977d0..19883aeb1ac82b852d617c866b3b42edc72d5068 100644 (file)
 #define ARIZONA_INPUT_ENABLES_STATUS             0x301
 #define ARIZONA_INPUT_RATE                       0x308
 #define ARIZONA_INPUT_VOLUME_RAMP                0x309
+#define ARIZONA_HPF_CONTROL                      0x30C
 #define ARIZONA_IN1L_CONTROL                     0x310
 #define ARIZONA_ADC_DIGITAL_VOLUME_1L            0x311
 #define ARIZONA_DMIC1L_CONTROL                   0x312
 #define ARIZONA_IN4L_CONTROL                     0x328
 #define ARIZONA_ADC_DIGITAL_VOLUME_4L            0x329
 #define ARIZONA_DMIC4L_CONTROL                   0x32A
+#define ARIZONA_IN4R_CONTROL                     0x32C
 #define ARIZONA_ADC_DIGITAL_VOLUME_4R            0x32D
 #define ARIZONA_DMIC4R_CONTROL                   0x32E
 #define ARIZONA_OUTPUT_ENABLES_1                 0x400
 #define ARIZONA_PDM_SPK1_CTRL_2                  0x491
 #define ARIZONA_PDM_SPK2_CTRL_1                  0x492
 #define ARIZONA_PDM_SPK2_CTRL_2                  0x493
+#define ARIZONA_HP1_SHORT_CIRCUIT_CTRL           0x4A0
+#define ARIZONA_HP2_SHORT_CIRCUIT_CTRL           0x4A1
+#define ARIZONA_HP3_SHORT_CIRCUIT_CTRL           0x4A2
 #define ARIZONA_SPK_CTRL_2                       0x4B5
 #define ARIZONA_SPK_CTRL_3                       0x4B6
 #define ARIZONA_DAC_COMP_1                       0x4DC
 #define ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME        0x74D
 #define ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE        0x74E
 #define ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME        0x74F
+#define ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE        0x750
+#define ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME        0x751
+#define ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE        0x752
+#define ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME        0x753
+#define ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE        0x754
+#define ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME        0x755
+#define ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE        0x756
+#define ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME        0x757
+#define ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE        0x758
+#define ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME        0x759
+#define ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE        0x75A
+#define ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME        0x75B
+#define ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE        0x75C
+#define ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME        0x75D
+#define ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE        0x75E
+#define ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME        0x75F
+#define ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE        0x760
+#define ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME        0x761
+#define ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE        0x762
+#define ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME        0x763
+#define ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE        0x764
+#define ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME        0x765
+#define ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE        0x766
+#define ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME        0x767
+#define ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE        0x768
+#define ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME        0x769
+#define ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE        0x76A
+#define ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME        0x76B
+#define ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE        0x76C
+#define ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME        0x76D
+#define ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE        0x76E
+#define ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME        0x76F
 #define ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE        0x780
 #define ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME        0x781
 #define ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE        0x782
 #define ARIZONA_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
 #define ARIZONA_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
 
+/*
+ * R780 (0x30C) - HPF Control
+ */
+#define ARIZONA_IN_HPF_CUT_MASK                  0x0007  /* IN_HPF_CUT [2:0] */
+#define ARIZONA_IN_HPF_CUT_SHIFT                      0  /* IN_HPF_CUT [2:0] */
+#define ARIZONA_IN_HPF_CUT_WIDTH                      3  /* IN_HPF_CUT [2:0] */
+
 /*
  * R784 (0x310) - IN1L Control
  */
+#define ARIZONA_IN1L_HPF_MASK                    0x8000  /* IN1L_HPF - [15] */
+#define ARIZONA_IN1L_HPF_SHIFT                       15  /* IN1L_HPF - [15] */
+#define ARIZONA_IN1L_HPF_WIDTH                        1  /* IN1L_HPF - [15] */
 #define ARIZONA_IN1_OSR_MASK                     0x6000  /* IN1_OSR - [14:13] */
 #define ARIZONA_IN1_OSR_SHIFT                        13  /* IN1_OSR - [14:13] */
 #define ARIZONA_IN1_OSR_WIDTH                         2  /* IN1_OSR - [14:13] */
 /*
  * R788 (0x314) - IN1R Control
  */
+#define ARIZONA_IN1R_HPF_MASK                    0x8000  /* IN1R_HPF - [15] */
+#define ARIZONA_IN1R_HPF_SHIFT                       15  /* IN1R_HPF - [15] */
+#define ARIZONA_IN1R_HPF_WIDTH                        1  /* IN1R_HPF - [15] */
 #define ARIZONA_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
 #define ARIZONA_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
 #define ARIZONA_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
 /*
  * R792 (0x318) - IN2L Control
  */
+#define ARIZONA_IN2L_HPF_MASK                    0x8000  /* IN2L_HPF - [15] */
+#define ARIZONA_IN2L_HPF_SHIFT                       15  /* IN2L_HPF - [15] */
+#define ARIZONA_IN2L_HPF_WIDTH                        1  /* IN2L_HPF - [15] */
 #define ARIZONA_IN2_OSR_MASK                     0x6000  /* IN2_OSR - [14:13] */
 #define ARIZONA_IN2_OSR_SHIFT                        13  /* IN2_OSR - [14:13] */
 #define ARIZONA_IN2_OSR_WIDTH                         2  /* IN2_OSR - [14:13] */
 /*
  * R796 (0x31C) - IN2R Control
  */
+#define ARIZONA_IN2R_HPF_MASK                    0x8000  /* IN2R_HPF - [15] */
+#define ARIZONA_IN2R_HPF_SHIFT                       15  /* IN2R_HPF - [15] */
+#define ARIZONA_IN2R_HPF_WIDTH                        1  /* IN2R_HPF - [15] */
 #define ARIZONA_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
 #define ARIZONA_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
 #define ARIZONA_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
 /*
  * R800 (0x320) - IN3L Control
  */
+#define ARIZONA_IN3L_HPF_MASK                    0x8000  /* IN3L_HPF - [15] */
+#define ARIZONA_IN3L_HPF_SHIFT                       15  /* IN3L_HPF - [15] */
+#define ARIZONA_IN3L_HPF_WIDTH                        1  /* IN3L_HPF - [15] */
 #define ARIZONA_IN3_OSR_MASK                     0x6000  /* IN3_OSR - [14:13] */
 #define ARIZONA_IN3_OSR_SHIFT                        13  /* IN3_OSR - [14:13] */
 #define ARIZONA_IN3_OSR_WIDTH                         2  /* IN3_OSR - [14:13] */
 /*
  * R804 (0x324) - IN3R Control
  */
+#define ARIZONA_IN3R_HPF_MASK                    0x8000  /* IN3R_HPF - [15] */
+#define ARIZONA_IN3R_HPF_SHIFT                       15  /* IN3R_HPF - [15] */
+#define ARIZONA_IN3R_HPF_WIDTH                        1  /* IN3R_HPF - [15] */
 #define ARIZONA_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
 #define ARIZONA_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
 #define ARIZONA_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
 /*
  * R808 (0x328) - IN4 Control
  */
+#define ARIZONA_IN4L_HPF_MASK                    0x8000  /* IN4L_HPF - [15] */
+#define ARIZONA_IN4L_HPF_SHIFT                       15  /* IN4L_HPF - [15] */
+#define ARIZONA_IN4L_HPF_WIDTH                        1  /* IN4L_HPF - [15] */
 #define ARIZONA_IN4_OSR_MASK                     0x6000  /* IN4_OSR - [14:13] */
 #define ARIZONA_IN4_OSR_SHIFT                        13  /* IN4_OSR - [14:13] */
 #define ARIZONA_IN4_OSR_WIDTH                         2  /* IN4_OSR - [14:13] */
 #define ARIZONA_IN4L_DMIC_DLY_SHIFT                   0  /* IN4L_DMIC_DLY - [5:0] */
 #define ARIZONA_IN4L_DMIC_DLY_WIDTH                   6  /* IN4L_DMIC_DLY - [5:0] */
 
+/*
+ * R812 (0x32C) - IN4R Control
+ */
+#define ARIZONA_IN4R_HPF_MASK                    0x8000  /* IN4R_HPF - [15] */
+#define ARIZONA_IN4R_HPF_SHIFT                       15  /* IN4R_HPF - [15] */
+#define ARIZONA_IN4R_HPF_WIDTH                        1  /* IN4R_HPF - [15] */
+
 /*
  * R813 (0x32D) - ADC Digital Volume 4R
  */
 /*
  * R1088 (0x440) - DRE Enable
  */
+#define ARIZONA_DRE3R_ENA                        0x0020  /* DRE3R_ENA */
+#define ARIZONA_DRE3R_ENA_MASK                   0x0020  /* DRE3R_ENA */
+#define ARIZONA_DRE3R_ENA_SHIFT                       5  /* DRE3R_ENA */
+#define ARIZONA_DRE3R_ENA_WIDTH                       1  /* DRE3R_ENA */
 #define ARIZONA_DRE3L_ENA                        0x0010  /* DRE3L_ENA */
 #define ARIZONA_DRE3L_ENA_MASK                   0x0010  /* DRE3L_ENA */
 #define ARIZONA_DRE3L_ENA_SHIFT                       4  /* DRE3L_ENA */
 #define ARIZONA_SPK2_FMT_SHIFT                        0  /* SPK2_FMT */
 #define ARIZONA_SPK2_FMT_WIDTH                        1  /* SPK2_FMT */
 
+/*
+ * R1184 (0x4A0) - HP1 Short Circuit Ctrl
+ */
+#define ARIZONA_HP1_SC_ENA                       0x1000  /* HP1_SC_ENA */
+#define ARIZONA_HP1_SC_ENA_MASK                  0x1000  /* HP1_SC_ENA */
+#define ARIZONA_HP1_SC_ENA_SHIFT                     12  /* HP1_SC_ENA */
+#define ARIZONA_HP1_SC_ENA_WIDTH                      1  /* HP1_SC_ENA */
+
+/*
+ * R1185 (0x4A1) - HP2 Short Circuit Ctrl
+ */
+#define ARIZONA_HP2_SC_ENA                       0x1000  /* HP2_SC_ENA */
+#define ARIZONA_HP2_SC_ENA_MASK                  0x1000  /* HP2_SC_ENA */
+#define ARIZONA_HP2_SC_ENA_SHIFT                     12  /* HP2_SC_ENA */
+#define ARIZONA_HP2_SC_ENA_WIDTH                      1  /* HP2_SC_ENA */
+
+/*
+ * R1186 (0x4A2) - HP3 Short Circuit Ctrl
+ */
+#define ARIZONA_HP3_SC_ENA                       0x1000  /* HP3_SC_ENA */
+#define ARIZONA_HP3_SC_ENA_MASK                  0x1000  /* HP3_SC_ENA */
+#define ARIZONA_HP3_SC_ENA_SHIFT                     12  /* HP3_SC_ENA */
+#define ARIZONA_HP3_SC_ENA_WIDTH                      1  /* HP3_SC_ENA */
+
 /*
  * R1244 (0x4DC) - DAC comp 1
  */
 #define ARIZONA_AIF2TX2_SLOT_SHIFT                    0  /* AIF2TX2_SLOT - [5:0] */
 #define ARIZONA_AIF2TX2_SLOT_WIDTH                    6  /* AIF2TX2_SLOT - [5:0] */
 
+/*
+ * R1355 (0x54B) - AIF2 Frame Ctrl 5
+ */
+#define ARIZONA_AIF2TX3_SLOT_MASK                0x003F  /* AIF2TX3_SLOT - [5:0] */
+#define ARIZONA_AIF2TX3_SLOT_SHIFT                    0  /* AIF2TX3_SLOT - [5:0] */
+#define ARIZONA_AIF2TX3_SLOT_WIDTH                    6  /* AIF2TX3_SLOT - [5:0] */
+
+/*
+ * R1356 (0x54C) - AIF2 Frame Ctrl 6
+ */
+#define ARIZONA_AIF2TX4_SLOT_MASK                0x003F  /* AIF2TX4_SLOT - [5:0] */
+#define ARIZONA_AIF2TX4_SLOT_SHIFT                    0  /* AIF2TX4_SLOT - [5:0] */
+#define ARIZONA_AIF2TX4_SLOT_WIDTH                    6  /* AIF2TX4_SLOT - [5:0] */
+
+
+/*
+ * R1357 (0x54D) - AIF2 Frame Ctrl 7
+ */
+#define ARIZONA_AIF2TX5_SLOT_MASK                0x003F  /* AIF2TX5_SLOT - [5:0] */
+#define ARIZONA_AIF2TX5_SLOT_SHIFT                    0  /* AIF2TX5_SLOT - [5:0] */
+#define ARIZONA_AIF2TX5_SLOT_WIDTH                    6  /* AIF2TX5_SLOT - [5:0] */
+
+/*
+ * R1358 (0x54E) - AIF2 Frame Ctrl 8
+ */
+#define ARIZONA_AIF2TX6_SLOT_MASK                0x003F  /* AIF2TX6_SLOT - [5:0] */
+#define ARIZONA_AIF2TX6_SLOT_SHIFT                    0  /* AIF2TX6_SLOT - [5:0] */
+#define ARIZONA_AIF2TX6_SLOT_WIDTH                    6  /* AIF2TX6_SLOT - [5:0] */
+
 /*
  * R1361 (0x551) - AIF2 Frame Ctrl 11
  */
 #define ARIZONA_AIF2RX2_SLOT_SHIFT                    0  /* AIF2RX2_SLOT - [5:0] */
 #define ARIZONA_AIF2RX2_SLOT_WIDTH                    6  /* AIF2RX2_SLOT - [5:0] */
 
+/*
+ * R1363 (0x553) - AIF2 Frame Ctrl 13
+ */
+#define ARIZONA_AIF2RX3_SLOT_MASK                0x003F  /* AIF2RX3_SLOT - [5:0] */
+#define ARIZONA_AIF2RX3_SLOT_SHIFT                    0  /* AIF2RX3_SLOT - [5:0] */
+#define ARIZONA_AIF2RX3_SLOT_WIDTH                    6  /* AIF2RX3_SLOT - [5:0] */
+
+/*
+ * R1364 (0x554) - AIF2 Frame Ctrl 14
+ */
+#define ARIZONA_AIF2RX4_SLOT_MASK                0x003F  /* AIF2RX4_SLOT - [5:0] */
+#define ARIZONA_AIF2RX4_SLOT_SHIFT                    0  /* AIF2RX4_SLOT - [5:0] */
+#define ARIZONA_AIF2RX4_SLOT_WIDTH                    6  /* AIF2RX4_SLOT - [5:0] */
+
+/*
+ * R1365 (0x555) - AIF2 Frame Ctrl 15
+ */
+#define ARIZONA_AIF2RX5_SLOT_MASK                0x003F  /* AIF2RX5_SLOT - [5:0] */
+#define ARIZONA_AIF2RX5_SLOT_SHIFT                    0  /* AIF2RX5_SLOT - [5:0] */
+#define ARIZONA_AIF2RX5_SLOT_WIDTH                    6  /* AIF2RX5_SLOT - [5:0] */
+
+/*
+ * R1366 (0x556) - AIF2 Frame Ctrl 16
+ */
+#define ARIZONA_AIF2RX6_SLOT_MASK                0x003F  /* AIF2RX6_SLOT - [5:0] */
+#define ARIZONA_AIF2RX6_SLOT_SHIFT                    0  /* AIF2RX6_SLOT - [5:0] */
+#define ARIZONA_AIF2RX6_SLOT_WIDTH                    6  /* AIF2RX6_SLOT - [5:0] */
+
 /*
  * R1369 (0x559) - AIF2 Tx Enables
  */
+#define ARIZONA_AIF2TX6_ENA                      0x0020  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX6_ENA_MASK                 0x0020  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX6_ENA_SHIFT                     5  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX6_ENA_WIDTH                     1  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX5_ENA                      0x0010  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX5_ENA_MASK                 0x0010  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX5_ENA_SHIFT                     4  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX5_ENA_WIDTH                     1  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX4_ENA                      0x0008  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX4_ENA_MASK                 0x0008  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX4_ENA_SHIFT                     3  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX4_ENA_WIDTH                     1  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX3_ENA                      0x0004  /* AIF2TX3_ENA */
+#define ARIZONA_AIF2TX3_ENA_MASK                 0x0004  /* AIF2TX3_ENA */
+#define ARIZONA_AIF2TX3_ENA_SHIFT                     2  /* AIF2TX3_ENA */
+#define ARIZONA_AIF2TX3_ENA_WIDTH                     1  /* AIF2TX3_ENA */
 #define ARIZONA_AIF2TX2_ENA                      0x0002  /* AIF2TX2_ENA */
 #define ARIZONA_AIF2TX2_ENA_MASK                 0x0002  /* AIF2TX2_ENA */
 #define ARIZONA_AIF2TX2_ENA_SHIFT                     1  /* AIF2TX2_ENA */
 /*
  * R1370 (0x55A) - AIF2 Rx Enables
  */
+#define ARIZONA_AIF2RX6_ENA                      0x0020  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX6_ENA_MASK                 0x0020  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX6_ENA_SHIFT                     5  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX6_ENA_WIDTH                     1  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX5_ENA                      0x0010  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX5_ENA_MASK                 0x0010  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX5_ENA_SHIFT                     4  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX5_ENA_WIDTH                     1  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX4_ENA                      0x0008  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX4_ENA_MASK                 0x0008  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX4_ENA_SHIFT                     3  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX4_ENA_WIDTH                     1  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX3_ENA                      0x0004  /* AIF2RX3_ENA */
+#define ARIZONA_AIF2RX3_ENA_MASK                 0x0004  /* AIF2RX3_ENA */
+#define ARIZONA_AIF2RX3_ENA_SHIFT                     2  /* AIF2RX3_ENA */
+#define ARIZONA_AIF2RX3_ENA_WIDTH                     1  /* AIF2RX3_ENA */
 #define ARIZONA_AIF2RX2_ENA                      0x0002  /* AIF2RX2_ENA */
 #define ARIZONA_AIF2RX2_ENA_MASK                 0x0002  /* AIF2RX2_ENA */
 #define ARIZONA_AIF2RX2_ENA_SHIFT                     1  /* AIF2RX2_ENA */
index 2d0c9071bcfb795a4f34cdc44b1e88abae394c5e..cab2dd27907661e9c312e03088e398cc06c89a20 100644 (file)
@@ -39,7 +39,8 @@ enum sec_device_type {
 struct sec_pmic_dev {
        struct device *dev;
        struct sec_platform_data *pdata;
-       struct regmap *regmap;
+       struct regmap *regmap_pmic;
+       struct regmap *regmap_rtc;
        struct i2c_client *i2c;
        struct i2c_client *rtc;
 
index ad05ce60c1c97a052c11713f18532836829831cc..2e5b194b9b1900b9d5304cbdb52f14aac576b85e 100644 (file)
@@ -22,6 +22,8 @@
 #define PHY_ID_KSZ8021         0x00221555
 #define PHY_ID_KSZ8031         0x00221556
 #define PHY_ID_KSZ8041         0x00221510
+/* undocumented */
+#define PHY_ID_KSZ8041RNLI     0x00221537
 #define PHY_ID_KSZ8051         0x00221550
 /* same id: ks8001 Rev. A/B, and ks8721 Rev 3. */
 #define PHY_ID_KSZ8001         0x0022161A
index f5096b58b20d3ef64618e18ca37e1083b97af252..f015c059e159f1f8cad2da7b88dd26cdcbfd637d 100644 (file)
@@ -55,7 +55,8 @@ extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
 extern int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode);
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
@@ -90,10 +91,19 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 #endif /* CONFIG_MIGRATION */
 
 #ifdef CONFIG_NUMA_BALANCING
+extern bool pmd_trans_migrating(pmd_t pmd);
+extern void wait_migrate_huge_page(struct anon_vma *anon_vma, 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)
+{
+       return false;
+}
+static inline void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+}
 static inline int migrate_misplaced_page(struct page *page,
                                         struct vm_area_struct *vma, int node)
 {
index 1cedd000cf293f4486575b87086b01e2ee1b26e5..35527173cf50c71baeba5f549007c5903bc8ea06 100644 (file)
@@ -1317,7 +1317,7 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
 #endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
 
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
 extern bool ptlock_alloc(struct page *page);
 extern void ptlock_free(struct page *page);
 
@@ -1325,7 +1325,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return page->ptl;
 }
-#else /* BLOATED_SPINLOCKS */
+#else /* ALLOC_SPLIT_PTLOCKS */
 static inline bool ptlock_alloc(struct page *page)
 {
        return true;
@@ -1339,7 +1339,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return &page->ptl;
 }
-#endif /* BLOATED_SPINLOCKS */
+#endif /* ALLOC_SPLIT_PTLOCKS */
 
 static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd)
 {
index bd299418a934e21b99c303af82a7c2f427bbf915..290901a8c1de9f0193ae3e2c640c070623431081 100644 (file)
@@ -26,6 +26,7 @@ struct address_space;
 #define USE_SPLIT_PTE_PTLOCKS  (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
 #define USE_SPLIT_PMD_PTLOCKS  (USE_SPLIT_PTE_PTLOCKS && \
                IS_ENABLED(CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK))
+#define ALLOC_SPLIT_PTLOCKS    (SPINLOCK_SIZE > BITS_PER_LONG/8)
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -155,7 +156,7 @@ struct page {
                                                 * system if PG_buddy is set.
                                                 */
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
                spinlock_t *ptl;
 #else
                spinlock_t ptl;
@@ -442,6 +443,14 @@ struct mm_struct {
 
        /* numa_scan_seq prevents two threads setting pte_numa */
        int numa_scan_seq;
+#endif
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+       /*
+        * An operation with batched TLB flushing is going on. Anything that
+        * can move process memory needs to flush the TLB when moving a
+        * PROT_NONE or PROT_NUMA mapped page.
+        */
+       bool tlb_flush_pending;
 #endif
        struct uprobes_state uprobes_state;
 };
@@ -459,4 +468,45 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
        return mm->cpu_vm_mask_var;
 }
 
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+/*
+ * Memory barriers to keep this state in sync are graciously provided by
+ * the page table locks, outside of which no page table modifications happen.
+ * The barriers below prevent the compiler from re-ordering the instructions
+ * around the memory barriers that are already present in the code.
+ */
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       return mm->tlb_flush_pending;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+       mm->tlb_flush_pending = true;
+
+       /*
+        * Guarantee that the tlb_flush_pending store does not leak into the
+        * critical section updating the page tables
+        */
+       smp_mb__before_spinlock();
+}
+/* Clearing is done after a TLB flush, which also provides a barrier. */
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       mm->tlb_flush_pending = false;
+}
+#else
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       return false;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+#endif
+
 #endif /* _LINUX_MM_TYPES_H */
index 4bcee94cef9314c44dfaa94fb17d3c905fefee08..69be3e6079c8c9320cff6598b8ba33ff1cdfb1f8 100644 (file)
@@ -181,7 +181,7 @@ struct proto_ops {
                                      int offset, size_t size, int flags);
        ssize_t         (*splice_read)(struct socket *sock,  loff_t *ppos,
                                       struct pipe_inode_info *pipe, size_t len, unsigned int flags);
-       void            (*set_peek_off)(struct sock *sk, int val);
+       int             (*set_peek_off)(struct sock *sk, int val);
 };
 
 #define DECLARE_SOCKADDR(type, dst, src)       \
index 7f0ed423a3606f1cc13e09a00d332dc4a45f924b..d9a550bf3e8e8a770c4198bf96bb2b81e34a3b6e 100644 (file)
@@ -1255,7 +1255,7 @@ struct net_device {
        unsigned char           perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
        unsigned char           addr_assign_type; /* hw address assignment type */
        unsigned char           addr_len;       /* hardware address length      */
-       unsigned char           neigh_priv_len;
+       unsigned short          neigh_priv_len;
        unsigned short          dev_id;         /* Used to differentiate devices
                                                 * that share the same link
                                                 * layer address
index c1637062c1ce138129a87dd571a5ea7cd2b53abd..12c2cb947df579bca8e55c46c5a58cf449f084fb 100644 (file)
@@ -413,16 +413,6 @@ enum lock_type4 {
 #define NFS4_VERSION 4
 #define NFS4_MINOR_VERSION 0
 
-#if defined(CONFIG_NFS_V4_2)
-#define NFS4_MAX_MINOR_VERSION 2
-#else
-#if defined(CONFIG_NFS_V4_1)
-#define NFS4_MAX_MINOR_VERSION 1
-#else
-#define NFS4_MAX_MINOR_VERSION 0
-#endif /* CONFIG_NFS_V4_1 */
-#endif /* CONFIG_NFS_V4_2 */
-
 #define NFS4_DEBUG 1
 
 /* Index of predefined Linux client operations */
index 14a48207a304ec65dda6ac8af22e0e0825b8fa6b..48997374eaf04eac0d52b8bf8d60c61c35944df3 100644 (file)
@@ -506,24 +506,6 @@ extern const struct inode_operations nfs_referral_inode_operations;
 extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
-/*
- * linux/fs/nfs/nfs4proc.c
- */
-#ifdef CONFIG_NFS_V4_SECURITY_LABEL
-extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
-static inline void nfs4_label_free(struct nfs4_label *label)
-{
-       if (label) {
-               kfree(label->label);
-               kfree(label);
-       }
-       return;
-}
-#else
-static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
-static inline void nfs4_label_free(void *label) {}
-#endif
-
 /*
  * linux/fs/nfs/unlink.c
  */
index 86292beebfe2b910e28491dfd0e9c2343428000d..438694650471cc66b62cb7890e19fde5799314f7 100644 (file)
@@ -129,10 +129,9 @@ struct parallel_data {
        struct padata_serial_queue      __percpu *squeue;
        atomic_t                        reorder_objects;
        atomic_t                        refcnt;
+       atomic_t                        seq_nr;
        struct padata_cpumask           cpumask;
        spinlock_t                      lock ____cacheline_aligned;
-       spinlock_t                      seq_lock;
-       unsigned int                    seq_nr;
        unsigned int                    processed;
        struct timer_list               timer;
 };
index 1084a15175e04ff0bc715e3e429aab7027d279f8..a13d6825e586972835ba2b3d53ac4ab504ba5369 100644 (file)
@@ -960,6 +960,7 @@ void pci_update_resource(struct pci_dev *dev, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+bool pci_device_is_present(struct pci_dev *pdev);
 
 /* ROM control related routines */
 int pci_enable_rom(struct pci_dev *pdev);
@@ -1567,65 +1568,65 @@ enum pci_fixup_pass {
 /* Anonymous variables would be nice... */
 #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,        \
                                  class_shift, hook)                    \
-       static const struct pci_fixup __pci_fixup_##name __used         \
+       static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used       \
        __attribute__((__section__(#section), aligned((sizeof(void *)))))    \
                = { vendor, device, class, class_shift, hook };
 
 #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device, class,    \
+               resume##hook, vendor, device, class,    \
                class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(vendor, device, class,    \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_SUSPEND(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device, class,   \
+               suspend##hook, vendor, device, class,   \
                class_shift, hook)
 
 #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device,           \
+               resume##hook, vendor, device,           \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook)           \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device,          \
+               suspend##hook, vendor, device,          \
                PCI_ANY_ID, 0, hook)
 
 #ifdef CONFIG_PCI_QUIRKS
index 57e890abe1f09220c777b5403c782cd6792872d6..a5fc7d01aad61049164f920f90a6f20df1cbc22d 100644 (file)
@@ -69,6 +69,7 @@
        __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;                    \
        extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;            \
        __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;                   \
+       extern __PCPU_ATTRS(sec) __typeof__(type) name;                 \
        __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak                 \
        __typeof__(type) name
 #else
index c78d90b28b19f4646ad9ab113ec3e8ad2d0f8ef1..3c73c045f8da961dd8a3ddb6d5c17a169b2a2b42 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/plat-omap/include/mach/mcbsp.h
- *
  * Defines for Multi-Channel Buffered Serial Port
  *
  * Copyright (C) 2002 RidgeRun, Inc.
@@ -21,8 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#ifndef __ASM_ARCH_OMAP_MCBSP_H
-#define __ASM_ARCH_OMAP_MCBSP_H
+#ifndef __ASOC_TI_MCBSP_H
+#define __ASOC_TI_MCBSP_H
 
 #include <linux/spinlock.h>
 #include <linux/clk.h>
index 9991aea3d577d7dff57481f823b25f521af34903..2f34bb98fe2ab6eb8993febc65dc1db0dd80fe22 100644 (file)
 
 #include <linux/platform_data/dma-ste-dma40.h>
 
-enum msp_i2s_id {
-       MSP_I2S_0 = 0,
-       MSP_I2S_1,
-       MSP_I2S_2,
-       MSP_I2S_3,
-};
-
 /* Platform data structure for a MSP I2S-device */
 struct msp_i2s_platform_data {
-       enum msp_i2s_id id;
+       int id;
        struct stedma40_chan_cfg *msp_i2s_dma_rx;
        struct stedma40_chan_cfg *msp_i2s_dma_tx;
 };
index 689a856b86f90e1329515cf1ad9b80d3e2e7cdf5..5245992b036734dd4c96f1c544539e070d058b64 100644 (file)
@@ -92,6 +92,7 @@ enum {
        MCASP_VERSION_1 = 0,    /* DM646x */
        MCASP_VERSION_2,        /* DA8xx/OMAPL1x */
        MCASP_VERSION_3,        /* TI81xx/AM33xx */
+       MCASP_VERSION_4,        /* DRA7xxx */
 };
 
 enum mcbsp_clk_input_pin {
index abd437d0a8a7eeac72297ad5306ca071993d8f58..ece0c6bbfcc5617f394092ec027f39ce3abc629d 100644 (file)
@@ -51,6 +51,7 @@ struct pstore_info {
        char            *buf;
        size_t          bufsize;
        struct mutex    read_mutex;     /* serialize open/read/close */
+       int             flags;
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
@@ -70,6 +71,8 @@ struct pstore_info {
        void            *data;
 };
 
+#define        PSTORE_FLAGS_FRAGILE    1
+
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
 extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
index 8e00f9f6f96395b3e209192259b6af58f7078143..9e7db9e73cc13ffc04d05b02c9c5ea0d877be7e9 100644 (file)
@@ -43,6 +43,7 @@ extern int unregister_reboot_notifier(struct notifier_block *);
  * Architecture-specific implementations of sys_reboot commands.
  */
 
+extern void migrate_to_reboot_cpu(void);
 extern void machine_restart(char *cmd);
 extern void machine_halt(void);
 extern void machine_power_off(void);
index 7e35d4b9e14a45cba37fd8a7f234e5a3a50ec4b5..53f97eb8dbc7660195f0ebc27893bf68c65cdff6 100644 (file)
@@ -440,8 +440,6 @@ struct task_cputime {
                .sum_exec_runtime = 0,                          \
        }
 
-#define PREEMPT_ENABLED                (PREEMPT_NEED_RESCHED)
-
 #ifdef CONFIG_PREEMPT_COUNT
 #define PREEMPT_DISABLED       (1 + PREEMPT_ENABLED)
 #else
@@ -831,8 +829,6 @@ struct sched_domain {
        unsigned int balance_interval;  /* initialise to 1. units in ms. */
        unsigned int nr_balance_failed; /* initialise to 0 */
 
-       u64 last_update;
-
        /* idle_balance() stats */
        u64 max_newidle_lb_cost;
        unsigned long next_decay_max_lb_cost;
@@ -934,7 +930,8 @@ struct pipe_inode_info;
 struct uts_namespace;
 
 struct load_weight {
-       unsigned long weight, inv_weight;
+       unsigned long weight;
+       u32 inv_weight;
 };
 
 struct sched_avg {
index 30aa0dc60d75786287226bf3cbedffd9f1b266a3..9d55438bc4ad766bf7f02d250c61d10c61c47b6e 100644 (file)
@@ -47,6 +47,8 @@ extern int shmem_init(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
 extern struct file *shmem_file_setup(const char *name,
                                        loff_t size, unsigned long flags);
+extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
+                                           unsigned long flags);
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
 extern void shmem_unlock_mapping(struct address_space *mapping);
index bec1cc7d5e3c41efbc4939ab742eeb955b64b7f0..215b5ea1cb302c43f0e8b9532fbe3ce59ff0f612 100644 (file)
@@ -2263,6 +2263,24 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
 
+/**
+ *     pskb_trim_rcsum - trim received skb and update checksum
+ *     @skb: buffer to trim
+ *     @len: new length
+ *
+ *     This is exactly the same as pskb_trim except that it ensures the
+ *     checksum of received packets are still valid after the operation.
+ */
+
+static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
+{
+       if (likely(len >= skb->len))
+               return 0;
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->ip_summed = CHECKSUM_NONE;
+       return __pskb_trim(skb, len);
+}
+
 #define skb_queue_walk(queue, skb) \
                for (skb = (queue)->next;                                       \
                     skb != (struct sk_buff *)(queue);                          \
@@ -2360,27 +2378,6 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
 __wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
                    __wsum csum);
 
-/**
- *     pskb_trim_rcsum - trim received skb and update checksum
- *     @skb: buffer to trim
- *     @len: new length
- *
- *     This is exactly the same as pskb_trim except that it ensures the
- *     checksum of received packets are still valid after the operation.
- */
-
-static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
-{
-       if (likely(len >= skb->len))
-               return 0;
-       if (skb->ip_summed == CHECKSUM_COMPLETE) {
-               __wsum adj = skb_checksum(skb, len, skb->len - len, 0);
-
-               skb->csum = csum_sub(skb->csum, adj);
-       }
-       return __pskb_trim(skb, len);
-}
-
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
                                       int len, void *buffer)
 {
index c2bba248fa63d46024930f5b4d6c47b652a51dc6..1e2f4fe12773bdaf9c5ffddd9b5eb77d42b665a0 100644 (file)
@@ -388,10 +388,55 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 /**
  * kmalloc - allocate memory
  * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate (see kcalloc).
+ * @flags: the type of memory to allocate.
  *
  * kmalloc is the normal method of allocating memory
  * for objects smaller than page size in the kernel.
+ *
+ * The @flags argument may be one of:
+ *
+ * %GFP_USER - Allocate memory on behalf of user.  May sleep.
+ *
+ * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
+ *
+ * %GFP_ATOMIC - Allocation will not sleep.  May use emergency pools.
+ *   For example, use this inside interrupt handlers.
+ *
+ * %GFP_HIGHUSER - Allocate pages from high memory.
+ *
+ * %GFP_NOIO - Do not do any I/O at all while trying to get memory.
+ *
+ * %GFP_NOFS - Do not make any fs calls while trying to get memory.
+ *
+ * %GFP_NOWAIT - Allocation will not sleep.
+ *
+ * %GFP_THISNODE - Allocate node-local memory only.
+ *
+ * %GFP_DMA - Allocation suitable for DMA.
+ *   Should only be used for kmalloc() caches. Otherwise, use a
+ *   slab created with SLAB_DMA.
+ *
+ * Also it is possible to set different flags by OR'ing
+ * in one or more of the following additional @flags:
+ *
+ * %__GFP_COLD - Request cache-cold pages instead of
+ *   trying to return cache-warm pages.
+ *
+ * %__GFP_HIGH - This allocation has high priority and may use emergency pools.
+ *
+ * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail
+ *   (think twice before using).
+ *
+ * %__GFP_NORETRY - If memory is not immediately available,
+ *   then give up at once.
+ *
+ * %__GFP_NOWARN - If allocation fails, don't issue any warnings.
+ *
+ * %__GFP_REPEAT - If allocation fails initially, try once more before failing.
+ *
+ * There are other flags available as well, but these are not intended
+ * for general use, and so are not documented here. For a full list of
+ * potential flags, always refer to linux/gfp.h.
  */
 static __always_inline void *kmalloc(size_t size, gfp_t flags)
 {
@@ -501,61 +546,6 @@ struct seq_file;
 int cache_show(struct kmem_cache *s, struct seq_file *m);
 void print_slabinfo_header(struct seq_file *m);
 
-/**
- * kmalloc - allocate memory
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * The @flags argument may be one of:
- *
- * %GFP_USER - Allocate memory on behalf of user.  May sleep.
- *
- * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
- *
- * %GFP_ATOMIC - Allocation will not sleep.  May use emergency pools.
- *   For example, use this inside interrupt handlers.
- *
- * %GFP_HIGHUSER - Allocate pages from high memory.
- *
- * %GFP_NOIO - Do not do any I/O at all while trying to get memory.
- *
- * %GFP_NOFS - Do not make any fs calls while trying to get memory.
- *
- * %GFP_NOWAIT - Allocation will not sleep.
- *
- * %GFP_THISNODE - Allocate node-local memory only.
- *
- * %GFP_DMA - Allocation suitable for DMA.
- *   Should only be used for kmalloc() caches. Otherwise, use a
- *   slab created with SLAB_DMA.
- *
- * Also it is possible to set different flags by OR'ing
- * in one or more of the following additional @flags:
- *
- * %__GFP_COLD - Request cache-cold pages instead of
- *   trying to return cache-warm pages.
- *
- * %__GFP_HIGH - This allocation has high priority and may use emergency pools.
- *
- * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail
- *   (think twice before using).
- *
- * %__GFP_NORETRY - If memory is not immediately available,
- *   then give up at once.
- *
- * %__GFP_NOWARN - If allocation fails, don't issue any warnings.
- *
- * %__GFP_REPEAT - If allocation fails initially, try once more before failing.
- *
- * There are other flags available as well, but these are not intended
- * for general use, and so are not documented here. For a full list of
- * potential flags, always refer to linux/gfp.h.
- *
- * kmalloc is the normal method of allocating memory
- * in the kernel.
- */
-static __always_inline void *kmalloc(size_t size, gfp_t flags);
-
 /**
  * kmalloc_array - allocate memory for an array.
  * @n: number of elements.
index c98cfa40695248d16ab3ee91891c33334239c252..fd4498329c7c509b3614ad820c7c717d976afa2f 100644 (file)
@@ -45,6 +45,7 @@ struct clk;
 
 #define TEGRA_POWERGATE_3D0    TEGRA_POWERGATE_3D
 
+#ifdef CONFIG_ARCH_TEGRA
 int tegra_powergate_is_powered(int id);
 int tegra_powergate_power_on(int id);
 int tegra_powergate_power_off(int id);
@@ -52,5 +53,31 @@ int tegra_powergate_remove_clamping(int id);
 
 /* Must be called with clk disabled, and returns with clk enabled */
 int tegra_powergate_sequence_power_up(int id, struct clk *clk);
+#else
+static inline int tegra_powergate_is_powered(int id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_powergate_power_on(int id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_powergate_power_off(int id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_powergate_remove_clamping(int id)
+{
+       return -ENOSYS;
+}
+
+static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk)
+{
+       return -ENOSYS;
+}
+#endif
 
 #endif /* _MACH_TEGRA_POWERGATE_H_ */
index ebeab360d851c1ece4952b3f5f4f294aa9673db0..f16dc0a4004976376c9036a244e1121ed52ed020 100644 (file)
@@ -267,6 +267,8 @@ static inline void tracepoint_synchronize_unregister(void)
 
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #endif /* DECLARE_TRACE */
 
 #ifndef TRACE_EVENT
@@ -399,4 +401,6 @@ static inline void tracepoint_synchronize_unregister(void)
 
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #endif /* ifdef TRACE_EVENT (see note above) */
index 7454865ad14834f50a05dc9baf7f6d78ea3de7b8..512ab162832ccc0bb4b30f6210d083d762573b78 100644 (file)
@@ -1264,6 +1264,8 @@ typedef void (*usb_complete_t)(struct urb *);
  * @sg: scatter gather buffer list, the buffer size of each element in
  *     the list (except the last) must be divisible by the endpoint's
  *     max packet size if no_sg_constraint isn't set in 'struct usb_bus'
+ *     (FIXME: scatter-gather under xHCI is broken for periodic transfers.
+ *     Do not use urb->sg for interrupt endpoints for now, only bulk.)
  * @num_mapped_sgs: (internal) number of mapped sg entries
  * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
index 0c4d4ca370ec9ba2e88c90b5d9a34b1efc9bc557..eeb28329fa3c9a17087834e2bb2f4d054757a005 100644 (file)
@@ -271,6 +271,8 @@ static inline u8 wusb_key_index(int index, int type, int originator)
 #define WUSB_KEY_INDEX_TYPE_GTK                        2
 #define WUSB_KEY_INDEX_ORIGINATOR_HOST         0
 #define WUSB_KEY_INDEX_ORIGINATOR_DEVICE       1
+/* bits 0-3 used for the key index. */
+#define WUSB_KEY_INDEX_MAX                     15
 
 /* A CCM Nonce, defined in WUSB1.0[6.4.1] */
 struct aes_ccm_nonce {
index bd8218b15009a810af8abd5df5a4bcad31dfdb20..941055e9d125af3bfe5a6915ff551e0bb1532445 100644 (file)
@@ -83,7 +83,7 @@ struct vb2_fileio_data;
 struct vb2_mem_ops {
        void            *(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
        void            (*put)(void *buf_priv);
-       struct dma_buf *(*get_dmabuf)(void *buf_priv);
+       struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 
        void            *(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
                                        unsigned long size, int write);
index 217bc5bfc6c6e99cf52117312ceda95c98f005a6..5a25f36fe3a7cb50a388e309df9b5905f013b6b4 100644 (file)
@@ -473,7 +473,7 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
 int ip_ra_control(struct sock *sk, unsigned char on,
                  void (*destructor)(struct sock *));
 
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
 void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
                   u32 info, u8 *payload);
 void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
index 2a5f668cd6836fae6ff45e551f8dacfd93dacd8e..488316e339a124fa55fdeac686a4fc6d28c0dd2c 100644 (file)
@@ -110,7 +110,8 @@ struct frag_hdr {
        __be32  identification;
 };
 
-#define        IP6_MF  0x0001
+#define        IP6_MF          0x0001
+#define        IP6_OFFSET      0xFFF8
 
 #include <net/sock.h>
 
@@ -776,8 +777,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
 
 int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
 
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                   int *addr_len);
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+                    int *addr_len);
 void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
                     u32 info, u8 *payload);
 void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
index 3f67704f3747281b3ad0852fd5d69dcd49c9b01c..90f48417b03dac91259aefe18d79c63145a23849 100644 (file)
@@ -31,7 +31,8 @@
 
 /* Compatibility glue so we can support IPv6 when it's compiled as a module */
 struct pingv6_ops {
-       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
+       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len,
+                              int *addr_len);
        int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
                                     struct sk_buff *skb);
        int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
index 2174d8da0770a5285d3d937a1174eb9e52dd2a27..67b5d0068273e64ac94125861699e790a9d06e9d 100644 (file)
@@ -629,6 +629,7 @@ struct sctp_chunk {
 #define SCTP_NEED_FRTX 0x1
 #define SCTP_DONT_FRTX 0x2
        __u16   rtt_in_progress:1,      /* This chunk used for RTT calc? */
+               resent:1,               /* Has this chunk ever been resent. */
                has_tsn:1,              /* Does this chunk have a TSN yet? */
                has_ssn:1,              /* Does this chunk have a SSN yet? */
                singleton:1,            /* Only chunk in the packet? */
@@ -1725,12 +1726,6 @@ struct sctp_association {
        /* How many duplicated TSNs have we seen?  */
        int numduptsns;
 
-       /* Number of seconds of idle time before an association is closed.
-        * In the association context, this is really used as a boolean
-        * since the real timeout is stored in the timeouts array
-        */
-       __u32 autoclose;
-
        /* These are to support
         * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses
         *  and Enforcement of Flow and Message Limits"
index e3a18ff0c38b58aec20413489bf7237c54a14a77..2ef3c3eca47aacaa28ee25aecd236897d276845a 100644 (file)
@@ -1035,7 +1035,6 @@ enum cg_proto_flags {
 };
 
 struct cg_proto {
-       void                    (*enter_memory_pressure)(struct sock *sk);
        struct res_counter      memory_allocated;       /* Current allocated memory. */
        struct percpu_counter   sockets_allocated;      /* Current number of sockets. */
        int                     memory_pressure;
@@ -1155,8 +1154,7 @@ static inline void sk_leave_memory_pressure(struct sock *sk)
                struct proto *prot = sk->sk_prot;
 
                for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
-                       if (cg_proto->memory_pressure)
-                               cg_proto->memory_pressure = 0;
+                       cg_proto->memory_pressure = 0;
        }
 
 }
@@ -1171,7 +1169,7 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
                struct proto *prot = sk->sk_prot;
 
                for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
-                       cg_proto->enter_memory_pressure(sk);
+                       cg_proto->memory_pressure = 1;
        }
 
        sk->sk_prot->enter_memory_pressure(sk);
index 979874c627ee7f450c7aabff5c948cb2c87f84c3..61e1935c91b121d0ba6a9e5d6f05221d15060432 100644 (file)
@@ -978,7 +978,7 @@ struct ib_uobject {
 };
 
 struct ib_udata {
-       void __user *inbuf;
+       const void __user *inbuf;
        void __user *outbuf;
        size_t       inlen;
        size_t       outlen;
index 546084964d554fc8e463e9244558fce4e4eb8563..fe3b58e836c881b7598d37c46d56cbd6d1b81b6e 100644 (file)
@@ -475,6 +475,9 @@ struct scsi_host_template {
         */
        unsigned ordered_tag:1;
 
+       /* True if the controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Countdown for host blocking with no commands outstanding.
         */
@@ -677,6 +680,9 @@ struct Scsi_Host {
        /* Don't resume host in EH */
        unsigned eh_noresume:1;
 
+       /* The controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Optional work queue to be utilized by the transport
         */
index 7c2be4a51894484e8a05fe08d11751c1cc7e04ab..bbabf84bdb443114fcd33d4b3a4bbc3172385a8b 100644 (file)
@@ -16,17 +16,11 @@ struct cs42l52_platform_data {
        /* MICBIAS Level. Check datasheet Pg48 */
        unsigned int micbias_lvl;
 
-       /* MICA mode selection 0=Single 1=Differential */
-       unsigned int mica_cfg;
+       /* MICA mode selection Differential or Single-ended */
+       bool mica_diff_cfg;
 
-       /* MICB mode selection 0=Single 1=Differential */
-       unsigned int micb_cfg;
-
-       /* MICA Select 0=MIC1A 1=MIC2A */
-       unsigned int mica_sel;
-
-       /* MICB Select 0=MIC2A 1=MIC2B */
-       unsigned int micb_sel;
+       /* MICB mode selection Differential or Single-ended */
+       bool micb_diff_cfg;
 
        /* Charge Pump Freq. Check datasheet Pg73 */
        unsigned int chgfreq;
index 4ef986cab182ec62565ced32541c5f301058c2c7..eb73a3a39ec2fbb9a3b4aef39ff65e21af9d51b4 100644 (file)
@@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
  * @compat_filter_fn: Will be used as the filter function when requesting a
  *  channel for platforms which do not use devicetree. The filter parameter
  *  will be the DAI's DMA data.
+ * @dma_dev: If set, request DMA channel on this device rather than the DAI
+ *  device.
+ * @chan_names: If set, these custom DMA channel names will be requested at
+ *  registration time.
  * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
  * @prealloc_buffer_size: Size of the preallocated audio buffer.
  *
@@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
                        struct snd_soc_pcm_runtime *rtd,
                        struct snd_pcm_substream *substream);
        dma_filter_fn compat_filter_fn;
+       struct device *dma_dev;
+       const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
 
        const struct snd_pcm_hardware *pcm_hardware;
        unsigned int prealloc_buffer_size;
diff --git a/include/sound/hda_verbs.h b/include/sound/hda_verbs.h
new file mode 100644 (file)
index 0000000..d0509db
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * HD-audio codec verbs
+ */
+
+#ifndef __SOUND_HDA_VERBS_H
+#define __SOUND_HDA_VERBS_H
+
+/*
+ * nodes
+ */
+#define        AC_NODE_ROOT            0x00
+
+/*
+ * function group types
+ */
+enum {
+       AC_GRP_AUDIO_FUNCTION = 0x01,
+       AC_GRP_MODEM_FUNCTION = 0x02,
+};
+
+/*
+ * widget types
+ */
+enum {
+       AC_WID_AUD_OUT,         /* Audio Out */
+       AC_WID_AUD_IN,          /* Audio In */
+       AC_WID_AUD_MIX,         /* Audio Mixer */
+       AC_WID_AUD_SEL,         /* Audio Selector */
+       AC_WID_PIN,             /* Pin Complex */
+       AC_WID_POWER,           /* Power */
+       AC_WID_VOL_KNB,         /* Volume Knob */
+       AC_WID_BEEP,            /* Beep Generator */
+       AC_WID_VENDOR = 0x0f    /* Vendor specific */
+};
+
+/*
+ * GET verbs
+ */
+#define AC_VERB_GET_STREAM_FORMAT              0x0a00
+#define AC_VERB_GET_AMP_GAIN_MUTE              0x0b00
+#define AC_VERB_GET_PROC_COEF                  0x0c00
+#define AC_VERB_GET_COEF_INDEX                 0x0d00
+#define AC_VERB_PARAMETERS                     0x0f00
+#define AC_VERB_GET_CONNECT_SEL                        0x0f01
+#define AC_VERB_GET_CONNECT_LIST               0x0f02
+#define AC_VERB_GET_PROC_STATE                 0x0f03
+#define AC_VERB_GET_SDI_SELECT                 0x0f04
+#define AC_VERB_GET_POWER_STATE                        0x0f05
+#define AC_VERB_GET_CONV                       0x0f06
+#define AC_VERB_GET_PIN_WIDGET_CONTROL         0x0f07
+#define AC_VERB_GET_UNSOLICITED_RESPONSE       0x0f08
+#define AC_VERB_GET_PIN_SENSE                  0x0f09
+#define AC_VERB_GET_BEEP_CONTROL               0x0f0a
+#define AC_VERB_GET_EAPD_BTLENABLE             0x0f0c
+#define AC_VERB_GET_DIGI_CONVERT_1             0x0f0d
+#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e /* unused */
+#define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
+/* f10-f1a: GPIO */
+#define AC_VERB_GET_GPIO_DATA                  0x0f15
+#define AC_VERB_GET_GPIO_MASK                  0x0f16
+#define AC_VERB_GET_GPIO_DIRECTION             0x0f17
+#define AC_VERB_GET_GPIO_WAKE_MASK             0x0f18
+#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK  0x0f19
+#define AC_VERB_GET_GPIO_STICKY_MASK           0x0f1a
+#define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
+/* f20: AFG/MFG */
+#define AC_VERB_GET_SUBSYSTEM_ID               0x0f20
+#define AC_VERB_GET_CVT_CHAN_COUNT             0x0f2d
+#define AC_VERB_GET_HDMI_DIP_SIZE              0x0f2e
+#define AC_VERB_GET_HDMI_ELDD                  0x0f2f
+#define AC_VERB_GET_HDMI_DIP_INDEX             0x0f30
+#define AC_VERB_GET_HDMI_DIP_DATA              0x0f31
+#define AC_VERB_GET_HDMI_DIP_XMIT              0x0f32
+#define AC_VERB_GET_HDMI_CP_CTRL               0x0f33
+#define AC_VERB_GET_HDMI_CHAN_SLOT             0x0f34
+#define AC_VERB_GET_DEVICE_SEL                 0xf35
+#define AC_VERB_GET_DEVICE_LIST                        0xf36
+
+/*
+ * SET verbs
+ */
+#define AC_VERB_SET_STREAM_FORMAT              0x200
+#define AC_VERB_SET_AMP_GAIN_MUTE              0x300
+#define AC_VERB_SET_PROC_COEF                  0x400
+#define AC_VERB_SET_COEF_INDEX                 0x500
+#define AC_VERB_SET_CONNECT_SEL                        0x701
+#define AC_VERB_SET_PROC_STATE                 0x703
+#define AC_VERB_SET_SDI_SELECT                 0x704
+#define AC_VERB_SET_POWER_STATE                        0x705
+#define AC_VERB_SET_CHANNEL_STREAMID           0x706
+#define AC_VERB_SET_PIN_WIDGET_CONTROL         0x707
+#define AC_VERB_SET_UNSOLICITED_ENABLE         0x708
+#define AC_VERB_SET_PIN_SENSE                  0x709
+#define AC_VERB_SET_BEEP_CONTROL               0x70a
+#define AC_VERB_SET_EAPD_BTLENABLE             0x70c
+#define AC_VERB_SET_DIGI_CONVERT_1             0x70d
+#define AC_VERB_SET_DIGI_CONVERT_2             0x70e
+#define AC_VERB_SET_VOLUME_KNOB_CONTROL                0x70f
+#define AC_VERB_SET_GPIO_DATA                  0x715
+#define AC_VERB_SET_GPIO_MASK                  0x716
+#define AC_VERB_SET_GPIO_DIRECTION             0x717
+#define AC_VERB_SET_GPIO_WAKE_MASK             0x718
+#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK  0x719
+#define AC_VERB_SET_GPIO_STICKY_MASK           0x71a
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0     0x71c
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1     0x71d
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2     0x71e
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3     0x71f
+#define AC_VERB_SET_EAPD                               0x788
+#define AC_VERB_SET_CODEC_RESET                        0x7ff
+#define AC_VERB_SET_CVT_CHAN_COUNT             0x72d
+#define AC_VERB_SET_HDMI_DIP_INDEX             0x730
+#define AC_VERB_SET_HDMI_DIP_DATA              0x731
+#define AC_VERB_SET_HDMI_DIP_XMIT              0x732
+#define AC_VERB_SET_HDMI_CP_CTRL               0x733
+#define AC_VERB_SET_HDMI_CHAN_SLOT             0x734
+#define AC_VERB_SET_DEVICE_SEL                 0x735
+
+/*
+ * Parameter IDs
+ */
+#define AC_PAR_VENDOR_ID               0x00
+#define AC_PAR_SUBSYSTEM_ID            0x01
+#define AC_PAR_REV_ID                  0x02
+#define AC_PAR_NODE_COUNT              0x04
+#define AC_PAR_FUNCTION_TYPE           0x05
+#define AC_PAR_AUDIO_FG_CAP            0x08
+#define AC_PAR_AUDIO_WIDGET_CAP                0x09
+#define AC_PAR_PCM                     0x0a
+#define AC_PAR_STREAM                  0x0b
+#define AC_PAR_PIN_CAP                 0x0c
+#define AC_PAR_AMP_IN_CAP              0x0d
+#define AC_PAR_CONNLIST_LEN            0x0e
+#define AC_PAR_POWER_STATE             0x0f
+#define AC_PAR_PROC_CAP                        0x10
+#define AC_PAR_GPIO_CAP                        0x11
+#define AC_PAR_AMP_OUT_CAP             0x12
+#define AC_PAR_VOL_KNB_CAP             0x13
+#define AC_PAR_DEVLIST_LEN             0x15
+#define AC_PAR_HDMI_LPCM_CAP           0x20
+
+/*
+ * AC_VERB_PARAMETERS results (32bit)
+ */
+
+/* Function Group Type */
+#define AC_FGT_TYPE                    (0xff<<0)
+#define AC_FGT_TYPE_SHIFT              0
+#define AC_FGT_UNSOL_CAP               (1<<8)
+
+/* Audio Function Group Capabilities */
+#define AC_AFG_OUT_DELAY               (0xf<<0)
+#define AC_AFG_IN_DELAY                        (0xf<<8)
+#define AC_AFG_BEEP_GEN                        (1<<16)
+
+/* Audio Widget Capabilities */
+#define AC_WCAP_STEREO                 (1<<0)  /* stereo I/O */
+#define AC_WCAP_IN_AMP                 (1<<1)  /* AMP-in present */
+#define AC_WCAP_OUT_AMP                        (1<<2)  /* AMP-out present */
+#define AC_WCAP_AMP_OVRD               (1<<3)  /* AMP-parameter override */
+#define AC_WCAP_FORMAT_OVRD            (1<<4)  /* format override */
+#define AC_WCAP_STRIPE                 (1<<5)  /* stripe */
+#define AC_WCAP_PROC_WID               (1<<6)  /* Proc Widget */
+#define AC_WCAP_UNSOL_CAP              (1<<7)  /* Unsol capable */
+#define AC_WCAP_CONN_LIST              (1<<8)  /* connection list */
+#define AC_WCAP_DIGITAL                        (1<<9)  /* digital I/O */
+#define AC_WCAP_POWER                  (1<<10) /* power control */
+#define AC_WCAP_LR_SWAP                        (1<<11) /* L/R swap */
+#define AC_WCAP_CP_CAPS                        (1<<12) /* content protection */
+#define AC_WCAP_CHAN_CNT_EXT           (7<<13) /* channel count ext */
+#define AC_WCAP_DELAY                  (0xf<<16)
+#define AC_WCAP_DELAY_SHIFT            16
+#define AC_WCAP_TYPE                   (0xf<<20)
+#define AC_WCAP_TYPE_SHIFT             20
+
+/* supported PCM rates and bits */
+#define AC_SUPPCM_RATES                        (0xfff << 0)
+#define AC_SUPPCM_BITS_8               (1<<16)
+#define AC_SUPPCM_BITS_16              (1<<17)
+#define AC_SUPPCM_BITS_20              (1<<18)
+#define AC_SUPPCM_BITS_24              (1<<19)
+#define AC_SUPPCM_BITS_32              (1<<20)
+
+/* supported PCM stream format */
+#define AC_SUPFMT_PCM                  (1<<0)
+#define AC_SUPFMT_FLOAT32              (1<<1)
+#define AC_SUPFMT_AC3                  (1<<2)
+
+/* GP I/O count */
+#define AC_GPIO_IO_COUNT               (0xff<<0)
+#define AC_GPIO_O_COUNT                        (0xff<<8)
+#define AC_GPIO_O_COUNT_SHIFT          8
+#define AC_GPIO_I_COUNT                        (0xff<<16)
+#define AC_GPIO_I_COUNT_SHIFT          16
+#define AC_GPIO_UNSOLICITED            (1<<30)
+#define AC_GPIO_WAKE                   (1<<31)
+
+/* Converter stream, channel */
+#define AC_CONV_CHANNEL                        (0xf<<0)
+#define AC_CONV_STREAM                 (0xf<<4)
+#define AC_CONV_STREAM_SHIFT           4
+
+/* Input converter SDI select */
+#define AC_SDI_SELECT                  (0xf<<0)
+
+/* stream format id */
+#define AC_FMT_CHAN_SHIFT              0
+#define AC_FMT_CHAN_MASK               (0x0f << 0)
+#define AC_FMT_BITS_SHIFT              4
+#define AC_FMT_BITS_MASK               (7 << 4)
+#define AC_FMT_BITS_8                  (0 << 4)
+#define AC_FMT_BITS_16                 (1 << 4)
+#define AC_FMT_BITS_20                 (2 << 4)
+#define AC_FMT_BITS_24                 (3 << 4)
+#define AC_FMT_BITS_32                 (4 << 4)
+#define AC_FMT_DIV_SHIFT               8
+#define AC_FMT_DIV_MASK                        (7 << 8)
+#define AC_FMT_MULT_SHIFT              11
+#define AC_FMT_MULT_MASK               (7 << 11)
+#define AC_FMT_BASE_SHIFT              14
+#define AC_FMT_BASE_48K                        (0 << 14)
+#define AC_FMT_BASE_44K                        (1 << 14)
+#define AC_FMT_TYPE_SHIFT              15
+#define AC_FMT_TYPE_PCM                        (0 << 15)
+#define AC_FMT_TYPE_NON_PCM            (1 << 15)
+
+/* Unsolicited response control */
+#define AC_UNSOL_TAG                   (0x3f<<0)
+#define AC_UNSOL_ENABLED               (1<<7)
+#define AC_USRSP_EN                    AC_UNSOL_ENABLED
+
+/* Unsolicited responses */
+#define AC_UNSOL_RES_TAG               (0x3f<<26)
+#define AC_UNSOL_RES_TAG_SHIFT         26
+#define AC_UNSOL_RES_SUBTAG            (0x1f<<21)
+#define AC_UNSOL_RES_SUBTAG_SHIFT      21
+#define AC_UNSOL_RES_DE                        (0x3f<<15)  /* Device Entry
+                                                    * (for DP1.2 MST)
+                                                    */
+#define AC_UNSOL_RES_DE_SHIFT          15
+#define AC_UNSOL_RES_IA                        (1<<2)  /* Inactive (for DP1.2 MST) */
+#define AC_UNSOL_RES_ELDV              (1<<1)  /* ELD Data valid (for HDMI) */
+#define AC_UNSOL_RES_PD                        (1<<0)  /* pinsense detect */
+#define AC_UNSOL_RES_CP_STATE          (1<<1)  /* content protection */
+#define AC_UNSOL_RES_CP_READY          (1<<0)  /* content protection */
+
+/* Pin widget capabilies */
+#define AC_PINCAP_IMP_SENSE            (1<<0)  /* impedance sense capable */
+#define AC_PINCAP_TRIG_REQ             (1<<1)  /* trigger required */
+#define AC_PINCAP_PRES_DETECT          (1<<2)  /* presence detect capable */
+#define AC_PINCAP_HP_DRV               (1<<3)  /* headphone drive capable */
+#define AC_PINCAP_OUT                  (1<<4)  /* output capable */
+#define AC_PINCAP_IN                   (1<<5)  /* input capable */
+#define AC_PINCAP_BALANCE              (1<<6)  /* balanced I/O capable */
+/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
+ *       but is marked reserved in the Intel HDA specification.
+ */
+#define AC_PINCAP_LR_SWAP              (1<<7)  /* L/R swap */
+/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
+ *       in HD-audio specification
+ */
+#define AC_PINCAP_HDMI                 (1<<7)  /* HDMI pin */
+#define AC_PINCAP_DP                   (1<<24) /* DisplayPort pin, can
+                                                * coexist with AC_PINCAP_HDMI
+                                                */
+#define AC_PINCAP_VREF                 (0x37<<8)
+#define AC_PINCAP_VREF_SHIFT           8
+#define AC_PINCAP_EAPD                 (1<<16) /* EAPD capable */
+#define AC_PINCAP_HBR                  (1<<27) /* High Bit Rate */
+/* Vref status (used in pin cap) */
+#define AC_PINCAP_VREF_HIZ             (1<<0)  /* Hi-Z */
+#define AC_PINCAP_VREF_50              (1<<1)  /* 50% */
+#define AC_PINCAP_VREF_GRD             (1<<2)  /* ground */
+#define AC_PINCAP_VREF_80              (1<<4)  /* 80% */
+#define AC_PINCAP_VREF_100             (1<<5)  /* 100% */
+
+/* Amplifier capabilities */
+#define AC_AMPCAP_OFFSET               (0x7f<<0)  /* 0dB offset */
+#define AC_AMPCAP_OFFSET_SHIFT         0
+#define AC_AMPCAP_NUM_STEPS            (0x7f<<8)  /* number of steps */
+#define AC_AMPCAP_NUM_STEPS_SHIFT      8
+#define AC_AMPCAP_STEP_SIZE            (0x7f<<16) /* step size 0-32dB
+                                                   * in 0.25dB
+                                                   */
+#define AC_AMPCAP_STEP_SIZE_SHIFT      16
+#define AC_AMPCAP_MUTE                 (1<<31)    /* mute capable */
+#define AC_AMPCAP_MUTE_SHIFT           31
+
+/* driver-specific amp-caps: using bits 24-30 */
+#define AC_AMPCAP_MIN_MUTE             (1 << 30) /* min-volume = mute */
+
+/* Connection list */
+#define AC_CLIST_LENGTH                        (0x7f<<0)
+#define AC_CLIST_LONG                  (1<<7)
+
+/* Supported power status */
+#define AC_PWRST_D0SUP                 (1<<0)
+#define AC_PWRST_D1SUP                 (1<<1)
+#define AC_PWRST_D2SUP                 (1<<2)
+#define AC_PWRST_D3SUP                 (1<<3)
+#define AC_PWRST_D3COLDSUP             (1<<4)
+#define AC_PWRST_S3D3COLDSUP           (1<<29)
+#define AC_PWRST_CLKSTOP               (1<<30)
+#define AC_PWRST_EPSS                  (1U<<31)
+
+/* Power state values */
+#define AC_PWRST_SETTING               (0xf<<0)
+#define AC_PWRST_ACTUAL                        (0xf<<4)
+#define AC_PWRST_ACTUAL_SHIFT          4
+#define AC_PWRST_D0                    0x00
+#define AC_PWRST_D1                    0x01
+#define AC_PWRST_D2                    0x02
+#define AC_PWRST_D3                    0x03
+#define AC_PWRST_ERROR                  (1<<8)
+#define AC_PWRST_CLK_STOP_OK            (1<<9)
+#define AC_PWRST_SETTING_RESET          (1<<10)
+
+/* Processing capabilies */
+#define AC_PCAP_BENIGN                 (1<<0)
+#define AC_PCAP_NUM_COEF               (0xff<<8)
+#define AC_PCAP_NUM_COEF_SHIFT         8
+
+/* Volume knobs capabilities */
+#define AC_KNBCAP_NUM_STEPS            (0x7f<<0)
+#define AC_KNBCAP_DELTA                        (1<<7)
+
+/* HDMI LPCM capabilities */
+#define AC_LPCMCAP_48K_CP_CHNS         (0x0f<<0) /* max channels w/ CP-on */
+#define AC_LPCMCAP_48K_NO_CHNS         (0x0f<<4) /* max channels w/o CP-on */
+#define AC_LPCMCAP_48K_20BIT           (1<<8)  /* 20b bitrate supported */
+#define AC_LPCMCAP_48K_24BIT           (1<<9)  /* 24b bitrate supported */
+#define AC_LPCMCAP_96K_CP_CHNS         (0x0f<<10) /* max channels w/ CP-on */
+#define AC_LPCMCAP_96K_NO_CHNS         (0x0f<<14) /* max channels w/o CP-on */
+#define AC_LPCMCAP_96K_20BIT           (1<<18) /* 20b bitrate supported */
+#define AC_LPCMCAP_96K_24BIT           (1<<19) /* 24b bitrate supported */
+#define AC_LPCMCAP_192K_CP_CHNS                (0x0f<<20) /* max channels w/ CP-on */
+#define AC_LPCMCAP_192K_NO_CHNS                (0x0f<<24) /* max channels w/o CP-on */
+#define AC_LPCMCAP_192K_20BIT          (1<<28) /* 20b bitrate supported */
+#define AC_LPCMCAP_192K_24BIT          (1<<29) /* 24b bitrate supported */
+#define AC_LPCMCAP_44K                 (1<<30) /* 44.1kHz support */
+#define AC_LPCMCAP_44K_MS              (1<<31) /* 44.1kHz-multiplies support */
+
+/* Display pin's device list length */
+#define AC_DEV_LIST_LEN_MASK           0x3f
+#define AC_MAX_DEV_LIST_LEN            64
+
+/*
+ * Control Parameters
+ */
+
+/* Amp gain/mute */
+#define AC_AMP_MUTE                    (1<<7)
+#define AC_AMP_GAIN                    (0x7f)
+#define AC_AMP_GET_INDEX               (0xf<<0)
+
+#define AC_AMP_GET_LEFT                        (1<<13)
+#define AC_AMP_GET_RIGHT               (0<<13)
+#define AC_AMP_GET_OUTPUT              (1<<15)
+#define AC_AMP_GET_INPUT               (0<<15)
+
+#define AC_AMP_SET_INDEX               (0xf<<8)
+#define AC_AMP_SET_INDEX_SHIFT         8
+#define AC_AMP_SET_RIGHT               (1<<12)
+#define AC_AMP_SET_LEFT                        (1<<13)
+#define AC_AMP_SET_INPUT               (1<<14)
+#define AC_AMP_SET_OUTPUT              (1<<15)
+
+/* DIGITAL1 bits */
+#define AC_DIG1_ENABLE                 (1<<0)
+#define AC_DIG1_V                      (1<<1)
+#define AC_DIG1_VCFG                   (1<<2)
+#define AC_DIG1_EMPHASIS               (1<<3)
+#define AC_DIG1_COPYRIGHT              (1<<4)
+#define AC_DIG1_NONAUDIO               (1<<5)
+#define AC_DIG1_PROFESSIONAL           (1<<6)
+#define AC_DIG1_LEVEL                  (1<<7)
+
+/* DIGITAL2 bits */
+#define AC_DIG2_CC                     (0x7f<<0)
+
+/* DIGITAL3 bits */
+#define AC_DIG3_ICT                    (0xf<<0)
+#define AC_DIG3_KAE                    (1<<7)
+
+/* Pin widget control - 8bit */
+#define AC_PINCTL_EPT                  (0x3<<0)
+#define AC_PINCTL_EPT_NATIVE           0
+#define AC_PINCTL_EPT_HBR              3
+#define AC_PINCTL_VREFEN               (0x7<<0)
+#define AC_PINCTL_VREF_HIZ             0       /* Hi-Z */
+#define AC_PINCTL_VREF_50              1       /* 50% */
+#define AC_PINCTL_VREF_GRD             2       /* ground */
+#define AC_PINCTL_VREF_80              4       /* 80% */
+#define AC_PINCTL_VREF_100             5       /* 100% */
+#define AC_PINCTL_IN_EN                        (1<<5)
+#define AC_PINCTL_OUT_EN               (1<<6)
+#define AC_PINCTL_HP_EN                        (1<<7)
+
+/* Pin sense - 32bit */
+#define AC_PINSENSE_IMPEDANCE_MASK     (0x7fffffff)
+#define AC_PINSENSE_PRESENCE           (1<<31)
+#define AC_PINSENSE_ELDV               (1<<30) /* ELD valid (HDMI) */
+
+/* EAPD/BTL enable - 32bit */
+#define AC_EAPDBTL_BALANCED            (1<<0)
+#define AC_EAPDBTL_EAPD                        (1<<1)
+#define AC_EAPDBTL_LR_SWAP             (1<<2)
+
+/* HDMI ELD data */
+#define AC_ELDD_ELD_VALID              (1<<31)
+#define AC_ELDD_ELD_DATA               0xff
+
+/* HDMI DIP size */
+#define AC_DIPSIZE_ELD_BUF             (1<<3) /* ELD buf size of packet size */
+#define AC_DIPSIZE_PACK_IDX            (0x07<<0) /* packet index */
+
+/* HDMI DIP index */
+#define AC_DIPIDX_PACK_IDX             (0x07<<5) /* packet idnex */
+#define AC_DIPIDX_BYTE_IDX             (0x1f<<0) /* byte index */
+
+/* HDMI DIP xmit (transmit) control */
+#define AC_DIPXMIT_MASK                        (0x3<<6)
+#define AC_DIPXMIT_DISABLE             (0x0<<6) /* disable xmit */
+#define AC_DIPXMIT_ONCE                        (0x2<<6) /* xmit once then disable */
+#define AC_DIPXMIT_BEST                        (0x3<<6) /* best effort */
+
+/* HDMI content protection (CP) control */
+#define AC_CPCTRL_CES                  (1<<9) /* current encryption state */
+#define AC_CPCTRL_READY                        (1<<8) /* ready bit */
+#define AC_CPCTRL_SUBTAG               (0x1f<<3) /* subtag for unsol-resp */
+#define AC_CPCTRL_STATE                        (3<<0) /* current CP request state */
+
+/* Converter channel <-> HDMI slot mapping */
+#define AC_CVTMAP_HDMI_SLOT            (0xf<<0) /* HDMI slot number */
+#define AC_CVTMAP_CHAN                 (0xf<<4) /* converter channel number */
+
+/* configuration default - 32bit */
+#define AC_DEFCFG_SEQUENCE             (0xf<<0)
+#define AC_DEFCFG_DEF_ASSOC            (0xf<<4)
+#define AC_DEFCFG_ASSOC_SHIFT          4
+#define AC_DEFCFG_MISC                 (0xf<<8)
+#define AC_DEFCFG_MISC_SHIFT           8
+#define AC_DEFCFG_MISC_NO_PRESENCE     (1<<0)
+#define AC_DEFCFG_COLOR                        (0xf<<12)
+#define AC_DEFCFG_COLOR_SHIFT          12
+#define AC_DEFCFG_CONN_TYPE            (0xf<<16)
+#define AC_DEFCFG_CONN_TYPE_SHIFT      16
+#define AC_DEFCFG_DEVICE               (0xf<<20)
+#define AC_DEFCFG_DEVICE_SHIFT         20
+#define AC_DEFCFG_LOCATION             (0x3f<<24)
+#define AC_DEFCFG_LOCATION_SHIFT       24
+#define AC_DEFCFG_PORT_CONN            (0x3<<30)
+#define AC_DEFCFG_PORT_CONN_SHIFT      30
+
+/* Display pin's device list entry */
+#define AC_DE_PD                       (1<<0)
+#define AC_DE_ELDV                     (1<<1)
+#define AC_DE_IA                       (1<<2)
+
+/* device device types (0x0-0xf) */
+enum {
+       AC_JACK_LINE_OUT,
+       AC_JACK_SPEAKER,
+       AC_JACK_HP_OUT,
+       AC_JACK_CD,
+       AC_JACK_SPDIF_OUT,
+       AC_JACK_DIG_OTHER_OUT,
+       AC_JACK_MODEM_LINE_SIDE,
+       AC_JACK_MODEM_HAND_SIDE,
+       AC_JACK_LINE_IN,
+       AC_JACK_AUX,
+       AC_JACK_MIC_IN,
+       AC_JACK_TELEPHONY,
+       AC_JACK_SPDIF_IN,
+       AC_JACK_DIG_OTHER_IN,
+       AC_JACK_OTHER = 0xf,
+};
+
+/* jack connection types (0x0-0xf) */
+enum {
+       AC_JACK_CONN_UNKNOWN,
+       AC_JACK_CONN_1_8,
+       AC_JACK_CONN_1_4,
+       AC_JACK_CONN_ATAPI,
+       AC_JACK_CONN_RCA,
+       AC_JACK_CONN_OPTICAL,
+       AC_JACK_CONN_OTHER_DIGITAL,
+       AC_JACK_CONN_OTHER_ANALOG,
+       AC_JACK_CONN_DIN,
+       AC_JACK_CONN_XLR,
+       AC_JACK_CONN_RJ11,
+       AC_JACK_CONN_COMB,
+       AC_JACK_CONN_OTHER = 0xf,
+};
+
+/* jack colors (0x0-0xf) */
+enum {
+       AC_JACK_COLOR_UNKNOWN,
+       AC_JACK_COLOR_BLACK,
+       AC_JACK_COLOR_GREY,
+       AC_JACK_COLOR_BLUE,
+       AC_JACK_COLOR_GREEN,
+       AC_JACK_COLOR_RED,
+       AC_JACK_COLOR_ORANGE,
+       AC_JACK_COLOR_YELLOW,
+       AC_JACK_COLOR_PURPLE,
+       AC_JACK_COLOR_PINK,
+       AC_JACK_COLOR_WHITE = 0xe,
+       AC_JACK_COLOR_OTHER,
+};
+
+/* Jack location (0x0-0x3f) */
+/* common case */
+enum {
+       AC_JACK_LOC_NONE,
+       AC_JACK_LOC_REAR,
+       AC_JACK_LOC_FRONT,
+       AC_JACK_LOC_LEFT,
+       AC_JACK_LOC_RIGHT,
+       AC_JACK_LOC_TOP,
+       AC_JACK_LOC_BOTTOM,
+};
+/* bits 4-5 */
+enum {
+       AC_JACK_LOC_EXTERNAL = 0x00,
+       AC_JACK_LOC_INTERNAL = 0x10,
+       AC_JACK_LOC_SEPARATE = 0x20,
+       AC_JACK_LOC_OTHER    = 0x30,
+};
+enum {
+       /* external on primary chasis */
+       AC_JACK_LOC_REAR_PANEL = 0x07,
+       AC_JACK_LOC_DRIVE_BAY,
+       /* internal */
+       AC_JACK_LOC_RISER = 0x17,
+       AC_JACK_LOC_HDMI,
+       AC_JACK_LOC_ATAPI,
+       /* others */
+       AC_JACK_LOC_MOBILE_IN = 0x37,
+       AC_JACK_LOC_MOBILE_OUT,
+};
+
+/* Port connectivity (0-3) */
+enum {
+       AC_JACK_PORT_COMPLEX,
+       AC_JACK_PORT_NONE,
+       AC_JACK_PORT_FIXED,
+       AC_JACK_PORT_BOTH,
+};
+
+/* max. codec address */
+#define HDA_MAX_CODEC_ADDRESS  0x0f
+
+#endif /* __SOUND_HDA_VERBS_H */
index af998397041768a82ee347665e7040a9a4e44b9c..782d1df342082da5327c4c763a571482712b8f49 100644 (file)
@@ -108,7 +108,7 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
 {
        struct snd_sg_buf *sgbuf = dmab->private_data;
        dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
-       addr &= PAGE_MASK;
+       addr &= ~((dma_addr_t)PAGE_SIZE - 1);
        return addr + offset % PAGE_SIZE;
 }
 
@@ -149,13 +149,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
                                  struct snd_dma_buffer *dmab);
 void snd_dma_free_pages(struct snd_dma_buffer *dmab);
 
-/* buffer-preservation managements */
-
-#define snd_dma_pci_buf_id(pci)        (((unsigned int)(pci)->vendor << 16) | (pci)->device)
-
-size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
-int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
-
 /* basic memory allocation functions */
 void *snd_malloc_pages(size_t size, gfp_t gfp_flags);
 void snd_free_pages(void *ptr, size_t size);
index 84b10f9a28324951a2a56d1cc89df9d50e0623bb..4883499ab38b07834dc6b4ee3fe085bf93b0efdf 100644 (file)
@@ -381,7 +381,6 @@ struct snd_pcm_substream {
        struct pm_qos_request latency_pm_qos_req; /* pm_qos request */
        size_t buffer_bytes_max;        /* limit ring buffer size */
        struct snd_dma_buffer dma_buffer;
-       unsigned int dma_buf_id;
        size_t dma_max;
        /* -- hardware operations -- */
        const struct snd_pcm_ops *ops;
@@ -901,6 +900,8 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
 int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
 unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
 unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
+unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
+                                        unsigned int rates_b);
 
 static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
                                              struct snd_dma_buffer *bufp)
index 37ae12e0ab06d323ab50f78a97225392f6541dbf..6b1c78f05fab49f3617dcef673d98c70a8fd256b 100644 (file)
@@ -354,4 +354,16 @@ params_period_bytes(const struct snd_pcm_hw_params *p)
                params_channels(p)) / 8;
 }
 
+static inline int
+params_width(const struct snd_pcm_hw_params *p)
+{
+       return snd_pcm_format_width(params_format(p));
+}
+
+static inline int
+params_physical_width(const struct snd_pcm_hw_params *p)
+{
+       return snd_pcm_format_physical_width(params_format(p));
+}
+
 #endif /* __SOUND_PCM_PARAMS_H */
index 12afab18945d056709df7495b75b0da6c0155426..e147498abe5090ac348a2e9497d18e4bd10bd9d2 100644 (file)
@@ -18,7 +18,7 @@
 #define RSND_GEN1_ADG  1
 #define RSND_GEN1_SSI  2
 
-#define RSND_GEN2_SRU  0
+#define RSND_GEN2_SCU  0
 #define RSND_GEN2_ADG  1
 #define RSND_GEN2_SSIU 2
 #define RSND_GEN2_SSI  3
@@ -58,6 +58,7 @@ struct rsnd_ssi_platform_info {
 
 struct rsnd_scu_platform_info {
        u32 flags;
+       u32 convert_rate; /* sampling rate convert */
 };
 
 /*
index 800c101bb096fd6f5c1170ebbdce1ab06cead062..71f27c403194f19ed26a189bfed3252f7177747b 100644 (file)
@@ -123,6 +123,8 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
                             int direction);
 
+int snd_soc_dai_is_dummy(struct snd_soc_dai *dai);
+
 struct snd_soc_dai_ops {
        /*
         * DAI clocking configuration, all optional.
@@ -220,6 +222,8 @@ struct snd_soc_dai_driver {
        struct snd_soc_pcm_stream capture;
        struct snd_soc_pcm_stream playback;
        unsigned int symmetric_rates:1;
+       unsigned int symmetric_channels:1;
+       unsigned int symmetric_samplebits:1;
 
        /* probe ordering - for components with runtime dependencies */
        int probe_order;
@@ -244,6 +248,8 @@ struct snd_soc_dai {
        unsigned int capture_active:1;          /* stream is in use */
        unsigned int playback_active:1;         /* stream is in use */
        unsigned int symmetric_rates:1;
+       unsigned int symmetric_channels:1;
+       unsigned int symmetric_samplebits:1;
        struct snd_pcm_runtime *runtime;
        unsigned int active;
        unsigned char probed:1;
@@ -258,6 +264,8 @@ struct snd_soc_dai {
 
        /* Symmetry data - only valid if symmetry is being enforced */
        unsigned int rate;
+       unsigned int channels;
+       unsigned int sample_bits;
 
        /* parent platform/codec */
        struct snd_soc_platform *platform;
index 2037c45adfe648e907fa86290f7dfea847989c20..68d92e36facda52f6e4b249e108bd43c8847e92e 100644 (file)
@@ -104,7 +104,8 @@ struct device;
        SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{      .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
+{      .id = snd_soc_dapm_mux, .name = wname, \
+       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
 {      .id = snd_soc_dapm_virt_mux, .name = wname, \
@@ -411,6 +412,7 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
                                 struct snd_soc_dai *dai);
 int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
+void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
 int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
                         const struct snd_soc_pcm_stream *params,
                         struct snd_soc_dapm_widget *source,
index 1f741cb24f337c3e4662c2ff2cd45f78985c54c1..03ce45bf8ade2cefb6c70df8a5f3687da6242db4 100644 (file)
@@ -334,9 +334,7 @@ struct snd_soc_jack_pin;
 #include <sound/soc-dapm.h>
 #include <sound/soc-dpcm.h>
 
-#ifdef CONFIG_GPIOLIB
 struct snd_soc_jack_gpio;
-#endif
 
 typedef int (*hw_write_t)(void *,const char* ,int);
 
@@ -446,6 +444,17 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                        struct snd_soc_jack_gpio *gpios);
 void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
                        struct snd_soc_jack_gpio *gpios);
+#else
+static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
+                                        struct snd_soc_jack_gpio *gpios)
+{
+       return 0;
+}
+
+static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
+                                          struct snd_soc_jack_gpio *gpios)
+{
+}
 #endif
 
 /* codec register bit access */
@@ -580,7 +589,6 @@ struct snd_soc_jack_zone {
  *                    to provide more complex checks (eg, reading an
  *                    ADC).
  */
-#ifdef CONFIG_GPIOLIB
 struct snd_soc_jack_gpio {
        unsigned int gpio;
        const char *name;
@@ -594,7 +602,6 @@ struct snd_soc_jack_gpio {
 
        int (*jack_status_check)(void);
 };
-#endif
 
 struct snd_soc_jack {
        struct mutex mutex;
@@ -879,6 +886,8 @@ struct snd_soc_dai_link {
 
        /* Symmetry requirements */
        unsigned int symmetric_rates:1;
+       unsigned int symmetric_channels:1;
+       unsigned int symmetric_samplebits:1;
 
        /* Do not create a PCM for this DAI link (Backend link) */
        unsigned int no_pcm:1;
@@ -886,6 +895,10 @@ struct snd_soc_dai_link {
        /* This DAI link can route to other DAI links at runtime (Frontend)*/
        unsigned int dynamic:1;
 
+       /* DPCM capture and Playback support */
+       unsigned int dpcm_capture:1;
+       unsigned int dpcm_playback:1;
+
        /* pmdown_time is ignored at stop */
        unsigned int ignore_pmdown_time:1;
 
index 1b365bfdfb3720714736ed33a7a544f8d46f7456..65aca51fe255e487f4a3b36e5708b5159b089c03 100644 (file)
@@ -29,7 +29,6 @@ struct spear_dma_data {
        dma_addr_t addr;
        u32 max_burst;
        enum dma_slave_buswidth addr_width;
-       bool (*filter)(struct dma_chan *chan, void *slave);
 };
 
 #endif /* SPEAR_DMA_H */
index 45412a6afa69d95ea82c820fb197d350c9d0575e..321301c0a643bfb32303b3f48cecae720f3fad87 100644 (file)
@@ -517,10 +517,6 @@ struct se_node_acl {
        u32                     acl_index;
 #define MAX_ACL_TAG_SIZE 64
        char                    acl_tag[MAX_ACL_TAG_SIZE];
-       u64                     num_cmds;
-       u64                     read_bytes;
-       u64                     write_bytes;
-       spinlock_t              stats_lock;
        /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
        atomic_t                acl_pr_ref_count;
        struct se_dev_entry     **device_list;
@@ -624,6 +620,7 @@ struct se_dev_attrib {
        u32             unmap_granularity;
        u32             unmap_granularity_alignment;
        u32             max_write_same_len;
+       u32             max_bytes_per_io;
        struct se_device *da_dev;
        struct config_group da_group;
 };
index 52594b20179e0d8459a0810c7fbcc75fceda84ff..5c38606613d89a06c361a56054e97031c391c2d3 100644 (file)
 #define TRACE_EVENT_FLAGS(name, value)                                 \
        __TRACE_EVENT_FLAGS(name, value)
 
+#undef TRACE_EVENT_PERF_PERM
+#define TRACE_EVENT_PERF_PERM(name, expr...)                           \
+       __TRACE_EVENT_PERF_PERM(name, expr)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 
 #undef TRACE_EVENT_FLAGS
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#undef TRACE_EVENT_PERF_PERM
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 /*
@@ -372,7 +379,8 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call)   \
        __data_size += (len) * sizeof(type);
 
 #undef __string
-#define __string(item, src) __dynamic_array(char, item, strlen(src) + 1)
+#define __string(item, src) __dynamic_array(char, item,                        \
+                   strlen((src) ? (const char *)(src) : "(null)") + 1)
 
 #undef DECLARE_EVENT_CLASS
 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
@@ -501,7 +509,7 @@ static inline notrace int ftrace_get_offsets_##call(                        \
 
 #undef __assign_str
 #define __assign_str(dst, src)                                         \
-       strcpy(__get_str(dst), src);
+       strcpy(__get_str(dst), (src) ? (const char *)(src) : "(null)");
 
 #undef TP_fast_assign
 #define TP_fast_assign(args...) args
index bcb0912afe7a4a233a171f2d1b4bb7d518c6884e..f854ca4a1372812dda6f71c20c8a84b3bdcfc19a 100644 (file)
@@ -75,6 +75,7 @@
 #define DRM_VMW_PARAM_FIFO_CAPS        4
 #define DRM_VMW_PARAM_MAX_FB_SIZE      5
 #define DRM_VMW_PARAM_FIFO_HW_VERSION  6
+#define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
 
 /**
  * struct drm_vmw_getparam_arg
index 2c267bcbb85c1c4e31b676127db7686d8d027e09..bc81fb2e1f0e19d363d3c8095c85b971c521d12a 100644 (file)
@@ -61,5 +61,16 @@ struct epoll_event {
        __u64 data;
 } EPOLL_PACKED;
 
-
+#ifdef CONFIG_PM_SLEEP
+static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
+{
+       if ((epev->events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
+               epev->events &= ~EPOLLWAKEUP;
+}
+#else
+static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
+{
+       epev->events &= ~EPOLLWAKEUP;
+}
+#endif
 #endif /* _UAPI_LINUX_EVENTPOLL_H */
index 1af72d8228e04db8c1d6de05cacfa1bfd4a577b7..c3363ba1ae057f66dc5b878ee9fde7899857c450 100644 (file)
@@ -28,6 +28,7 @@ struct genlmsghdr {
 #define GENL_ID_GENERATE       0
 #define GENL_ID_CTRL           NLMSG_MIN_TYPE
 #define GENL_ID_VFS_DQUOT      (NLMSG_MIN_TYPE + 1)
+#define GENL_ID_PMCRAID                (NLMSG_MIN_TYPE + 2)
 
 /**************************************************************************
  * Controller
index b78566f59abaa54528ed86acf85eb7e7b3f305fa..6db460121f84845d4026420cdc2fd12fc4f1497e 100644 (file)
@@ -488,7 +488,9 @@ enum {
        IFLA_HSR_UNSPEC,
        IFLA_HSR_SLAVE1,
        IFLA_HSR_SLAVE2,
-       IFLA_HSR_MULTICAST_SPEC,
+       IFLA_HSR_MULTICAST_SPEC,        /* Last byte of supervision addr */
+       IFLA_HSR_SUPERVISION_ADDR,      /* Supervision frame multicast addr */
+       IFLA_HSR_SEQ_NR,
        __IFLA_HSR_MAX,
 };
 
index a3726275876dc509bfa99a01b8113385c1fb2d2f..ecc88592ecbe94acfbacd1eda9b5907a832470da 100644 (file)
@@ -719,6 +719,8 @@ struct input_keymap_entry {
 #define BTN_DPAD_LEFT          0x222
 #define BTN_DPAD_RIGHT         0x223
 
+#define KEY_ALS_TOGGLE         0x230   /* Ambient light sensor */
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
@@ -856,6 +858,7 @@ struct input_keymap_entry {
 #define SW_FRONT_PROXIMITY     0x0b  /* set = front proximity sensor active */
 #define SW_ROTATE_LOCK         0x0c  /* set = rotate locked/disabled */
 #define SW_LINEIN_INSERT       0x0d  /* set = inserted */
+#define SW_MUTE_DEVICE         0x0e  /* set = device disabled */
 #define SW_MAX                 0x0f
 #define SW_CNT                 (SW_MAX+1)
 
index 17e7d95e4f536b883cf98ebe363ed3734e9db958..6eb40244e0194110ce6c7e3878f738227ddfb013 100644 (file)
 
 #include <linux/virtio_ring.h>
 
-#ifndef __KERNEL__
-#define ALIGN(a, x)    (((a) + (x) - 1) & ~((x) - 1))
-#define __aligned(x)   __attribute__ ((aligned(x)))
-#endif
-
-#define mic_aligned_size(x) ALIGN(sizeof(x), 8)
+#define __mic_align(a, x) (((a) + (x) - 1) & ~((x) - 1))
 
 /**
  * struct mic_device_desc: Virtio device information shared between the
@@ -48,8 +43,8 @@ struct mic_device_desc {
        __u8 feature_len;
        __u8 config_len;
        __u8 status;
-       __u64 config[0];
-} __aligned(8);
+       __le64 config[0];
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_device_ctrl: Per virtio device information in the device page
@@ -66,7 +61,7 @@ struct mic_device_desc {
  * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
  */
 struct mic_device_ctrl {
-       __u64 vdev;
+       __le64 vdev;
        __u8 config_change;
        __u8 vdev_reset;
        __u8 guest_ack;
@@ -74,7 +69,7 @@ struct mic_device_ctrl {
        __u8 used_address_updated;
        __s8 c2h_vdev_db;
        __s8 h2c_vdev_db;
-} __aligned(8);
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_bootparam: Virtio device independent information in device page
@@ -87,13 +82,13 @@ struct mic_device_ctrl {
  * @shutdown_card: Set to 1 by the host when a card shutdown is initiated
  */
 struct mic_bootparam {
-       __u32 magic;
+       __le32 magic;
        __s8 c2h_shutdown_db;
        __s8 h2c_shutdown_db;
        __s8 h2c_config_db;
        __u8 shutdown_status;
        __u8 shutdown_card;
-} __aligned(8);
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_device_page: High level representation of the device page
@@ -116,10 +111,10 @@ struct mic_device_page {
  * @num: The number of entries in the virtio_ring
  */
 struct mic_vqconfig {
-       __u64 address;
-       __u64 used_address;
-       __u16 num;
-} __aligned(8);
+       __le64 address;
+       __le64 used_address;
+       __le16 num;
+} __attribute__ ((aligned(8)));
 
 /*
  * The alignment to use between consumer and producer parts of vring.
@@ -154,7 +149,7 @@ struct mic_vqconfig {
  */
 struct _mic_vring_info {
        __u16 avail_idx;
-       int magic;
+       __le32 magic;
 };
 
 /**
@@ -173,15 +168,13 @@ struct mic_vring {
        int len;
 };
 
-#define mic_aligned_desc_size(d) ALIGN(mic_desc_size(d), 8)
+#define mic_aligned_desc_size(d) __mic_align(mic_desc_size(d), 8)
 
 #ifndef INTEL_MIC_CARD
 static inline unsigned mic_desc_size(const struct mic_device_desc *desc)
 {
-       return mic_aligned_size(*desc)
-               + desc->num_vq * mic_aligned_size(struct mic_vqconfig)
-               + desc->feature_len * 2
-               + desc->config_len;
+       return sizeof(*desc) + desc->num_vq * sizeof(struct mic_vqconfig)
+               + desc->feature_len * 2 + desc->config_len;
 }
 
 static inline struct mic_vqconfig *
@@ -201,8 +194,7 @@ static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
 }
 static inline unsigned mic_total_desc_size(struct mic_device_desc *desc)
 {
-       return mic_aligned_desc_size(desc) +
-               mic_aligned_size(struct mic_device_ctrl);
+       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
 }
 #endif
 
index 4e31db4eea412dcfc3c56364d734b420f36afaef..f2159d30d1f5a24c76d6e939318603e72faa2637 100644 (file)
@@ -33,6 +33,7 @@ struct netlink_diag_ring {
 };
 
 enum {
+       /* NETLINK_DIAG_NONE, standard nl API requires this attribute!  */
        NETLINK_DIAG_MEMINFO,
        NETLINK_DIAG_GROUPS,
        NETLINK_DIAG_RX_RING,
index b2cc0cd9c4d9782433b4203e24480267257071ce..d08c63f3dd6ff47c7cf090927e91f27cfc0d767f 100644 (file)
@@ -29,6 +29,7 @@ struct packet_diag_msg {
 };
 
 enum {
+       /* PACKET_DIAG_NONE, standard nl API requires this attribute!  */
        PACKET_DIAG_INFO,
        PACKET_DIAG_MCLIST,
        PACKET_DIAG_RX_RING,
index e1802d6153aec4d0c5fd81300dcde057d9bf8a59..959d454f76a185c87ce7fc223a229d37db2564f8 100644 (file)
@@ -679,6 +679,7 @@ enum perf_event_type {
         *
         *      { u64                   weight;   } && PERF_SAMPLE_WEIGHT
         *      { u64                   data_src; } && PERF_SAMPLE_DATA_SRC
+        *      { u64                   transaction; } && PERF_SAMPLE_TRANSACTION
         * };
         */
        PERF_RECORD_SAMPLE                      = 9,
index b9e2a6a7446f077e528dd15fac8e8d97f0d9a232..1eb0b8dd18308481313b9d13b284f897a56188aa 100644 (file)
@@ -31,6 +31,7 @@ struct unix_diag_msg {
 };
 
 enum {
+       /* UNIX_DIAG_NONE, standard nl API requires this attribute!  */
        UNIX_DIAG_NAME,
        UNIX_DIAG_VFS,
        UNIX_DIAG_PEER,
index d630163b9a2e6d46f079b00357be501d3b5335fc..5759810e1c1b9768f67f8e703c625b7ce9d76e94 100644 (file)
@@ -30,7 +30,7 @@
 #include <sound/compress_params.h>
 
 
-#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 1)
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 2)
 /**
  * struct snd_compressed_buffer: compressed buffer
  * @fragment_size: size of buffer fragment in bytes
@@ -67,8 +67,8 @@ struct snd_compr_params {
 struct snd_compr_tstamp {
        __u32 byte_offset;
        __u32 copied_total;
-       snd_pcm_uframes_t pcm_frames;
-       snd_pcm_uframes_t pcm_io_frames;
+       __u32 pcm_frames;
+       __u32 pcm_io_frames;
        __u32 sampling_rate;
 };
 
index 602dc6c45d1a091fb548ac586c69813f25f4f508..165e7059de75173ec1bf29dcfb9138c35a4a3956 100644 (file)
@@ -57,6 +57,7 @@
 #define MAX_NUM_CODECS 32
 #define MAX_NUM_CODEC_DESCRIPTORS 32
 #define MAX_NUM_BITRATES 32
+#define MAX_NUM_SAMPLE_RATES 32
 
 /* Codecs are listed linearly to allow for extensibility */
 #define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
@@ -324,7 +325,8 @@ union snd_codec_options {
 
 /** struct snd_codec_desc - description of codec capabilities
  * @max_ch: Maximum number of audio channels
- * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @sample_rates: Sampling rates in Hz, use values like 48000 for this
+ * @num_sample_rates: Number of valid values in sample_rates array
  * @bit_rate: Indexed array containing supported bit rates
  * @num_bitrates: Number of valid values in bit_rate array
  * @rate_control: value is specified by SND_RATECONTROLMODE defines.
@@ -346,7 +348,8 @@ union snd_codec_options {
 
 struct snd_codec_desc {
        __u32 max_ch;
-       __u32 sample_rates;
+       __u32 sample_rates[MAX_NUM_SAMPLE_RATES];
+       __u32 num_sample_rates;
        __u32 bit_rate[MAX_NUM_BITRATES];
        __u32 num_bitrates;
        __u32 rate_control;
@@ -364,7 +367,8 @@ struct snd_codec_desc {
  * @ch_out: Number of output channels. In case of contradiction between
  *             this field and the channelMode field, the channelMode field
  *             overrides.
- * @sample_rate: Audio sample rate of input data
+ * @sample_rate: Audio sample rate of input data in Hz, use values like 48000
+ *             for this.
  * @bit_rate: Bitrate of encoded data. May be ignored by decoders
  * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
  *               Encoders may rely on profiles for quality levels.
index 65e12099ef89d9f3b5706858d956d8aabe427348..ae665ac59c36b6812a0470d5a7e0124c3e13a69f 100644 (file)
@@ -146,7 +146,7 @@ struct blkif_request_segment_aligned {
 struct blkif_request_rw {
        uint8_t        nr_segments;  /* number of segments                   */
        blkif_vdev_t   handle;       /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_request,u.rw.id) == 8 */
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -163,7 +163,7 @@ struct blkif_request_discard {
        uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero.        */
 #define BLKIF_DISCARD_SECURE (1<<0)  /* ignored if discard-secure=0          */
        blkif_vdev_t   _pad1;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad2;        /* offsetof(blkif_req..,u.discard.id)==8*/
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -175,7 +175,7 @@ struct blkif_request_discard {
 struct blkif_request_other {
        uint8_t      _pad1;
        blkif_vdev_t _pad2;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
 #endif
        uint64_t     id;           /* private guest value, echoed in resp  */
@@ -184,7 +184,7 @@ struct blkif_request_other {
 struct blkif_request_indirect {
        uint8_t        indirect_op;
        uint16_t       nr_segments;
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_...,u.indirect.id) == 8 */
 #endif
        uint64_t       id;
@@ -192,7 +192,7 @@ struct blkif_request_indirect {
        blkif_vdev_t   handle;
        uint16_t       _pad2;
        grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t      _pad3;         /* make it 64 byte aligned */
 #else
        uint64_t      _pad3;         /* make it 64 byte aligned */
index 79383d3aa5dc5f7fe64abdcaf7d511144ca016e5..4e5d96ab2034c25e2c1bb38d4ab9e619f8e04e86 100644 (file)
@@ -809,6 +809,12 @@ config GENERIC_SCHED_CLOCK
 config ARCH_SUPPORTS_NUMA_BALANCING
        bool
 
+#
+# For architectures that know their GCC __int128 support is sound
+#
+config ARCH_SUPPORTS_INT128
+       bool
+
 # For architectures that (ab)use NUMA to represent different memory regions
 # all cpu-local but of different latencies, such as SuperH.
 #
index b3097bde4e9cbc999e5d09205db8014e0da27632..790d83c7d16071ffb96827fc4a372fd9b8eb4c5f 100644 (file)
@@ -5,3 +5,4 @@ config_data.h
 config_data.gz
 timeconst.h
 hz.bc
+x509_certificate_list
index bbaf7d59c1bb14f166441e6532b55585790e4b52..bc010ee272b6cfec39892e6cb04b98cc06995e1a 100644 (file)
@@ -137,9 +137,10 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
 ###############################################################################
 ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
 X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
-X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
-X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
+X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509
+X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
                                $(or $(realpath $(CERT)),$(CERT))))
+X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw))
 
 ifeq ($(X509_CERTIFICATES),)
 $(warning *** No X.509 certificates found ***)
@@ -164,9 +165,9 @@ $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
 targets += $(obj)/.x509.list
 $(obj)/.x509.list:
        @echo $(X509_CERTIFICATES) >$@
+endif
 
 clean-files := x509_certificate_list .x509.list
-endif
 
 ifeq ($(CONFIG_MODULE_SIG),y)
 ###############################################################################
index 5253204afdcace55e89cda669aaf2896eba23aaa..9fd4246b04b8298ec608dbba4d9ee9997e105fbc 100644 (file)
@@ -22,6 +22,6 @@ void foo(void)
 #ifdef CONFIG_SMP
        DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS));
 #endif
-       DEFINE(BLOATED_SPINLOCKS, sizeof(spinlock_t) > sizeof(int));
+       DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
        /* End of constants */
 }
index 4c62513fe19fc8c4b938aeb8b3acb5158da2f976..bc1dcabe92176636baf79c7ef52e597422aeaf75 100644 (file)
@@ -89,6 +89,14 @@ static DEFINE_MUTEX(cgroup_mutex);
 
 static DEFINE_MUTEX(cgroup_root_mutex);
 
+/*
+ * cgroup destruction makes heavy use of work items and there can be a lot
+ * of concurrent destructions.  Use a separate workqueue so that cgroup
+ * destruction work items don't end up filling up max_active of system_wq
+ * which may lead to deadlock.
+ */
+static struct workqueue_struct *cgroup_destroy_wq;
+
 /*
  * Generate an array of cgroup subsystem pointers. At boot time, this is
  * populated with the built in subsystems, and modular subsystems are
@@ -191,6 +199,7 @@ static void cgroup_destroy_css_killed(struct cgroup *cgrp);
 static int cgroup_destroy_locked(struct cgroup *cgrp);
 static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
                              bool is_add);
+static int cgroup_file_release(struct inode *inode, struct file *file);
 
 /**
  * cgroup_css - obtain a cgroup's css for the specified subsystem
@@ -871,7 +880,7 @@ static void cgroup_free_rcu(struct rcu_head *head)
        struct cgroup *cgrp = container_of(head, struct cgroup, rcu_head);
 
        INIT_WORK(&cgrp->destroy_work, cgroup_free_fn);
-       schedule_work(&cgrp->destroy_work);
+       queue_work(cgroup_destroy_wq, &cgrp->destroy_work);
 }
 
 static void cgroup_diput(struct dentry *dentry, struct inode *inode)
@@ -881,6 +890,16 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                struct cgroup *cgrp = dentry->d_fsdata;
 
                BUG_ON(!(cgroup_is_dead(cgrp)));
+
+               /*
+                * XXX: cgrp->id is only used to look up css's.  As cgroup
+                * and css's lifetimes will be decoupled, it should be made
+                * per-subsystem and moved to css->id so that lookups are
+                * successful until the target css is released.
+                */
+               idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+               cgrp->id = -1;
+
                call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
        } else {
                struct cfent *cfe = __d_cfe(dentry);
@@ -2421,7 +2440,7 @@ static const struct file_operations cgroup_seqfile_operations = {
        .read = seq_read,
        .write = cgroup_file_write,
        .llseek = seq_lseek,
-       .release = single_release,
+       .release = cgroup_file_release,
 };
 
 static int cgroup_file_open(struct inode *inode, struct file *file)
@@ -2482,6 +2501,8 @@ static int cgroup_file_release(struct inode *inode, struct file *file)
                ret = cft->release(inode, file);
        if (css->ss)
                css_put(css);
+       if (file->f_op == &cgroup_seqfile_operations)
+               single_release(inode, file);
        return ret;
 }
 
@@ -4249,7 +4270,7 @@ static void css_free_rcu_fn(struct rcu_head *rcu_head)
         * css_put().  dput() requires process context which we don't have.
         */
        INIT_WORK(&css->destroy_work, css_free_work_fn);
-       schedule_work(&css->destroy_work);
+       queue_work(cgroup_destroy_wq, &css->destroy_work);
 }
 
 static void css_release(struct percpu_ref *ref)
@@ -4257,6 +4278,7 @@ static void css_release(struct percpu_ref *ref)
        struct cgroup_subsys_state *css =
                container_of(ref, struct cgroup_subsys_state, refcnt);
 
+       rcu_assign_pointer(css->cgroup->subsys[css->ss->subsys_id], NULL);
        call_rcu(&css->rcu_head, css_free_rcu_fn);
 }
 
@@ -4415,14 +4437,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
        root->number_of_cgroups++;
 
-       /* each css holds a ref to the cgroup's dentry and the parent css */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               dget(dentry);
-               css_get(css->parent);
-       }
-
        /* hold a ref to the parent's dentry */
        dget(parent->dentry);
 
@@ -4434,6 +4448,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                if (err)
                        goto err_destroy;
 
+               /* each css holds a ref to the cgroup's dentry and parent css */
+               dget(dentry);
+               css_get(css->parent);
+
+               /* mark it consumed for error path */
+               css_ar[ss->subsys_id] = NULL;
+
                if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
                    parent->parent) {
                        pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
@@ -4480,6 +4501,14 @@ err_free_cgrp:
        return err;
 
 err_destroy:
+       for_each_root_subsys(root, ss) {
+               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
+
+               if (css) {
+                       percpu_ref_cancel_init(&css->refcnt);
+                       ss->css_free(css);
+               }
+       }
        cgroup_destroy_locked(cgrp);
        mutex_unlock(&cgroup_mutex);
        mutex_unlock(&dentry->d_inode->i_mutex);
@@ -4539,7 +4568,7 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
                container_of(ref, struct cgroup_subsys_state, refcnt);
 
        INIT_WORK(&css->destroy_work, css_killed_work_fn);
-       schedule_work(&css->destroy_work);
+       queue_work(cgroup_destroy_wq, &css->destroy_work);
 }
 
 /**
@@ -4641,8 +4670,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
         * will be invoked to perform the rest of destruction once the
         * percpu refs of all css's are confirmed to be killed.
         */
-       for_each_root_subsys(cgrp->root, ss)
-               kill_css(cgroup_css(cgrp, ss));
+       for_each_root_subsys(cgrp->root, ss) {
+               struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
+
+               if (css)
+                       kill_css(css);
+       }
 
        /*
         * Mark @cgrp dead.  This prevents further task migration and child
@@ -4711,14 +4744,6 @@ static void cgroup_destroy_css_killed(struct cgroup *cgrp)
        /* delete this cgroup from parent->children */
        list_del_rcu(&cgrp->sibling);
 
-       /*
-        * We should remove the cgroup object from idr before its grace
-        * period starts, so we won't be looking up a cgroup while the
-        * cgroup is being freed.
-        */
-       idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
-       cgrp->id = -1;
-
        dput(d);
 
        set_bit(CGRP_RELEASABLE, &parent->flags);
@@ -5063,6 +5088,22 @@ out:
        return err;
 }
 
+static int __init cgroup_wq_init(void)
+{
+       /*
+        * There isn't much point in executing destruction path in
+        * parallel.  Good chunk is serialized with cgroup_mutex anyway.
+        * Use 1 for @max_active.
+        *
+        * We would prefer to do this in cgroup_init() above, but that
+        * is called before init_workqueues(): so leave this until after.
+        */
+       cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1);
+       BUG_ON(!cgroup_destroy_wq);
+       return 0;
+}
+core_initcall(cgroup_wq_init);
+
 /*
  * proc_cgroup_show()
  *  - Print task's cgroup paths into seq_file, one line for each hierarchy
index 6bf981e13c437ff81979f4c9f08f69998c8ca45a..4772034b4b17062a4506bc4f437c599b8d5f2ac3 100644 (file)
@@ -1033,8 +1033,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
        need_loop = task_has_mempolicy(tsk) ||
                        !nodes_intersects(*newmems, tsk->mems_allowed);
 
-       if (need_loop)
+       if (need_loop) {
+               local_irq_disable();
                write_seqcount_begin(&tsk->mems_allowed_seq);
+       }
 
        nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
        mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1);
@@ -1042,8 +1044,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
        mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP2);
        tsk->mems_allowed = *newmems;
 
-       if (need_loop)
+       if (need_loop) {
                write_seqcount_end(&tsk->mems_allowed_seq);
+               local_irq_enable();
+       }
 
        task_unlock(tsk);
 }
index d724e7757cd1ec2df7a9c2ac9be1b0c23f6e4e71..f5744010a8d2f980f1902279de41a866ceb00a37 100644 (file)
@@ -1396,6 +1396,8 @@ event_sched_out(struct perf_event *event,
        if (event->state != PERF_EVENT_STATE_ACTIVE)
                return;
 
+       perf_pmu_disable(event->pmu);
+
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
@@ -1412,6 +1414,8 @@ event_sched_out(struct perf_event *event,
                ctx->nr_freq--;
        if (event->attr.exclusive || !cpuctx->active_oncpu)
                cpuctx->exclusive = 0;
+
+       perf_pmu_enable(event->pmu);
 }
 
 static void
@@ -1652,6 +1656,7 @@ event_sched_in(struct perf_event *event,
                 struct perf_event_context *ctx)
 {
        u64 tstamp = perf_event_time(event);
+       int ret = 0;
 
        if (event->state <= PERF_EVENT_STATE_OFF)
                return 0;
@@ -1674,10 +1679,13 @@ event_sched_in(struct perf_event *event,
         */
        smp_wmb();
 
+       perf_pmu_disable(event->pmu);
+
        if (event->pmu->add(event, PERF_EF_START)) {
                event->state = PERF_EVENT_STATE_INACTIVE;
                event->oncpu = -1;
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto out;
        }
 
        event->tstamp_running += tstamp - event->tstamp_stopped;
@@ -1693,7 +1701,10 @@ event_sched_in(struct perf_event *event,
        if (event->attr.exclusive)
                cpuctx->exclusive = 1;
 
-       return 0;
+out:
+       perf_pmu_enable(event->pmu);
+
+       return ret;
 }
 
 static int
@@ -2743,6 +2754,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                if (!event_filter_match(event))
                        continue;
 
+               perf_pmu_disable(event->pmu);
+
                hwc = &event->hw;
 
                if (hwc->interrupts == MAX_INTERRUPTS) {
@@ -2752,7 +2765,7 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                }
 
                if (!event->attr.freq || !event->attr.sample_freq)
-                       continue;
+                       goto next;
 
                /*
                 * stop the event and update event->count
@@ -2774,6 +2787,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                        perf_adjust_period(event, period, delta, false);
 
                event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
+       next:
+               perf_pmu_enable(event->pmu);
        }
 
        perf_pmu_enable(ctx->pmu);
@@ -5680,11 +5695,6 @@ static void swevent_hlist_put(struct perf_event *event)
 {
        int cpu;
 
-       if (event->cpu != -1) {
-               swevent_hlist_put_cpu(event, event->cpu);
-               return;
-       }
-
        for_each_possible_cpu(cpu)
                swevent_hlist_put_cpu(event, cpu);
 }
@@ -5718,9 +5728,6 @@ static int swevent_hlist_get(struct perf_event *event)
        int err;
        int cpu, failed_cpu;
 
-       if (event->cpu != -1)
-               return swevent_hlist_get_cpu(event, event->cpu);
-
        get_online_cpus();
        for_each_possible_cpu(cpu) {
                err = swevent_hlist_get_cpu(event, cpu);
index 832cb28105bbb7900a6c1342a095179303734215..763faf037ec1cccb135b98d1deccf339f69cd2e5 100644 (file)
@@ -61,7 +61,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
 static inline int init_kernel_text(unsigned long addr)
 {
        if (addr >= (unsigned long)_sinittext &&
-           addr <= (unsigned long)_einittext)
+           addr < (unsigned long)_einittext)
                return 1;
        return 0;
 }
@@ -69,7 +69,7 @@ static inline int init_kernel_text(unsigned long addr)
 int core_kernel_text(unsigned long addr)
 {
        if (addr >= (unsigned long)_stext &&
-           addr <= (unsigned long)_etext)
+           addr < (unsigned long)_etext)
                return 1;
 
        if (system_state == SYSTEM_BOOTING &&
index 728d5be9548ce61913c85e14303248363eae0a31..5721f0e3f2da4d1d4bcbc788b4016c944bbfea03 100644 (file)
@@ -537,6 +537,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
        spin_lock_init(&mm->page_table_lock);
        mm_init_aio(mm);
        mm_init_owner(mm, p);
+       clear_tlb_flush_pending(mm);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
index b462fa197517b6176701fa860cdb966bc44a69ba..aa6a8aadb911fb323b4662a4652c95ff4319f0c5 100644 (file)
@@ -19,6 +19,12 @@ EXPORT_SYMBOL(system_freezing_cnt);
 bool pm_freezing;
 bool pm_nosig_freezing;
 
+/*
+ * Temporary export for the deadlock workaround in ata_scsi_hotplug().
+ * Remove once the hack becomes unnecessary.
+ */
+EXPORT_SYMBOL_GPL(pm_freezing);
+
 /* protects freezing and frozen transitions */
 static DEFINE_SPINLOCK(freezer_lock);
 
index 80ba086f021d3022afcf3f06ecdb1d920cdc8f7c..f6ff0191ecf72aca1d42f128771af55f9c859d13 100644 (file)
@@ -251,6 +251,9 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
                return -EINVAL;
        address -= key->both.offset;
 
+       if (unlikely(!access_ok(rw, uaddr, sizeof(u32))))
+               return -EFAULT;
+
        /*
         * PROCESS_PRIVATE futexes are fast.
         * As the mm cannot disappear under us and the 'key' only needs
@@ -259,8 +262,6 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
         *        but access_ok() should be faster than find_vma()
         */
        if (!fshared) {
-               if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
-                       return -EFAULT;
                key->private.mm = mm;
                key->private.address = address;
                get_futex_key_refs(key);
@@ -288,7 +289,7 @@ again:
                put_page(page);
                /* serialize against __split_huge_page_splitting() */
                local_irq_disable();
-               if (likely(__get_user_pages_fast(address, 1, 1, &page) == 1)) {
+               if (likely(__get_user_pages_fast(address, 1, !ro, &page) == 1)) {
                        page_head = compound_head(page);
                        /*
                         * page_head is valid pointer but we must pin
index cb228bf217603d6e841c1028dd610598ae133bff..abcd6ca86cb76b56e5979613a1964c0db743b5d0 100644 (file)
@@ -50,7 +50,7 @@ static void resume_irqs(bool want_early)
                bool is_early = desc->action &&
                        desc->action->flags & IRQF_EARLY_RESUME;
 
-               if (is_early != want_early)
+               if (!is_early && want_early)
                        continue;
 
                raw_spin_lock_irqsave(&desc->lock, flags);
index 490afc03627e52e34e51d69e0a15693b7716b17a..9c970167e4025f01be6bd696499eec2504c72ef7 100644 (file)
@@ -47,6 +47,9 @@ u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 size_t vmcoreinfo_size;
 size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
+/* Flag to indicate we are going to kexec a new kernel */
+bool kexec_in_progress = false;
+
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
        .name  = "Crash kernel",
@@ -1675,7 +1678,9 @@ int kernel_kexec(void)
        } else
 #endif
        {
+               kexec_in_progress = true;
                kernel_restart_prepare(NULL);
+               migrate_to_reboot_cpu();
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
        }
index 07af2c95dcfeea37f855db214e8e3405274bddb6..2abd25d79cc87bfc171f491c595d500e161f2de3 100644 (file)
@@ -46,6 +46,7 @@ static int padata_index_to_cpu(struct parallel_data *pd, int cpu_index)
 
 static int padata_cpu_hash(struct parallel_data *pd)
 {
+       unsigned int seq_nr;
        int cpu_index;
 
        /*
@@ -53,10 +54,8 @@ static int padata_cpu_hash(struct parallel_data *pd)
         * seq_nr mod. number of cpus in use.
         */
 
-       spin_lock(&pd->seq_lock);
-       cpu_index =  pd->seq_nr % cpumask_weight(pd->cpumask.pcpu);
-       pd->seq_nr++;
-       spin_unlock(&pd->seq_lock);
+       seq_nr = atomic_inc_return(&pd->seq_nr);
+       cpu_index = seq_nr % cpumask_weight(pd->cpumask.pcpu);
 
        return padata_index_to_cpu(pd, cpu_index);
 }
@@ -429,7 +428,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,
        padata_init_pqueues(pd);
        padata_init_squeues(pd);
        setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd);
-       pd->seq_nr = 0;
+       atomic_set(&pd->seq_nr, -1);
        atomic_set(&pd->reorder_objects, 0);
        atomic_set(&pd->refcnt, 0);
        pd->pinst = pinst;
index 463aa6736751a0a12d949ddeb93330b6067f053b..eacb8bd8cab4e1205230ecfdde12483be9846cf7 100644 (file)
@@ -81,6 +81,7 @@ void pm_vt_switch_unregister(struct device *dev)
        list_for_each_entry(tmp, &pm_vt_switch_list, head) {
                if (tmp->dev == dev) {
                        list_del(&tmp->head);
+                       kfree(tmp);
                        break;
                }
        }
index 6abb03dff5c053f44ef5dbc28f7bf754e5669e78..08a7652324321b132e3fca0f27f7285a609660dc 100644 (file)
@@ -1632,7 +1632,7 @@ module_param(rcu_idle_gp_delay, int, 0644);
 static int rcu_idle_lazy_gp_delay = RCU_IDLE_LAZY_GP_DELAY;
 module_param(rcu_idle_lazy_gp_delay, int, 0644);
 
-extern int tick_nohz_enabled;
+extern int tick_nohz_active;
 
 /*
  * Try to advance callbacks for all flavors of RCU on the current CPU, but
@@ -1729,7 +1729,7 @@ static void rcu_prepare_for_idle(int cpu)
        int tne;
 
        /* Handle nohz enablement switches conservatively. */
-       tne = ACCESS_ONCE(tick_nohz_enabled);
+       tne = ACCESS_ONCE(tick_nohz_active);
        if (tne != rdtp->tick_nohz_enabled_snap) {
                if (rcu_cpu_has_callbacks(cpu, NULL))
                        invoke_rcu_core(); /* force nohz to see update. */
index f813b3474646c5b320a19d9a8997349bdd14d68e..662c83fc16b77ed79b9474c681848858666055e0 100644 (file)
@@ -104,7 +104,7 @@ int unregister_reboot_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_reboot_notifier);
 
-static void migrate_to_reboot_cpu(void)
+void migrate_to_reboot_cpu(void)
 {
        /* The boot cpu is always logical cpu 0 */
        int cpu = reboot_cpu;
index c1808606ee5f0f4e48e2fc51380369ba248bd9fe..a88f4a485c5e5f92190dd5bf784600d79d5f8f18 100644 (file)
@@ -2660,6 +2660,7 @@ asmlinkage void __sched notrace preempt_schedule(void)
        } while (need_resched());
 }
 EXPORT_SYMBOL(preempt_schedule);
+#endif /* CONFIG_PREEMPT */
 
 /*
  * this is the entry point to schedule() from kernel preemption
@@ -2693,8 +2694,6 @@ asmlinkage void __sched preempt_schedule_irq(void)
        exception_exit(prev_state);
 }
 
-#endif /* CONFIG_PREEMPT */
-
 int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
                          void *key)
 {
@@ -4762,7 +4761,7 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd)
                cpumask_clear_cpu(rq->cpu, old_rd->span);
 
                /*
-                * If we dont want to free the old_rt yet then
+                * If we dont want to free the old_rd yet then
                 * set old_rd to NULL to skip the freeing later
                 * in this function:
                 */
@@ -4903,6 +4902,7 @@ DEFINE_PER_CPU(struct sched_domain *, sd_asym);
 static void update_top_cache_domain(int cpu)
 {
        struct sched_domain *sd;
+       struct sched_domain *busy_sd = NULL;
        int id = cpu;
        int size = 1;
 
@@ -4910,8 +4910,9 @@ static void update_top_cache_domain(int cpu)
        if (sd) {
                id = cpumask_first(sched_domain_span(sd));
                size = cpumask_weight(sched_domain_span(sd));
-               rcu_assign_pointer(per_cpu(sd_busy, cpu), sd->parent);
+               busy_sd = sd->parent; /* sd_busy */
        }
+       rcu_assign_pointer(per_cpu(sd_busy, cpu), busy_sd);
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_size, cpu) = size;
@@ -5112,6 +5113,7 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
                 * die on a /0 trap.
                 */
                sg->sgp->power = SCHED_POWER_SCALE * cpumask_weight(sg_span);
+               sg->sgp->power_orig = sg->sgp->power;
 
                /*
                 * Make sure the first group of this domain contains the
index e8b652ebe027c481e87122f629a300058cf82679..c7395d97e4cb7c33f26925569adff8f7e3007d4e 100644 (file)
@@ -178,59 +178,61 @@ void sched_init_granularity(void)
        update_sysctl();
 }
 
-#if BITS_PER_LONG == 32
-# define WMULT_CONST   (~0UL)
-#else
-# define WMULT_CONST   (1UL << 32)
-#endif
-
+#define WMULT_CONST    (~0U)
 #define WMULT_SHIFT    32
 
-/*
- * Shift right and round:
- */
-#define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
+static void __update_inv_weight(struct load_weight *lw)
+{
+       unsigned long w;
+
+       if (likely(lw->inv_weight))
+               return;
+
+       w = scale_load_down(lw->weight);
+
+       if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
+               lw->inv_weight = 1;
+       else if (unlikely(!w))
+               lw->inv_weight = WMULT_CONST;
+       else
+               lw->inv_weight = WMULT_CONST / w;
+}
 
 /*
- * delta *= weight / lw
+ * delta_exec * weight / lw.weight
+ *   OR
+ * (delta_exec * (weight * lw->inv_weight)) >> WMULT_SHIFT
+ *
+ * Either weight := NICE_0_LOAD and lw \e prio_to_wmult[], in which case
+ * we're guaranteed shift stays positive because inv_weight is guaranteed to
+ * fit 32 bits, and NICE_0_LOAD gives another 10 bits; therefore shift >= 22.
+ *
+ * Or, weight =< lw.weight (because lw.weight is the runqueue weight), thus
+ * weight/lw.weight <= 1, and therefore our shift will also be positive.
  */
-static unsigned long
-calc_delta_mine(unsigned long delta_exec, unsigned long weight,
-               struct load_weight *lw)
+static u64 __calc_delta(u64 delta_exec, unsigned long weight, struct load_weight *lw)
 {
-       u64 tmp;
+       u64 fact = scale_load_down(weight);
+       int shift = WMULT_SHIFT;
 
-       /*
-        * weight can be less than 2^SCHED_LOAD_RESOLUTION for task group sched
-        * entities since MIN_SHARES = 2. Treat weight as 1 if less than
-        * 2^SCHED_LOAD_RESOLUTION.
-        */
-       if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION)))
-               tmp = (u64)delta_exec * scale_load_down(weight);
-       else
-               tmp = (u64)delta_exec;
+       __update_inv_weight(lw);
 
-       if (!lw->inv_weight) {
-               unsigned long w = scale_load_down(lw->weight);
-
-               if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
-                       lw->inv_weight = 1;
-               else if (unlikely(!w))
-                       lw->inv_weight = WMULT_CONST;
-               else
-                       lw->inv_weight = WMULT_CONST / w;
+       if (unlikely(fact >> 32)) {
+               while (fact >> 32) {
+                       fact >>= 1;
+                       shift--;
+               }
        }
 
-       /*
-        * Check whether we'd overflow the 64-bit multiplication:
-        */
-       if (unlikely(tmp > WMULT_CONST))
-               tmp = SRR(SRR(tmp, WMULT_SHIFT/2) * lw->inv_weight,
-                       WMULT_SHIFT/2);
-       else
-               tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
+       /* hint to use a 32x32->64 mul */
+       fact = (u64)(u32)fact * lw->inv_weight;
 
-       return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
+       while (fact >> 32) {
+               fact >>= 1;
+               shift--;
+       }
+
+       return mul_u64_u32_shr(delta_exec, fact, shift);
 }
 
 
@@ -443,7 +445,7 @@ find_matching_se(struct sched_entity **se, struct sched_entity **pse)
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
 static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec);
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec);
 
 /**************************************************************
  * Scheduling class tree data structure manipulation methods:
@@ -612,11 +614,10 @@ int sched_proc_update_handler(struct ctl_table *table, int write,
 /*
  * delta /= w
  */
-static inline unsigned long
-calc_delta_fair(unsigned long delta, struct sched_entity *se)
+static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)
 {
        if (unlikely(se->load.weight != NICE_0_LOAD))
-               delta = calc_delta_mine(delta, NICE_0_LOAD, &se->load);
+               delta = __calc_delta(delta, NICE_0_LOAD, &se->load);
 
        return delta;
 }
@@ -665,7 +666,7 @@ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
                        update_load_add(&lw, se->load.weight);
                        load = &lw;
                }
-               slice = calc_delta_mine(slice, se->load.weight, load);
+               slice = __calc_delta(slice, se->load.weight, load);
        }
        return slice;
 }
@@ -703,47 +704,32 @@ void init_task_runnable_average(struct task_struct *p)
 #endif
 
 /*
- * Update the current task's runtime statistics. Skip current tasks that
- * are not in our scheduling class.
+ * Update the current task's runtime statistics.
  */
-static inline void
-__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
-             unsigned long delta_exec)
-{
-       unsigned long delta_exec_weighted;
-
-       schedstat_set(curr->statistics.exec_max,
-                     max((u64)delta_exec, curr->statistics.exec_max));
-
-       curr->sum_exec_runtime += delta_exec;
-       schedstat_add(cfs_rq, exec_clock, delta_exec);
-       delta_exec_weighted = calc_delta_fair(delta_exec, curr);
-
-       curr->vruntime += delta_exec_weighted;
-       update_min_vruntime(cfs_rq);
-}
-
 static void update_curr(struct cfs_rq *cfs_rq)
 {
        struct sched_entity *curr = cfs_rq->curr;
        u64 now = rq_clock_task(rq_of(cfs_rq));
-       unsigned long delta_exec;
+       u64 delta_exec;
 
        if (unlikely(!curr))
                return;
 
-       /*
-        * Get the amount of time the current task was running
-        * since the last time we changed load (this cannot
-        * overflow on 32 bits):
-        */
-       delta_exec = (unsigned long)(now - curr->exec_start);
-       if (!delta_exec)
+       delta_exec = now - curr->exec_start;
+       if (unlikely((s64)delta_exec <= 0))
                return;
 
-       __update_curr(cfs_rq, curr, delta_exec);
        curr->exec_start = now;
 
+       schedstat_set(curr->statistics.exec_max,
+                     max(delta_exec, curr->statistics.exec_max));
+
+       curr->sum_exec_runtime += delta_exec;
+       schedstat_add(cfs_rq, exec_clock, delta_exec);
+
+       curr->vruntime += calc_delta_fair(delta_exec, curr);
+       update_min_vruntime(cfs_rq);
+
        if (entity_is_task(curr)) {
                struct task_struct *curtask = task_of(curr);
 
@@ -1752,6 +1738,13 @@ void task_numa_work(struct callback_head *work)
                    (vma->vm_file && (vma->vm_flags & (VM_READ|VM_WRITE)) == (VM_READ)))
                        continue;
 
+               /*
+                * Skip inaccessible VMAs to avoid any confusion between
+                * PROT_NONE and NUMA hinting ptes
+                */
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+                       continue;
+
                do {
                        start = max(start, vma->vm_start);
                        end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
@@ -3015,8 +3008,7 @@ static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
        }
 }
 
-static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec)
+static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
 {
        /* dock delta_exec before expiring quota (as it could span periods) */
        cfs_rq->runtime_remaining -= delta_exec;
@@ -3034,7 +3026,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
 }
 
 static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec)
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
 {
        if (!cfs_bandwidth_used() || !cfs_rq->runtime_enabled)
                return;
@@ -3574,8 +3566,7 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
        return rq_clock_task(rq_of(cfs_rq));
 }
 
-static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec) {}
+static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec) {}
 static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
 static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
@@ -5379,10 +5370,31 @@ void update_group_power(struct sched_domain *sd, int cpu)
                 */
 
                for_each_cpu(cpu, sched_group_cpus(sdg)) {
-                       struct sched_group *sg = cpu_rq(cpu)->sd->groups;
+                       struct sched_group_power *sgp;
+                       struct rq *rq = cpu_rq(cpu);
+
+                       /*
+                        * build_sched_domains() -> init_sched_groups_power()
+                        * gets here before we've attached the domains to the
+                        * runqueues.
+                        *
+                        * Use power_of(), which is set irrespective of domains
+                        * in update_cpu_power().
+                        *
+                        * This avoids power/power_orig from being 0 and
+                        * causing divide-by-zero issues on boot.
+                        *
+                        * Runtime updates will correct power_orig.
+                        */
+                       if (unlikely(!rq->sd)) {
+                               power_orig += power_of(cpu);
+                               power += power_of(cpu);
+                               continue;
+                       }
 
-                       power_orig += sg->sgp->power_orig;
-                       power += sg->sgp->power;
+                       sgp = rq->sd->groups->sgp;
+                       power_orig += sgp->power_orig;
+                       power += sgp->power;
                }
        } else  {
                /*
index 7d57275fc396d1c56475c707888f1f95fd84142b..1c4065575fa2c44d91250455db38638d728788e8 100644 (file)
@@ -901,6 +901,13 @@ inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && prio < prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, prio);
 }
@@ -910,6 +917,13 @@ dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && rt_rq->highest_prio.curr != prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr);
 }
index 4aef390671cbb9653fc5c64342f656694585f56c..3e9868d47535b44d85e8515070bf86cf5cc6fe81 100644 (file)
@@ -3,8 +3,18 @@
 
        __INITRODATA
 
+       .align 8
        .globl VMLINUX_SYMBOL(system_certificate_list)
 VMLINUX_SYMBOL(system_certificate_list):
+__cert_list_start:
        .incbin "kernel/x509_certificate_list"
-       .globl VMLINUX_SYMBOL(system_certificate_list_end)
-VMLINUX_SYMBOL(system_certificate_list_end):
+__cert_list_end:
+
+       .align 8
+       .globl VMLINUX_SYMBOL(system_certificate_list_size)
+VMLINUX_SYMBOL(system_certificate_list_size):
+#ifdef CONFIG_64BIT
+       .quad __cert_list_end - __cert_list_start
+#else
+       .long __cert_list_end - __cert_list_start
+#endif
index 564dd93430a276b0ac7db03a59cbb5648a639c93..52ebc70263f4d8e806dc436fd55e6000cf818915 100644 (file)
@@ -22,7 +22,7 @@ struct key *system_trusted_keyring;
 EXPORT_SYMBOL_GPL(system_trusted_keyring);
 
 extern __initconst const u8 system_certificate_list[];
-extern __initconst const u8 system_certificate_list_end[];
+extern __initconst const unsigned long system_certificate_list_size;
 
 /*
  * Load the compiled-in keys
@@ -60,8 +60,8 @@ static __init int load_system_certificate_list(void)
 
        pr_notice("Loading compiled-in X.509 certificates\n");
 
-       end = system_certificate_list_end;
        p = system_certificate_list;
+       end = p + system_certificate_list_size;
        while (p < end) {
                /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
                 * than 256 bytes in size.
index 64522ecdfe0e868420acdd7b47a65de99b847748..162b03ab0ad2ed16e3654f7006aae6f88c1886cf 100644 (file)
@@ -33,6 +33,21 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  */
 ktime_t tick_next_period;
 ktime_t tick_period;
+
+/*
+ * tick_do_timer_cpu is a timer core internal variable which holds the CPU NR
+ * which is responsible for calling do_timer(), i.e. the timekeeping stuff. This
+ * variable has two functions:
+ *
+ * 1) Prevent a thundering herd issue of a gazillion of CPUs trying to grab the
+ *    timekeeping lock all at once. Only the CPU which is assigned to do the
+ *    update is handling it.
+ *
+ * 2) Hand off the duty in the NOHZ idle case by setting the value to
+ *    TICK_DO_TIMER_NONE, i.e. a non existing CPU. So the next cpu which looks
+ *    at it will take over and keep the time keeping alive.  The handover
+ *    procedure also covers cpu hotplug.
+ */
 int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
 
 /*
index 3612fc77f834372c0d5d674f3bc5ae609dd64635..ea20f7d1ac2c4f91af4dd8dd4db3b01b5c6ae4b7 100644 (file)
@@ -361,8 +361,8 @@ void __init tick_nohz_init(void)
 /*
  * NO HZ enabled ?
  */
-int tick_nohz_enabled __read_mostly  = 1;
-
+static int tick_nohz_enabled __read_mostly  = 1;
+int tick_nohz_active  __read_mostly;
 /*
  * Enable / Disable tickless mode
  */
@@ -465,7 +465,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t now, idle;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return -1;
 
        now = ktime_get();
@@ -506,7 +506,7 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t now, iowait;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return -1;
 
        now = ktime_get();
@@ -711,8 +711,10 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
                return false;
        }
 
-       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) {
+               ts->sleep_length = (ktime_t) { .tv64 = NSEC_PER_SEC/HZ };
                return false;
+       }
 
        if (need_resched())
                return false;
@@ -799,11 +801,6 @@ void tick_nohz_idle_enter(void)
        local_irq_disable();
 
        ts = &__get_cpu_var(tick_cpu_sched);
-       /*
-        * set ts->inidle unconditionally. even if the system did not
-        * switch to nohz mode the cpu frequency governers rely on the
-        * update of the idle time accounting in tick_nohz_start_idle().
-        */
        ts->inidle = 1;
        __tick_nohz_idle_enter(ts);
 
@@ -973,7 +970,7 @@ static void tick_nohz_switch_to_nohz(void)
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        ktime_t next;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return;
 
        local_irq_disable();
@@ -981,7 +978,7 @@ static void tick_nohz_switch_to_nohz(void)
                local_irq_enable();
                return;
        }
-
+       tick_nohz_active = 1;
        ts->nohz_mode = NOHZ_MODE_LOWRES;
 
        /*
@@ -1139,8 +1136,10 @@ void tick_setup_sched_timer(void)
        }
 
 #ifdef CONFIG_NO_HZ_COMMON
-       if (tick_nohz_enabled)
+       if (tick_nohz_enabled) {
                ts->nohz_mode = NOHZ_MODE_HIGHRES;
+               tick_nohz_active = 1;
+       }
 #endif
 }
 #endif /* HIGH_RES_TIMERS */
index 3abf53418b67c6ee92c16522299a8821856b749d..87b4f00284c9e21f420d0865af937b03eb286f33 100644 (file)
@@ -1347,7 +1347,7 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk)
        tk->xtime_nsec -= remainder;
        tk->xtime_nsec += 1ULL << tk->shift;
        tk->ntp_error += remainder << tk->ntp_error_shift;
-
+       tk->ntp_error -= (1ULL << tk->shift) << tk->ntp_error_shift;
 }
 #else
 #define old_vsyscall_fixup(tk)
index 6582b82fa966d6ba503a7361f8f89f699f4de04d..accfd241b9e5d5c67040407dfa4f3d8603851de2 100644 (file)
@@ -1518,9 +1518,8 @@ static int init_timers_cpu(int cpu)
                        /*
                         * The APs use this path later in boot
                         */
-                       base = kmalloc_node(sizeof(*base),
-                                               GFP_KERNEL | __GFP_ZERO,
-                                               cpu_to_node(cpu));
+                       base = kzalloc_node(sizeof(*base), GFP_KERNEL,
+                                           cpu_to_node(cpu));
                        if (!base)
                                return -ENOMEM;
 
index 22fa556967609465a0dbd98e238ee1d14b52e328..72a0f81dc5a801e62ef5bb400c068705851b32f6 100644 (file)
@@ -367,9 +367,6 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list,
 
 static int __register_ftrace_function(struct ftrace_ops *ops)
 {
-       if (unlikely(ftrace_disabled))
-               return -ENODEV;
-
        if (FTRACE_WARN_ON(ops == &global_ops))
                return -EINVAL;
 
@@ -428,9 +425,6 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
 {
        int ret;
 
-       if (ftrace_disabled)
-               return -ENODEV;
-
        if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED)))
                return -EBUSY;
 
@@ -781,7 +775,7 @@ static int ftrace_profile_init(void)
        int cpu;
        int ret = 0;
 
-       for_each_online_cpu(cpu) {
+       for_each_possible_cpu(cpu) {
                ret = ftrace_profile_init_cpu(cpu);
                if (ret)
                        break;
@@ -2088,10 +2082,15 @@ static void ftrace_startup_enable(int command)
 static int ftrace_startup(struct ftrace_ops *ops, int command)
 {
        bool hash_enable = true;
+       int ret;
 
        if (unlikely(ftrace_disabled))
                return -ENODEV;
 
+       ret = __register_ftrace_function(ops);
+       if (ret)
+               return ret;
+
        ftrace_start_up++;
        command |= FTRACE_UPDATE_CALLS;
 
@@ -2113,12 +2112,17 @@ static int ftrace_startup(struct ftrace_ops *ops, int command)
        return 0;
 }
 
-static void ftrace_shutdown(struct ftrace_ops *ops, int command)
+static int ftrace_shutdown(struct ftrace_ops *ops, int command)
 {
        bool hash_disable = true;
+       int ret;
 
        if (unlikely(ftrace_disabled))
-               return;
+               return -ENODEV;
+
+       ret = __unregister_ftrace_function(ops);
+       if (ret)
+               return ret;
 
        ftrace_start_up--;
        /*
@@ -2153,9 +2157,10 @@ static void ftrace_shutdown(struct ftrace_ops *ops, int command)
        }
 
        if (!command || !ftrace_enabled)
-               return;
+               return 0;
 
        ftrace_run_update_code(command);
+       return 0;
 }
 
 static void ftrace_startup_sysctl(void)
@@ -3060,16 +3065,13 @@ static void __enable_ftrace_function_probe(void)
        if (i == FTRACE_FUNC_HASHSIZE)
                return;
 
-       ret = __register_ftrace_function(&trace_probe_ops);
-       if (!ret)
-               ret = ftrace_startup(&trace_probe_ops, 0);
+       ret = ftrace_startup(&trace_probe_ops, 0);
 
        ftrace_probe_registered = 1;
 }
 
 static void __disable_ftrace_function_probe(void)
 {
-       int ret;
        int i;
 
        if (!ftrace_probe_registered)
@@ -3082,9 +3084,7 @@ static void __disable_ftrace_function_probe(void)
        }
 
        /* no more funcs left */
-       ret = __unregister_ftrace_function(&trace_probe_ops);
-       if (!ret)
-               ftrace_shutdown(&trace_probe_ops, 0);
+       ftrace_shutdown(&trace_probe_ops, 0);
 
        ftrace_probe_registered = 0;
 }
@@ -4366,12 +4366,15 @@ core_initcall(ftrace_nodyn_init);
 static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; }
 static inline void ftrace_startup_enable(int command) { }
 /* Keep as macros so we do not need to define the commands */
-# define ftrace_startup(ops, command)                  \
-       ({                                              \
-               (ops)->flags |= FTRACE_OPS_FL_ENABLED;  \
-               0;                                      \
+# define ftrace_startup(ops, command)                                  \
+       ({                                                              \
+               int ___ret = __register_ftrace_function(ops);           \
+               if (!___ret)                                            \
+                       (ops)->flags |= FTRACE_OPS_FL_ENABLED;          \
+               ___ret;                                                 \
        })
-# define ftrace_shutdown(ops, command) do { } while (0)
+# define ftrace_shutdown(ops, command) __unregister_ftrace_function(ops)
+
 # define ftrace_startup_sysctl()       do { } while (0)
 # define ftrace_shutdown_sysctl()      do { } while (0)
 
@@ -4780,9 +4783,7 @@ int register_ftrace_function(struct ftrace_ops *ops)
 
        mutex_lock(&ftrace_lock);
 
-       ret = __register_ftrace_function(ops);
-       if (!ret)
-               ret = ftrace_startup(ops, 0);
+       ret = ftrace_startup(ops, 0);
 
        mutex_unlock(&ftrace_lock);
 
@@ -4801,9 +4802,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
        int ret;
 
        mutex_lock(&ftrace_lock);
-       ret = __unregister_ftrace_function(ops);
-       if (!ret)
-               ftrace_shutdown(ops, 0);
+       ret = ftrace_shutdown(ops, 0);
        mutex_unlock(&ftrace_lock);
 
        return ret;
@@ -4997,6 +4996,13 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state,
        return NOTIFY_DONE;
 }
 
+/* Just a place holder for function graph */
+static struct ftrace_ops fgraph_ops __read_mostly = {
+       .func           = ftrace_stub,
+       .flags          = FTRACE_OPS_FL_STUB | FTRACE_OPS_FL_GLOBAL |
+                               FTRACE_OPS_FL_RECURSION_SAFE,
+};
+
 int register_ftrace_graph(trace_func_graph_ret_t retfunc,
                        trace_func_graph_ent_t entryfunc)
 {
@@ -5023,7 +5029,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
        ftrace_graph_return = retfunc;
        ftrace_graph_entry = entryfunc;
 
-       ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
+       ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET);
 
 out:
        mutex_unlock(&ftrace_lock);
@@ -5040,7 +5046,7 @@ void unregister_ftrace_graph(void)
        ftrace_graph_active--;
        ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
        ftrace_graph_entry = ftrace_graph_entry_stub;
-       ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
+       ftrace_shutdown(&fgraph_ops, FTRACE_STOP_FUNC_RET);
        unregister_pm_notifier(&ftrace_suspend_notifier);
        unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
 
index 78e27e3b52ac2ee0b9e86f544b77a45e12865d95..e854f420e033eb65a2bca233bb8df2e42778faf7 100644 (file)
@@ -24,6 +24,12 @@ static int   total_ref_count;
 static int perf_trace_event_perm(struct ftrace_event_call *tp_event,
                                 struct perf_event *p_event)
 {
+       if (tp_event->perf_perm) {
+               int ret = tp_event->perf_perm(tp_event, p_event);
+               if (ret)
+                       return ret;
+       }
+
        /* The ftrace function trace is allowed only for root. */
        if (ftrace_event_is_function(tp_event) &&
            perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
@@ -173,7 +179,7 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,
 int perf_trace_init(struct perf_event *p_event)
 {
        struct ftrace_event_call *tp_event;
-       int event_id = p_event->attr.config;
+       u64 event_id = p_event->attr.config;
        int ret = -EINVAL;
 
        mutex_lock(&event_mutex);
index f919a2e21bf30e68ad6a99ee627d63f5bb6cb44c..a11800ae96de5d1f098153aaacdb715ba5098493 100644 (file)
@@ -2314,6 +2314,9 @@ int event_trace_del_tracer(struct trace_array *tr)
        /* Disable any running events */
        __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0);
 
+       /* Access to events are within rcu_read_lock_sched() */
+       synchronize_sched();
+
        down_write(&trace_event_sem);
        __trace_remove_event_dirs(tr);
        debugfs_remove_recursive(tr->event_dir);
index e4b6d11bdf78f35a2a6d8e831cd3ec21d97d9c00..ea90eb5f6f1730dce05ca992c19ebb533d7085db 100644 (file)
@@ -431,11 +431,6 @@ static void unreg_event_syscall_enter(struct ftrace_event_file *file,
        if (!tr->sys_refcount_enter)
                unregister_trace_sys_enter(ftrace_syscall_enter, tr);
        mutex_unlock(&syscall_trace_lock);
-       /*
-        * Callers expect the event to be completely disabled on
-        * return, so wait for current handlers to finish.
-        */
-       synchronize_sched();
 }
 
 static int reg_event_syscall_exit(struct ftrace_event_file *file,
@@ -474,11 +469,6 @@ static void unreg_event_syscall_exit(struct ftrace_event_file *file,
        if (!tr->sys_refcount_exit)
                unregister_trace_sys_exit(ftrace_syscall_exit, tr);
        mutex_unlock(&syscall_trace_lock);
-       /*
-        * Callers expect the event to be completely disabled on
-        * return, so wait for current handlers to finish.
-        */
-       synchronize_sched();
 }
 
 static int __init init_syscall_trace(struct ftrace_event_call *call)
index a3a0dbfda32957616f143ae2722541a5846c0a62..c006131beb77c5151f92cacb9e11e6a3b1defe1b 100644 (file)
@@ -51,9 +51,9 @@ struct user_namespace init_user_ns = {
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
-#ifdef CONFIG_KEYS_KERBEROS_CACHE
-       .krb_cache_register_sem =
-       __RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem),
+#ifdef CONFIG_PERSISTENT_KEYRINGS
+       .persistent_keyring_register_sem =
+       __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
 #endif
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
index 987293d03ebcf0e6bf1c6b81e8a4e68c7965e903..b010eac595d20eece261310cc4acb629ad70b92b 100644 (file)
@@ -305,6 +305,9 @@ static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER);
 /* I: attributes used when instantiating standard unbound pools on demand */
 static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
 
+/* I: attributes used when instantiating ordered pools on demand */
+static struct workqueue_attrs *ordered_wq_attrs[NR_STD_WORKER_POOLS];
+
 struct workqueue_struct *system_wq __read_mostly;
 EXPORT_SYMBOL(system_wq);
 struct workqueue_struct *system_highpri_wq __read_mostly;
@@ -518,14 +521,21 @@ static inline void debug_work_activate(struct work_struct *work) { }
 static inline void debug_work_deactivate(struct work_struct *work) { }
 #endif
 
-/* allocate ID and assign it to @pool */
+/**
+ * worker_pool_assign_id - allocate ID and assing it to @pool
+ * @pool: the pool pointer of interest
+ *
+ * Returns 0 if ID in [0, WORK_OFFQ_POOL_NONE) is allocated and assigned
+ * successfully, -errno on failure.
+ */
 static int worker_pool_assign_id(struct worker_pool *pool)
 {
        int ret;
 
        lockdep_assert_held(&wq_pool_mutex);
 
-       ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL);
+       ret = idr_alloc(&worker_pool_idr, pool, 0, WORK_OFFQ_POOL_NONE,
+                       GFP_KERNEL);
        if (ret >= 0) {
                pool->id = ret;
                return 0;
@@ -1320,7 +1330,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
 
        debug_work_activate(work);
 
-       /* if dying, only works from the same workqueue are allowed */
+       /* if draining, only works from the same workqueue are allowed */
        if (unlikely(wq->flags & __WQ_DRAINING) &&
            WARN_ON_ONCE(!is_chained_work(wq)))
                return;
@@ -1736,16 +1746,17 @@ static struct worker *create_worker(struct worker_pool *pool)
        if (IS_ERR(worker->task))
                goto fail;
 
+       set_user_nice(worker->task, pool->attrs->nice);
+
+       /* prevent userland from meddling with cpumask of workqueue workers */
+       worker->task->flags |= PF_NO_SETAFFINITY;
+
        /*
         * set_cpus_allowed_ptr() will fail if the cpumask doesn't have any
         * online CPUs.  It'll be re-applied when any of the CPUs come up.
         */
-       set_user_nice(worker->task, pool->attrs->nice);
        set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
 
-       /* prevent userland from meddling with cpumask of workqueue workers */
-       worker->task->flags |= PF_NO_SETAFFINITY;
-
        /*
         * The caller is responsible for ensuring %POOL_DISASSOCIATED
         * remains stable across this function.  See the comments above the
@@ -2840,19 +2851,6 @@ already_gone:
        return false;
 }
 
-static bool __flush_work(struct work_struct *work)
-{
-       struct wq_barrier barr;
-
-       if (start_flush_work(work, &barr)) {
-               wait_for_completion(&barr.done);
-               destroy_work_on_stack(&barr.work);
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * flush_work - wait for a work to finish executing the last queueing instance
  * @work: the work to flush
@@ -2866,10 +2864,18 @@ static bool __flush_work(struct work_struct *work)
  */
 bool flush_work(struct work_struct *work)
 {
+       struct wq_barrier barr;
+
        lock_map_acquire(&work->lockdep_map);
        lock_map_release(&work->lockdep_map);
 
-       return __flush_work(work);
+       if (start_flush_work(work, &barr)) {
+               wait_for_completion(&barr.done);
+               destroy_work_on_stack(&barr.work);
+               return true;
+       } else {
+               return false;
+       }
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
@@ -4106,7 +4112,7 @@ out_unlock:
 static int alloc_and_link_pwqs(struct workqueue_struct *wq)
 {
        bool highpri = wq->flags & WQ_HIGHPRI;
-       int cpu;
+       int cpu, ret;
 
        if (!(wq->flags & WQ_UNBOUND)) {
                wq->cpu_pwqs = alloc_percpu(struct pool_workqueue);
@@ -4126,6 +4132,13 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
                        mutex_unlock(&wq->mutex);
                }
                return 0;
+       } else if (wq->flags & __WQ_ORDERED) {
+               ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
+               /* there should only be single pwq for ordering guarantee */
+               WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
+                             wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
+                    "ordering guarantee broken for workqueue %s\n", wq->name);
+               return ret;
        } else {
                return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
        }
@@ -4814,14 +4827,7 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 
        INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
        schedule_work_on(cpu, &wfc.work);
-
-       /*
-        * The work item is on-stack and can't lead to deadlock through
-        * flushing.  Use __flush_work() to avoid spurious lockdep warnings
-        * when work_on_cpu()s are nested.
-        */
-       __flush_work(&wfc.work);
-
+       flush_work(&wfc.work);
        return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);
@@ -5009,10 +5015,6 @@ static int __init init_workqueues(void)
        int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };
        int i, cpu;
 
-       /* make sure we have enough bits for OFFQ pool ID */
-       BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT)) <
-                    WORK_CPU_END * NR_STD_WORKER_POOLS);
-
        WARN_ON(__alignof__(struct pool_workqueue) < __alignof__(long long));
 
        pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC);
@@ -5051,13 +5053,23 @@ static int __init init_workqueues(void)
                }
        }
 
-       /* create default unbound wq attrs */
+       /* create default unbound and ordered wq attrs */
        for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
                struct workqueue_attrs *attrs;
 
                BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
                attrs->nice = std_nice[i];
                unbound_std_wq_attrs[i] = attrs;
+
+               /*
+                * An ordered wq should have only one pwq as ordering is
+                * guaranteed by max_active which is enforced by pwqs.
+                * Turn off NUMA so that dfl_pwq is used for all nodes.
+                */
+               BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
+               attrs->nice = std_nice[i];
+               attrs->no_numa = true;
+               ordered_wq_attrs[i] = attrs;
        }
 
        system_wq = alloc_workqueue("events", 0, 0);
index 17edeaf1918019b43c53dffd6e620298dcb710a2..1b6a44f1ec3e3b10f3b02d19f8ab0ce59453f6d5 100644 (file)
@@ -759,8 +759,8 @@ all_leaves_cluster_together:
        pr_devel("all leaves cluster together\n");
        diff = INT_MAX;
        for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-               int x = ops->diff_objects(assoc_array_ptr_to_leaf(edit->leaf),
-                                         assoc_array_ptr_to_leaf(node->slots[i]));
+               int x = ops->diff_objects(assoc_array_ptr_to_leaf(node->slots[i]),
+                                         index_key);
                if (x < diff) {
                        BUG_ON(x < 0);
                        diff = x;
index d2b123f8456b22479681d4512fbb8c1e445a0158..f07a40d33871e2b9414ea40b53ee154108932d4e 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/export.h>
 #include <linux/lockref.h>
+#include <linux/mutex.h>
 
 #if USE_CMPXCHG_LOCKREF
 
 # define cmpxchg64_relaxed cmpxchg64
 #endif
 
-/*
- * Allow architectures to override the default cpu_relax() within CMPXCHG_LOOP.
- * This is useful for architectures with an expensive cpu_relax().
- */
-#ifndef arch_mutex_cpu_relax
-# define arch_mutex_cpu_relax() cpu_relax()
-#endif
-
 /*
  * Note that the "cmpxchg()" reloads the "old" value for the
  * failure case.
index eb69f352401de910552fb7f28959b38f4746a878..723bbe04a0b0511976d3778a4df94cb2974eb9c8 100644 (file)
@@ -543,7 +543,7 @@ config ZSWAP
 
 config MEM_SOFT_DIRTY
        bool "Track memory changes"
-       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY
+       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY && PROC_FS
        select PROC_PAGE_MONITOR
        help
          This option enables memory changes tracking by introducing a
index 805165bcd3dd0ab8f27bbff2c9105927ed803c15..f58bcd016f432dd094d6f6378aa53f9799d30811 100644 (file)
@@ -134,6 +134,10 @@ static void update_pageblock_skip(struct compact_control *cc,
                        bool migrate_scanner)
 {
        struct zone *zone = cc->zone;
+
+       if (cc->ignore_skip_hint)
+               return;
+
        if (!page)
                return;
 
index bccd5a628ea6765478d2fa45dc01390a83ee8a5b..7de1bf85f6833422e16161445b71e328fad2e1f6 100644 (file)
@@ -882,6 +882,10 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                ret = 0;
                goto out_unlock;
        }
+
+       /* mmap_sem prevents this happening but warn if that changes */
+       WARN_ON(pmd_trans_migrating(pmd));
+
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1243,6 +1247,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
                return ERR_PTR(-EFAULT);
 
+       /* Full NUMA hinting faults to serialise migration in fault paths */
+       if ((flags & FOLL_NUMA) && pmd_numa(*pmd))
+               goto out;
+
        page = pmd_page(*pmd);
        VM_BUG_ON(!PageHead(page));
        if (flags & FOLL_TOUCH) {
@@ -1295,6 +1303,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(!pmd_same(pmd, *pmdp)))
                goto out_unlock;
 
+       /*
+        * If there are potential migrations, wait for completion and retry
+        * without disrupting NUMA hinting information. Do not relock and
+        * check_same as the page may no longer be mapped.
+        */
+       if (unlikely(pmd_trans_migrating(*pmdp))) {
+               spin_unlock(ptl);
+               wait_migrate_huge_page(vma->anon_vma, pmdp);
+               goto out;
+       }
+
        page = pmd_page(pmd);
        BUG_ON(is_huge_zero_page(page));
        page_nid = page_to_nid(page);
@@ -1323,23 +1342,22 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                /* If the page was locked, there are no parallel migrations */
                if (page_locked)
                        goto clear_pmdnuma;
+       }
 
-               /*
-                * Otherwise wait for potential migrations and retry. We do
-                * relock and check_same as the page may no longer be mapped.
-                * As the fault is being retried, do not account for it.
-                */
+       /* Migration could have started since the pmd_trans_migrating check */
+       if (!page_locked) {
                spin_unlock(ptl);
                wait_on_page_locked(page);
                page_nid = -1;
                goto out;
        }
 
-       /* Page is misplaced, serialise migrations and parallel THP splits */
+       /*
+        * Page is misplaced. Page lock serialises migrations. Acquire anon_vma
+        * to serialises splits
+        */
        get_page(page);
        spin_unlock(ptl);
-       if (!page_locked)
-               lock_page(page);
        anon_vma = page_lock_anon_vma_read(page);
 
        /* Confirm the PMD did not change while page_table_lock was released */
@@ -1351,6 +1369,13 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out_unlock;
        }
 
+       /* Bail if we fail to protect against THP splits for any reason */
+       if (unlikely(!anon_vma)) {
+               put_page(page);
+               page_nid = -1;
+               goto clear_pmdnuma;
+       }
+
        /*
         * Migrate the THP to the requested node, returns with page unlocked
         * and pmd_numa cleared.
@@ -1481,8 +1506,18 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
                pmd = pmdp_get_and_clear(mm, old_addr, old_pmd);
                VM_BUG_ON(!pmd_none(*new_pmd));
                set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
-               if (new_ptl != old_ptl)
+               if (new_ptl != old_ptl) {
+                       pgtable_t pgtable;
+
+                       /*
+                        * Move preallocated PTE page table if new_pmd is on
+                        * different PMD page table.
+                        */
+                       pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
+                       pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
+
                        spin_unlock(new_ptl);
+               }
                spin_unlock(old_ptl);
        }
 out:
@@ -1507,6 +1542,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                ret = 1;
                if (!prot_numa) {
                        entry = pmdp_get_and_clear(mm, addr, pmd);
+                       if (pmd_numa(entry))
+                               entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
                        BUG_ON(pmd_write(entry));
@@ -1521,7 +1558,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                         */
                        if (!is_huge_zero_page(page) &&
                            !pmd_numa(*pmd)) {
-                               entry = pmdp_get_and_clear(mm, addr, pmd);
+                               entry = *pmd;
                                entry = pmd_mknuma(entry);
                                ret = HPAGE_PMD_NR;
                        }
index f1a0ae6e11b86b3020c90d7241ba12d47d2bbaa8..bf5e8945714944f896e2dc79b33b75a491da4794 100644 (file)
@@ -2694,7 +2694,10 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
                goto bypass;
 
        if (unlikely(task_in_memcg_oom(current)))
-               goto bypass;
+               goto nomem;
+
+       if (gfp_mask & __GFP_NOFAIL)
+               oom = false;
 
        /*
         * We always charge the cgroup the mm_struct belongs to.
@@ -6352,6 +6355,42 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       /*
+        * XXX: css_offline() would be where we should reparent all
+        * memory to prepare the cgroup for destruction.  However,
+        * memcg does not do css_tryget() and res_counter charging
+        * under the same RCU lock region, which means that charging
+        * could race with offlining.  Offlining only happens to
+        * cgroups with no tasks in them but charges can show up
+        * without any tasks from the swapin path when the target
+        * memcg is looked up from the swapout record and not from the
+        * current task as it usually is.  A race like this can leak
+        * charges and put pages with stale cgroup pointers into
+        * circulation:
+        *
+        * #0                        #1
+        *                           lookup_swap_cgroup_id()
+        *                           rcu_read_lock()
+        *                           mem_cgroup_lookup()
+        *                           css_tryget()
+        *                           rcu_read_unlock()
+        * disable css_tryget()
+        * call_rcu()
+        *   offline_css()
+        *     reparent_charges()
+        *                           res_counter_charge()
+        *                           css_put()
+        *                             css_free()
+        *                           pc->mem_cgroup = dead memcg
+        *                           add page to lru
+        *
+        * The bulk of the charges are still moved in offline_css() to
+        * avoid pinning a lot of pages in case a long-term reference
+        * like a swapout record is deferring the css_free() to long
+        * after offlining.  But this makes sure we catch any charges
+        * made after offlining:
+        */
+       mem_cgroup_reparent_charges(memcg);
 
        memcg_destroy_kmem(memcg);
        __mem_cgroup_free(memcg);
index b7c171602ba1ebb8697f0c523f1a62f51c3a2fa4..db08af92c6fce92d9e0d61ca5752aa003c52c3f2 100644 (file)
@@ -1505,10 +1505,16 @@ static int soft_offline_huge_page(struct page *page, int flags)
                if (ret > 0)
                        ret = -EIO;
        } else {
-               set_page_hwpoison_huge_page(hpage);
-               dequeue_hwpoisoned_huge_page(hpage);
-               atomic_long_add(1 << compound_order(hpage),
-                               &num_poisoned_pages);
+               /* overcommit hugetlb page will be freed to buddy */
+               if (PageHuge(page)) {
+                       set_page_hwpoison_huge_page(hpage);
+                       dequeue_hwpoisoned_huge_page(hpage);
+                       atomic_long_add(1 << compound_order(hpage),
+                                       &num_poisoned_pages);
+               } else {
+                       SetPageHWPoison(page);
+                       atomic_long_inc(&num_poisoned_pages);
+               }
        }
        return ret;
 }
index 5d9025f3b3e1cd65bd97655ee95d6cd2f390ce5b..6768ce9e57d29b6d8076b11c62c2097662f334d5 100644 (file)
@@ -4271,7 +4271,7 @@ void copy_user_huge_page(struct page *dst, struct page *src,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
 
-#if USE_SPLIT_PTE_PTLOCKS && BLOATED_SPINLOCKS
+#if USE_SPLIT_PTE_PTLOCKS && ALLOC_SPLIT_PTLOCKS
 bool ptlock_alloc(struct page *page)
 {
        spinlock_t *ptl;
index eca4a3129129751208b41cfe808e9e31e5dc7b5f..0cd2c4d4e2703f88f56b957b6f442a531fbd2e1f 100644 (file)
@@ -1197,14 +1197,16 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
                        break;
                vma = vma->vm_next;
        }
+
+       if (PageHuge(page)) {
+               if (vma)
+                       return alloc_huge_page_noerr(vma, address, 1);
+               else
+                       return NULL;
+       }
        /*
-        * queue_pages_range() confirms that @page belongs to some vma,
-        * so vma shouldn't be NULL.
+        * if !vma, alloc_page_vma() will use task or system default policy
         */
-       BUG_ON(!vma);
-
-       if (PageHuge(page))
-               return alloc_huge_page_noerr(vma, address, 1);
        return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
 }
 #else
@@ -1318,7 +1320,7 @@ static long do_mbind(unsigned long start, unsigned long len,
                if (nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
        } else
-               putback_lru_pages(&pagelist);
+               putback_movable_pages(&pagelist);
 
        up_write(&mm->mmap_sem);
  mpol_out:
index bb940045fe8595842ed58f2e32f87b83d40485e1..9194375b230729fead356e8dd3c8f6bb951415ab 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/hugetlb_cgroup.h>
 #include <linux/gfp.h>
 #include <linux/balloon_compaction.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/tlbflush.h>
 
@@ -316,14 +317,15 @@ static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
  */
 int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode)
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count)
 {
-       int expected_count = 0;
+       int expected_count = 1 + extra_count;
        void **pslot;
 
        if (!mapping) {
                /* Anonymous page without mapping */
-               if (page_count(page) != 1)
+               if (page_count(page) != expected_count)
                        return -EAGAIN;
                return MIGRATEPAGE_SUCCESS;
        }
@@ -333,7 +335,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
        pslot = radix_tree_lookup_slot(&mapping->page_tree,
                                        page_index(page));
 
-       expected_count = 2 + page_has_private(page);
+       expected_count += 1 + page_has_private(page);
        if (page_count(page) != expected_count ||
                radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {
                spin_unlock_irq(&mapping->tree_lock);
@@ -583,7 +585,7 @@ int migrate_page(struct address_space *mapping,
 
        BUG_ON(PageWriteback(page));    /* Writeback must be complete */
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -610,7 +612,7 @@ int buffer_migrate_page(struct address_space *mapping,
 
        head = page_buffers(page);
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -1654,6 +1656,18 @@ int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
        return 1;
 }
 
+bool pmd_trans_migrating(pmd_t pmd)
+{
+       struct page *page = pmd_page(pmd);
+       return PageLocked(page);
+}
+
+void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+       struct page *page = pmd_page(*pmd);
+       wait_on_page_locked(page);
+}
+
 /*
  * Attempt to migrate a misplaced page to the specified destination
  * node. Caller is expected to have an elevated reference count on
@@ -1716,12 +1730,14 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                                struct page *page, int node)
 {
        spinlock_t *ptl;
-       unsigned long haddr = address & HPAGE_PMD_MASK;
        pg_data_t *pgdat = NODE_DATA(node);
        int isolated = 0;
        struct page *new_page = NULL;
        struct mem_cgroup *memcg = NULL;
        int page_lru = page_is_file_cache(page);
+       unsigned long mmun_start = address & HPAGE_PMD_MASK;
+       unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
+       pmd_t orig_entry;
 
        /*
         * Rate-limit the amount of data that is being migrated to a node.
@@ -1744,6 +1760,9 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                goto out_fail;
        }
 
+       if (mm_tlb_flush_pending(mm))
+               flush_tlb_range(vma, mmun_start, mmun_end);
+
        /* Prepare a page as a migration target */
        __set_page_locked(new_page);
        SetPageSwapBacked(new_page);
@@ -1755,9 +1774,12 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
        WARN_ON(PageLRU(new_page));
 
        /* Recheck the target PMD */
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        ptl = pmd_lock(mm, pmd);
-       if (unlikely(!pmd_same(*pmd, entry))) {
+       if (unlikely(!pmd_same(*pmd, entry) || page_count(page) != 2)) {
+fail_putback:
                spin_unlock(ptl);
+               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
                /* Reverse changes made by migrate_page_copy() */
                if (TestClearPageActive(new_page))
@@ -1774,7 +1796,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                putback_lru_page(page);
                mod_zone_page_state(page_zone(page),
                         NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR);
-               goto out_fail;
+
+               goto out_unlock;
        }
 
        /*
@@ -1786,16 +1809,35 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_prepare_migration(page, new_page, &memcg);
 
+       orig_entry = *pmd;
        entry = mk_pmd(new_page, vma->vm_page_prot);
-       entry = pmd_mknonnuma(entry);
-       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
        entry = pmd_mkhuge(entry);
+       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 
-       pmdp_clear_flush(vma, haddr, pmd);
-       set_pmd_at(mm, haddr, pmd, entry);
-       page_add_new_anon_rmap(new_page, vma, haddr);
+       /*
+        * Clear the old entry under pagetable lock and establish the new PTE.
+        * Any parallel GUP will either observe the old page blocking on the
+        * page lock, block on the page table lock or observe the new page.
+        * The SetPageUptodate on the new page and page_add_new_anon_rmap
+        * guarantee the copy is visible before the pagetable update.
+        */
+       flush_cache_range(vma, mmun_start, mmun_end);
+       page_add_new_anon_rmap(new_page, vma, mmun_start);
+       pmdp_clear_flush(vma, mmun_start, pmd);
+       set_pmd_at(mm, mmun_start, pmd, entry);
+       flush_tlb_range(vma, mmun_start, mmun_end);
        update_mmu_cache_pmd(vma, address, &entry);
+
+       if (page_count(page) != 2) {
+               set_pmd_at(mm, mmun_start, pmd, orig_entry);
+               flush_tlb_range(vma, mmun_start, mmun_end);
+               update_mmu_cache_pmd(vma, address, &entry);
+               page_remove_rmap(new_page);
+               goto fail_putback;
+       }
+
        page_remove_rmap(page);
+
        /*
         * Finish the charge transaction under the page table lock to
         * prevent split_huge_page() from dividing up the charge
@@ -1803,6 +1845,7 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_end_migration(memcg, page, new_page, true);
        spin_unlock(ptl);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
        unlock_page(new_page);
        unlock_page(page);
@@ -1820,10 +1863,15 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
 out_fail:
        count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
 out_dropref:
-       entry = pmd_mknonnuma(entry);
-       set_pmd_at(mm, haddr, pmd, entry);
-       update_mmu_cache_pmd(vma, address, &entry);
+       ptl = pmd_lock(mm, pmd);
+       if (pmd_same(*pmd, entry)) {
+               entry = pmd_mknonnuma(entry);
+               set_pmd_at(mm, mmun_start, pmd, entry);
+               update_mmu_cache_pmd(vma, address, &entry);
+       }
+       spin_unlock(ptl);
 
+out_unlock:
        unlock_page(page);
        put_page(page);
        return 0;
index 26667971c824b08ca3dae7188a965e1e4efe0b79..bb53a6591aea1373d6bc74d5bb3e847650af8d24 100644 (file)
@@ -52,17 +52,21 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        pte_t ptent;
                        bool updated = false;
 
-                       ptent = ptep_modify_prot_start(mm, addr, pte);
                        if (!prot_numa) {
+                               ptent = ptep_modify_prot_start(mm, addr, pte);
+                               if (pte_numa(ptent))
+                                       ptent = pte_mknonnuma(ptent);
                                ptent = pte_modify(ptent, newprot);
                                updated = true;
                        } else {
                                struct page *page;
 
+                               ptent = *pte;
                                page = vm_normal_page(vma, addr, oldpte);
                                if (page) {
                                        if (!pte_numa(oldpte)) {
                                                ptent = pte_mknuma(ptent);
+                                               set_pte_at(mm, addr, pte, ptent);
                                                updated = true;
                                        }
                                }
@@ -79,7 +83,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
                        if (updated)
                                pages++;
-                       ptep_modify_prot_commit(mm, addr, pte, ptent);
+
+                       /* Only !prot_numa always clears the pte */
+                       if (!prot_numa)
+                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
@@ -181,6 +188,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        BUG_ON(addr >= end);
        pgd = pgd_offset(mm, addr);
        flush_cache_range(vma, addr, end);
+       set_tlb_flush_pending(mm);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
@@ -192,6 +200,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        /* Only flush the TLB if we actually modified any entries: */
        if (pages)
                flush_tlb_range(vma, start, end);
+       clear_tlb_flush_pending(mm);
 
        return pages;
 }
index 580a5f075ed0ab6e3047351a8271b1f053e35774..5248fe070aa4e9f94b4be087aa8957e16cf16c1f 100644 (file)
@@ -1816,7 +1816,7 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
 
 static bool zone_local(struct zone *local_zone, struct zone *zone)
 {
-       return node_distance(local_zone->node, zone->node) == LOCAL_DISTANCE;
+       return local_zone->node == zone->node;
 }
 
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
@@ -1913,18 +1913,17 @@ zonelist_scan:
                 * page was allocated in should have no effect on the
                 * time the page has in memory before being reclaimed.
                 *
-                * When zone_reclaim_mode is enabled, try to stay in
-                * local zones in the fastpath.  If that fails, the
-                * slowpath is entered, which will do another pass
-                * starting with the local zones, but ultimately fall
-                * back to remote zones that do not partake in the
-                * fairness round-robin cycle of this zonelist.
+                * Try to stay in local zones in the fastpath.  If
+                * that fails, the slowpath is entered, which will do
+                * another pass starting with the local zones, but
+                * ultimately fall back to remote zones that do not
+                * partake in the fairness round-robin cycle of this
+                * zonelist.
                 */
                if (alloc_flags & ALLOC_WMARK_LOW) {
                        if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0)
                                continue;
-                       if (zone_reclaim_mode &&
-                           !zone_local(preferred_zone, zone))
+                       if (!zone_local(preferred_zone, zone))
                                continue;
                }
                /*
@@ -2390,7 +2389,7 @@ static void prepare_slowpath(gfp_t gfp_mask, unsigned int order,
                 * thrash fairness information for zones that are not
                 * actually part of this zonelist's round-robin cycle.
                 */
-               if (zone_reclaim_mode && !zone_local(preferred_zone, zone))
+               if (!zone_local(preferred_zone, zone))
                        continue;
                mod_zone_page_state(zone, NR_ALLOC_BATCH,
                                    high_wmark_pages(zone) -
index cbb38545d9d6ab8d96ebcdb001ed9e19db772f59..a8b9199259342df9cafb84be53010eb2206ebece 100644 (file)
@@ -110,9 +110,10 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
 pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
                       pte_t *ptep)
 {
+       struct mm_struct *mm = (vma)->vm_mm;
        pte_t pte;
-       pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
-       if (pte_accessible(pte))
+       pte = ptep_get_and_clear(mm, address, ptep);
+       if (pte_accessible(mm, pte))
                flush_tlb_page(vma, address);
        return pte;
 }
@@ -191,6 +192,9 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
+       pmd_t entry = *pmdp;
+       if (pmd_numa(entry))
+               entry = pmd_mknonnuma(entry);
        set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(*pmdp));
        flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
 }
index 55c8b8dc9ffb0c349eb63ad20a8d7bbcc2e9b25d..068522d8502a58e9465a963e68c37ce4ccf635d7 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -600,7 +600,11 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
        spinlock_t *ptl;
 
        if (unlikely(PageHuge(page))) {
+               /* when pud is not present, pte will be NULL */
                pte = huge_pte_offset(mm, address);
+               if (!pte)
+                       return NULL;
+
                ptl = huge_pte_lockptr(page_hstate(page), mm, pte);
                goto check;
        }
index 8297623fcaedec21b37b5080d376967e673afe92..902a14842b74a6efe5a0de23f965e8a2a9dad820 100644 (file)
@@ -2918,13 +2918,8 @@ static struct dentry_operations anon_ops = {
        .d_dname = simple_dname
 };
 
-/**
- * shmem_file_setup - get an unlinked file living in tmpfs
- * @name: name for dentry (to be seen in /proc/<pid>/maps
- * @size: size to be set for the file
- * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
- */
-struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+static struct file *__shmem_file_setup(const char *name, loff_t size,
+                                      unsigned long flags, unsigned int i_flags)
 {
        struct file *res;
        struct inode *inode;
@@ -2957,6 +2952,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
        if (!inode)
                goto put_dentry;
 
+       inode->i_flags |= i_flags;
        d_instantiate(path.dentry, inode);
        inode->i_size = size;
        clear_nlink(inode);     /* It is unlinked */
@@ -2977,6 +2973,32 @@ put_memory:
        shmem_unacct_size(flags, size);
        return res;
 }
+
+/**
+ * shmem_kernel_file_setup - get an unlinked file living in tmpfs which must be
+ *     kernel internal.  There will be NO LSM permission checks against the
+ *     underlying inode.  So users of this interface must do LSM checks at a
+ *     higher layer.  The one user is the big_key implementation.  LSM checks
+ *     are provided at the key level rather than the inode level.
+ * @name: name for dentry (to be seen in /proc/<pid>/maps
+ * @size: size to be set for the file
+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
+ */
+struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags)
+{
+       return __shmem_file_setup(name, size, flags, S_PRIVATE);
+}
+
+/**
+ * shmem_file_setup - get an unlinked file living in tmpfs
+ * @name: name for dentry (to be seen in /proc/<pid>/maps
+ * @size: size to be set for the file
+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
+ */
+struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+{
+       return __shmem_file_setup(name, size, flags, 0);
+}
 EXPORT_SYMBOL_GPL(shmem_file_setup);
 
 /**
index 229d820bdf0b06453cb43058020d54e33f210297..045d56eaeca2b777973bf1450d7b410a09d2d9f1 100644 (file)
@@ -426,6 +426,16 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
 int br_handle_frame_finish(struct sk_buff *skb);
 rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
 
+static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
+{
+       return rcu_dereference(dev->rx_handler) == br_handle_frame;
+}
+
+static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev)
+{
+       return br_rx_handler_check_rcu(dev) ? br_port_get_rcu(dev) : NULL;
+}
+
 /* br_ioctl.c */
 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd,
index 8660ea3be7054571defa59bcfbfc0cd0dd7ab99e..bdb459d21ad8e2d5191023c5b096de39b6a78c90 100644 (file)
@@ -153,7 +153,7 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
        if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0)
                goto err;
 
-       p = br_port_get_rcu(dev);
+       p = br_port_get_check_rcu(dev);
        if (!p)
                goto err;
 
index 618c6a8a911b65c9a406ba5d7d0e221cb124960e..dd32e34c1e2c9481aa2db3c37437ef0d85ba5277 100644 (file)
@@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
            __get_user(kmsg->msg_flags, &umsg->msg_flags))
                return -EFAULT;
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-               return -EINVAL;
+               kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        kmsg->msg_name = compat_ptr(tmp1);
        kmsg->msg_iov = compat_ptr(tmp2);
        kmsg->msg_control = compat_ptr(tmp3);
index 95897183226e18882bdbe16d8e9ba3a111ffae71..e70301eb7a4a0472d1ade5bd3d318fe453bd2b8b 100644 (file)
@@ -64,7 +64,6 @@ static struct genl_family net_drop_monitor_family = {
        .hdrsize        = 0,
        .name           = "NET_DM",
        .version        = 2,
-       .maxattr        = NET_DM_CMD_MAX,
 };
 
 static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data);
index ca15f32821fb8d536586354108488050b7cc6a0e..36b1443f9ae4b38cdd7b15f645f08032acac06d0 100644 (file)
@@ -1161,6 +1161,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                                                 neigh->parms->reachable_time :
                                                 0)));
                neigh->nud_state = new;
+               notify = 1;
        }
 
        if (lladdr != neigh->ha) {
index 261357a663001ccf98a92ba5f6d0f6ad141c7ce3..a797fff7f22213f3e5d1be6f97ab632a791079a4 100644 (file)
@@ -2527,6 +2527,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
                if (x) {
                        int ret;
                        __u8 *eth;
+                       struct iphdr *iph;
+
                        nhead = x->props.header_len - skb_headroom(skb);
                        if (nhead > 0) {
                                ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
@@ -2548,6 +2550,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
                        eth = (__u8 *) skb_push(skb, ETH_HLEN);
                        memcpy(eth, pkt_dev->hh, 12);
                        *(u16 *) &eth[12] = protocol;
+
+                       /* Update IPv4 header len as well as checksum value */
+                       iph = ip_hdr(skb);
+                       iph->tot_len = htons(skb->len - ETH_HLEN);
+                       ip_send_check(iph);
                }
        }
        return 1;
index 2718fed53d8cf5b81a06c82f8cdf8ed96632185a..06e72d3cdf60dbd96a3ad4829cfcc2baec0a80e8 100644 (file)
@@ -3584,6 +3584,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
        skb->skb_iif = 0;
+       skb->local_df = 0;
        skb_dst_drop(skb);
        skb->mark = 0;
        secpath_reset(skb);
index ab20ed9b0f31da64cb118cf645fa88f5787b5571..5393b4b719d71de2e3126664e3dcd5882c0c99d9 100644 (file)
@@ -882,7 +882,7 @@ set_rcvbuf:
 
        case SO_PEEK_OFF:
                if (sock->ops->set_peek_off)
-                       sock->ops->set_peek_off(sk, val);
+                       ret = sock->ops->set_peek_off(sk, val);
                else
                        ret = -EOPNOTSUPP;
                break;
index 4ac71ff7c2e47c4a3bcec19206845c8afd7ce9e8..2b90a786e475f78ab7084765bfeedc608632255a 100644 (file)
@@ -851,7 +851,6 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
index 003f5bb3acd25f4dc696255c56ac1985eae58a62..4bdab152187826f364f0acff43dca1db8d0dc938 100644 (file)
@@ -288,7 +288,8 @@ void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr,
 static bool seq_nr_after(u16 a, u16 b)
 {
        /* Remove inconsistency where
-        * seq_nr_after(a, b) == seq_nr_before(a, b) */
+        * seq_nr_after(a, b) == seq_nr_before(a, b)
+        */
        if ((int) b - a == 32768)
                return false;
 
index 5325af85eea670f5c865367fc991eaf9b907cd98..01a5261ac7a5520230fb0d2e147ffd3cf0a930ec 100644 (file)
@@ -23,6 +23,8 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
        [IFLA_HSR_SLAVE1]               = { .type = NLA_U32 },
        [IFLA_HSR_SLAVE2]               = { .type = NLA_U32 },
        [IFLA_HSR_MULTICAST_SPEC]       = { .type = NLA_U8 },
+       [IFLA_HSR_SUPERVISION_ADDR]     = { .type = NLA_BINARY, .len = ETH_ALEN },
+       [IFLA_HSR_SEQ_NR]               = { .type = NLA_U16 },
 };
 
 
@@ -59,6 +61,31 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
        return hsr_dev_finalize(dev, link, multicast_spec);
 }
 
+static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct hsr_priv *hsr_priv;
+
+       hsr_priv = netdev_priv(dev);
+
+       if (hsr_priv->slave[0])
+               if (nla_put_u32(skb, IFLA_HSR_SLAVE1, hsr_priv->slave[0]->ifindex))
+                       goto nla_put_failure;
+
+       if (hsr_priv->slave[1])
+               if (nla_put_u32(skb, IFLA_HSR_SLAVE2, hsr_priv->slave[1]->ifindex))
+                       goto nla_put_failure;
+
+       if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN,
+                   hsr_priv->sup_multicast_addr) ||
+           nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr_priv->sequence_nr))
+               goto nla_put_failure;
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
 static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .kind           = "hsr",
        .maxtype        = IFLA_HSR_MAX,
@@ -66,6 +93,7 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .priv_size      = sizeof(struct hsr_priv),
        .setup          = hsr_dev_setup,
        .newlink        = hsr_newlink,
+       .fill_info      = hsr_fill_info,
 };
 
 
index 523be38e37de82736a28bc9aa229f1911d2eaa31..f2e15738534d316ed0c50b8be2e1976fa03052c5 100644 (file)
@@ -104,7 +104,10 @@ errout:
 static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 {
        struct fib_result *result = (struct fib_result *) arg->result;
-       struct net_device *dev = result->fi->fib_dev;
+       struct net_device *dev = NULL;
+
+       if (result->fi)
+               dev = result->fi->fib_dev;
 
        /* do not accept result if the route does
         * not meet the required prefix length
index 3f858266fa7e33a0941a135ec8a36b36278fdfce..ddf32a6bc415c28f0b9639514dd86eb11b18ce85 100644 (file)
@@ -386,7 +386,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
 /*
  *     Handle MSG_ERRQUEUE
  */
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
        struct sock_exterr_skb *serr;
        struct sk_buff *skb, *skb2;
@@ -423,6 +423,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
                                                   serr->addr_offset);
                sin->sin_port = serr->port;
                memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+               *addr_len = sizeof(*sin);
        }
 
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
index f13bd91d9a56774f58dcf14de892b2bedd855cc5..a313c3fbeb469e0594b2f7bccd788d687184bc61 100644 (file)
@@ -423,6 +423,7 @@ static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)
 static struct xt_target synproxy_tg4_reg __read_mostly = {
        .name           = "SYNPROXY",
        .family         = NFPROTO_IPV4,
+       .hooks          = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
        .target         = synproxy_tg4,
        .targetsize     = sizeof(struct xt_synproxy_info),
        .checkentry     = synproxy_tg4_check,
index fff5ba1a33b76321f70d1365d072f7330d524ea9..4a5e94ac314a8cfdae20d8e393724ea2d01bd588 100644 (file)
@@ -72,7 +72,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
        const struct nft_reject *priv = nft_expr_priv(expr);
 
-       if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type))
+       if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
                goto nla_put_failure;
 
        switch (priv->type) {
index 876c6ca2d8f9e77a28f1e629aa6523df1ee8f42f..242e7f4ed6f44ff5765966388618152e2721fa87 100644 (file)
@@ -772,7 +772,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                err = PTR_ERR(rt);
                rt = NULL;
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                goto out;
        }
 
@@ -841,10 +841,11 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        if (flags & MSG_ERRQUEUE) {
                if (family == AF_INET) {
-                       return ip_recv_error(sk, msg, len);
+                       return ip_recv_error(sk, msg, len, addr_len);
 #if IS_ENABLED(CONFIG_IPV6)
                } else if (family == AF_INET6) {
-                       return pingv6_ops.ipv6_recv_error(sk, msg, len);
+                       return pingv6_ops.ipv6_recv_error(sk, msg, len,
+                                                         addr_len);
 #endif
                }
        }
index ce848461acbb07f6b758dc900225c7aff16ac690..46d6a1c923a8741776fa1de1cdd727b6cba72294 100644 (file)
 const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
 const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
 
-/*
- *     Add a protocol handler to the hash tables
- */
-
 int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        if (!prot->netns_ok) {
@@ -55,10 +51,6 @@ int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
 }
 EXPORT_SYMBOL(inet_add_offload);
 
-/*
- *     Remove a protocol from the hash tables.
- */
-
 int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        int ret;
index 5cb8ddb505ee8911461ec92a5c74feef0b441e00..23c3e5b5bb53f9e6f40ebbe8de4afd1683f9d7e5 100644 (file)
@@ -697,7 +697,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                goto out;
 
        if (flags & MSG_ERRQUEUE) {
-               err = ip_recv_error(sk, msg, len);
+               err = ip_recv_error(sk, msg, len, addr_len);
                goto out;
        }
 
index 59a6f8b90cd9d7c9ca51bbcd2cc424153d6571df..06721392475105fec441b2d97b3c72e6927b7e54 100644 (file)
@@ -177,7 +177,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
                return err;
        }
 
index 03e9154f7e687efef63c91878e33427672bc4036..f7e522c558ba2eb43165f85d46c2ba3a91ce42eb 100644 (file)
@@ -6,13 +6,6 @@
 #include <linux/memcontrol.h>
 #include <linux/module.h>
 
-static void memcg_tcp_enter_memory_pressure(struct sock *sk)
-{
-       if (sk->sk_cgrp->memory_pressure)
-               sk->sk_cgrp->memory_pressure = 1;
-}
-EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure);
-
 int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
 {
        /*
@@ -60,7 +53,6 @@ EXPORT_SYMBOL(tcp_destroy_cgroup);
 static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 {
        struct cg_proto *cg_proto;
-       u64 old_lim;
        int i;
        int ret;
 
@@ -71,7 +63,6 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
        if (val > RES_COUNTER_MAX)
                val = RES_COUNTER_MAX;
 
-       old_lim = res_counter_read_u64(&cg_proto->memory_allocated, RES_LIMIT);
        ret = res_counter_set_limit(&cg_proto->memory_allocated, val);
        if (ret)
                return ret;
index a2b68a108eae69170c8d915be778c9aeebf0f371..05606353c7e7cb026096acaf598a8685b84b85c9 100644 (file)
@@ -274,33 +274,32 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
 {
        const struct iphdr *iph = skb_gro_network_header(skb);
        __wsum wsum;
-       __sum16 sum;
+
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
+       wsum = skb->csum;
 
        switch (skb->ip_summed) {
+       case CHECKSUM_NONE:
+               wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
+                                   0);
+
+               /* fall through */
+
        case CHECKSUM_COMPLETE:
                if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
-                                 skb->csum)) {
+                                 wsum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-flush:
+
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
-                                         skb_gro_len(skb), IPPROTO_TCP, 0);
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 5944d7d668dd91da21e945eac748bbbbbb11d67a..f140048334ce21f38d86ac4a2fdf770df5330d78 100644 (file)
@@ -560,15 +560,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
                                                 __be16 sport, __be16 dport,
                                                 struct udp_table *udptable)
 {
-       struct sock *sk;
        const struct iphdr *iph = ip_hdr(skb);
 
-       if (unlikely(sk = skb_steal_sock(skb)))
-               return sk;
-       else
-               return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
-                                        iph->daddr, dport, inet_iif(skb),
-                                        udptable);
+       return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
+                                iph->daddr, dport, inet_iif(skb),
+                                udptable);
 }
 
 struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
@@ -999,7 +995,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        err = PTR_ERR(rt);
                        rt = NULL;
                        if (err == -ENETUNREACH)
-                               IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                               IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                        goto out;
                }
 
@@ -1098,6 +1094,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
        struct udp_sock *up = udp_sk(sk);
        int ret;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        if (!up->pending) {
                struct msghdr msg = {   .msg_flags = flags|MSG_MORE };
 
@@ -1236,7 +1235,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        bool slow;
 
        if (flags & MSG_ERRQUEUE)
-               return ip_recv_error(sk, msg, len);
+               return ip_recv_error(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1600,12 +1599,16 @@ static void flush_stack(struct sock **stack, unsigned int count,
                kfree_skb(skb1);
 }
 
-static void udp_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
+/* For TCP sockets, sk_rx_dst is protected by socket lock
+ * For UDP, we use xchg() to guard against concurrent changes.
+ */
+static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
 {
-       struct dst_entry *dst = skb_dst(skb);
+       struct dst_entry *old;
 
        dst_hold(dst);
-       sk->sk_rx_dst = dst;
+       old = xchg(&sk->sk_rx_dst, dst);
+       dst_release(old);
 }
 
 /*
@@ -1736,15 +1739,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (udp4_csum_init(skb, uh, proto))
                goto csum_error;
 
-       if (skb->sk) {
+       sk = skb_steal_sock(skb);
+       if (sk) {
+               struct dst_entry *dst = skb_dst(skb);
                int ret;
-               sk = skb->sk;
 
-               if (unlikely(sk->sk_rx_dst == NULL))
-                       udp_sk_rx_dst_set(sk, skb);
+               if (unlikely(sk->sk_rx_dst != dst))
+                       udp_sk_rx_dst_set(sk, dst);
 
                ret = udp_queue_rcv_skb(sk, skb);
-
+               sock_put(sk);
                /* a return value > 0 means to resubmit the input, but
                 * it wants the return to be -protocol, or 0
                 */
@@ -1910,17 +1914,20 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
 
 void udp_v4_early_demux(struct sk_buff *skb)
 {
-       const struct iphdr *iph = ip_hdr(skb);
-       const struct udphdr *uh = udp_hdr(skb);
+       struct net *net = dev_net(skb->dev);
+       const struct iphdr *iph;
+       const struct udphdr *uh;
        struct sock *sk;
        struct dst_entry *dst;
-       struct net *net = dev_net(skb->dev);
        int dif = skb->dev->ifindex;
 
        /* validate the packet */
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
                return;
 
+       iph = ip_hdr(skb);
+       uh = udp_hdr(skb);
+
        if (skb->pkt_type == PACKET_BROADCAST ||
            skb->pkt_type == PACKET_MULTICAST)
                sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
index 12c97d8aa6bbb31ff1519459b89b7b9fb33817f5..d5fa5b8c443ecbbcb0ed09a10db19b06730b7d8b 100644 (file)
@@ -2613,7 +2613,7 @@ static void init_loopback(struct net_device *dev)
                        if (sp_ifa->rt)
                                continue;
 
-                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
 
                        /* Failure cases are ignored */
                        if (!IS_ERR(sp_rt)) {
index a454b0ff57c7c67a91e2e5c887609e7a65e5a910..93b1aa34c4320304125b478bbdad73b8b691b572 100644 (file)
@@ -73,7 +73,6 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                }
        }
 
@@ -318,7 +317,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
 /*
  *     Handle MSG_ERRQUEUE
  */
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sock_exterr_skb *serr;
@@ -369,6 +368,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                                               &sin->sin6_addr);
                        sin->sin6_scope_id = 0;
                }
+               *addr_len = sizeof(*sin);
        }
 
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
@@ -377,6 +377,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
        if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
                sin->sin6_family = AF_INET6;
                sin->sin6_flowinfo = 0;
+               sin->sin6_port = 0;
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error);
 /*
  *     Handle IPV6_RECVPATHMTU
  */
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+                    int *addr_len)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sk_buff *skb;
@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
                sin->sin6_port = 0;
                sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
                sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
+               *addr_len = sizeof(*sin);
        }
 
        put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
index e27591635f92c45306a33cb9513628751e93dd16..3fd0a578329e523828fc56b40b6ffe217fd850dc 100644 (file)
@@ -122,7 +122,11 @@ out:
 static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 {
        struct rt6_info *rt = (struct rt6_info *) arg->result;
-       struct net_device *dev = rt->rt6i_idev->dev;
+       struct net_device *dev = NULL;
+
+       if (rt->rt6i_idev)
+               dev = rt->rt6i_idev->dev;
+
        /* do not accept result if the route does
         * not meet the required prefix length
         */
index 59df872e2f4d62f68b583ff40218d68c5d5189df..4acdb63495dbe2484de9d278b810401e6d26fc6a 100644 (file)
@@ -116,8 +116,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
        }
        rcu_read_unlock_bh();
 
-       IP6_INC_STATS_BH(dev_net(dst->dev),
-                        ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
+       IP6_INC_STATS(dev_net(dst->dev),
+                     ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
        kfree_skb(skb);
        return -EINVAL;
 }
index 3512177deb4d0e7d12c6d145781802074f490615..3008651713947c76dac697d466f1301d05bba025 100644 (file)
@@ -1277,6 +1277,9 @@ skip_linkparms:
                            ri->prefix_len == 0)
                                continue;
 #endif
+                       if (ri->prefix_len == 0 &&
+                           !in6_dev->cnf.accept_ra_defrtr)
+                               continue;
                        if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
                                continue;
                        rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
index f78f41aca8e90967a026a145f938746ce317cf10..a0d17270117c37793be3cb61c4d767cd57f70611 100644 (file)
@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
 static struct xt_target synproxy_tg6_reg __read_mostly = {
        .name           = "SYNPROXY",
        .family         = NFPROTO_IPV6,
+       .hooks          = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
        .target         = synproxy_tg6,
        .targetsize     = sizeof(struct xt_synproxy_info),
        .checkentry     = synproxy_tg6_check,
index 8815e31a87fed4ba51ebd78a6724df8a3a436b85..a83243c3d656f553b6ccec94451e26e28cd1e743 100644 (file)
@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = {
 
 
 /* Compatibility glue so we can support IPv6 when it's compiled as a module */
-static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                                int *addr_len)
 {
        return -EAFNOSUPPORT;
 }
index 22d1bd4670dab741b2417051b45370b4a75b42a3..e048cf1bb6a234bb1c0eac0987d8e093a733f2f1 100644 (file)
@@ -36,10 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol
 }
 EXPORT_SYMBOL(inet6_add_protocol);
 
-/*
- *     Remove a protocol from the hash tables.
- */
-
 int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
        int ret;
index e24ff1df0401288e4e810cf79ec3ea20d86a06c0..b6bb87e55805873ec3244db9586f58b14700835d 100644 (file)
@@ -466,10 +466,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
                return -EOPNOTSUPP;
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
@@ -792,7 +792,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
index 7faa9d5e15033ae45715d63a33c21150e74f8665..a0a48ac3403f3a9284786aa5b8f00dc03696e2e0 100644 (file)
@@ -84,6 +84,8 @@ static int             ip6_dst_gc(struct dst_ops *ops);
 
 static int             ip6_pkt_discard(struct sk_buff *skb);
 static int             ip6_pkt_discard_out(struct sk_buff *skb);
+static int             ip6_pkt_prohibit(struct sk_buff *skb);
+static int             ip6_pkt_prohibit_out(struct sk_buff *skb);
 static void            ip6_link_failure(struct sk_buff *skb);
 static void            ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
                                           struct sk_buff *skb, u32 mtu);
@@ -234,9 +236,6 @@ static const struct rt6_info ip6_null_entry_template = {
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
-static int ip6_pkt_prohibit(struct sk_buff *skb);
-static int ip6_pkt_prohibit_out(struct sk_buff *skb);
-
 static const struct rt6_info ip6_prohibit_entry_template = {
        .dst = {
                .__refcnt       = ATOMIC_INIT(1),
@@ -1565,21 +1564,24 @@ int ip6_route_add(struct fib6_config *cfg)
                                goto out;
                        }
                }
-               rt->dst.output = ip6_pkt_discard_out;
-               rt->dst.input = ip6_pkt_discard;
                rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
                switch (cfg->fc_type) {
                case RTN_BLACKHOLE:
                        rt->dst.error = -EINVAL;
+                       rt->dst.output = dst_discard;
+                       rt->dst.input = dst_discard;
                        break;
                case RTN_PROHIBIT:
                        rt->dst.error = -EACCES;
+                       rt->dst.output = ip6_pkt_prohibit_out;
+                       rt->dst.input = ip6_pkt_prohibit;
                        break;
                case RTN_THROW:
-                       rt->dst.error = -EAGAIN;
-                       break;
                default:
-                       rt->dst.error = -ENETUNREACH;
+                       rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
+                                       : -ENETUNREACH;
+                       rt->dst.output = ip6_pkt_discard_out;
+                       rt->dst.input = ip6_pkt_discard;
                        break;
                }
                goto install_route;
@@ -2144,8 +2146,6 @@ static int ip6_pkt_discard_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
 }
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-
 static int ip6_pkt_prohibit(struct sk_buff *skb)
 {
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
@@ -2157,8 +2157,6 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
 }
 
-#endif
-
 /*
  *     Allocate a dst for local (unicast / anycast) address.
  */
@@ -2168,12 +2166,10 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
                                    bool anycast)
 {
        struct net *net = dev_net(idev->dev);
-       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL);
-
-       if (!rt) {
-               net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n");
+       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
+                                           DST_NOCOUNT, NULL);
+       if (!rt)
                return ERR_PTR(-ENOMEM);
-       }
 
        in6_dev_hold(idev);
 
index 1b4a4a95367552c8cc22d19850b0779eee87cdc6..366fbba3359ab790e1b22917931acdbdb1daebf3 100644 (file)
@@ -478,14 +478,44 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
        dev_put(dev);
 }
 
+/* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
+ * if sufficient data bytes are available
+ */
+static int ipip6_err_gen_icmpv6_unreach(struct sk_buff *skb)
+{
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       struct rt6_info *rt;
+       struct sk_buff *skb2;
+
+       if (!pskb_may_pull(skb, iph->ihl * 4 + sizeof(struct ipv6hdr) + 8))
+               return 1;
+
+       skb2 = skb_clone(skb, GFP_ATOMIC);
+
+       if (!skb2)
+               return 1;
+
+       skb_dst_drop(skb2);
+       skb_pull(skb2, iph->ihl * 4);
+       skb_reset_network_header(skb2);
+
+       rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0);
+
+       if (rt && rt->dst.dev)
+               skb2->dev = rt->dst.dev;
+
+       icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
+
+       if (rt)
+               ip6_rt_put(rt);
+
+       kfree_skb(skb2);
+
+       return 0;
+}
 
 static int ipip6_err(struct sk_buff *skb, u32 info)
 {
-
-/* All the routers (except for Linux) return only
-   8 bytes of packet payload. It means, that precise relaying of
-   ICMP in the real Internet is absolutely infeasible.
- */
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
@@ -500,7 +530,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        case ICMP_DEST_UNREACH:
                switch (code) {
                case ICMP_SR_FAILED:
-               case ICMP_PORT_UNREACH:
                        /* Impossible event. */
                        return 0;
                default:
@@ -545,6 +574,9 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                goto out;
 
        err = 0;
+       if (!ipip6_err_gen_icmpv6_unreach(skb))
+               goto out;
+
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
                goto out;
 
@@ -919,7 +951,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (!new_skb) {
                        ip_rt_put(rt);
                        dev->stats.tx_dropped++;
-                       dev_kfree_skb(skb);
+                       kfree_skb(skb);
                        return NETDEV_TX_OK;
                }
                if (skb->sk)
@@ -945,7 +977,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 tx_error_icmp:
        dst_link_failure(skb);
 tx_error:
-       dev_kfree_skb(skb);
+       kfree_skb(skb);
 out:
        dev->stats.tx_errors++;
        return NETDEV_TX_OK;
@@ -985,7 +1017,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
 
 tx_err:
        dev->stats.tx_errors++;
-       dev_kfree_skb(skb);
+       kfree_skb(skb);
        return NETDEV_TX_OK;
 
 }
index 0740f93a114a26ac09150638576f523bcd53694c..f67033b4bb6687621b7df4f9d3b691519c65f629 100644 (file)
@@ -156,7 +156,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
index c1097c79890070e3d04517cecb7f0b263c0a4fc7..6d18157dc32c5e6fadf7798d26cdd665e18cb541 100644 (file)
@@ -37,34 +37,32 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
        __wsum wsum;
-       __sum16 sum;
+
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
+       wsum = skb->csum;
 
        switch (skb->ip_summed) {
+       case CHECKSUM_NONE:
+               wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
+                                   wsum);
+
+               /* fall through */
+
        case CHECKSUM_COMPLETE:
                if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
-                                 skb->csum)) {
+                                 wsum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-flush:
+
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
-                                                   skb_gro_len(skb),
-                                                   IPPROTO_TCP, 0));
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 81eb8cf8389b6a5af55f7b2994d7dbefe3d732bf..089c741a399217b2c7dd90f7783df4aa89eb5424 100644 (file)
@@ -393,10 +393,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        bool slow;
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1140,7 +1140,6 @@ do_udp_sendmsg:
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
index cfd65304be60ae8937449a8c1e4cf77406c11305..bb6e206ea70b84ed180eb73a302fb6349b0f3fe8 100644 (file)
@@ -528,7 +528,6 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
@@ -665,7 +664,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                *addr_len = sizeof(*lsa);
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
index 95667b088c5b73cd0e95e8c1753ed76acec9dca0..364ce0c5962fd48c85ea23b71b2d1dd463082575 100644 (file)
@@ -1368,7 +1368,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                        changed |=
                              ieee80211_mps_set_sta_local_pm(sta,
                                                             params->local_pm);
-               ieee80211_bss_info_change_notify(sdata, changed);
+               ieee80211_mbss_info_change_notify(sdata, changed);
 #endif
        }
 
@@ -2488,8 +2488,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
-       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-           sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return -EOPNOTSUPP;
 
        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
@@ -3120,9 +3119,17 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                    params->chandef.chan->band)
                        return -EINVAL;
 
+               ifmsh->chsw_init = true;
+               if (!ifmsh->pre_value)
+                       ifmsh->pre_value = 1;
+               else
+                       ifmsh->pre_value++;
+
                err = ieee80211_mesh_csa_beacon(sdata, params, true);
-               if (err < 0)
+               if (err < 0) {
+                       ifmsh->chsw_init = false;
                        return err;
+               }
                break;
 #endif
        default:
index 531be040b9ae85972d61bf7df248ae28308d811b..27a39de89679b7d3710fea18a65b6d5df6d003d0 100644 (file)
@@ -823,6 +823,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        if (err)
                return false;
 
+       /* channel switch is not supported, disconnect */
+       if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
+               goto disconnect;
+
        params.count = csa_ie.count;
        params.chandef = csa_ie.chandef;
 
index 29dc505be125c3c19737f8f6cee911492c52727c..4aea4e7911135133818e66a1439b111d14e6147e 100644 (file)
@@ -1228,6 +1228,7 @@ struct ieee80211_csa_ie {
        u8 mode;
        u8 count;
        u8 ttl;
+       u16 pre_value;
 };
 
 /* Parsed Information Elements */
index ff101ea1d9ae1e208deb5d6fe1d67c1677b398c2..36c3a4cbcabf66b2a0864414b3c23ea2896b7c4e 100644 (file)
@@ -1325,7 +1325,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.bssid = NULL;
                break;
        case NL80211_IFTYPE_AP_VLAN:
-               break;
        case NL80211_IFTYPE_P2P_DEVICE:
                sdata->vif.bss_conf.bssid = sdata->vif.addr;
                break;
index 21d5d44444d04c82fc73c9fd6dee3f58ab56e512..7d1c3ac48ed941866170afdf387def183690d612 100644 (file)
@@ -940,6 +940,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
                            result);
 
+       local->hw.conf.flags = IEEE80211_CONF_IDLE;
+
        ieee80211_led_init(local);
 
        rtnl_lock();
@@ -1047,6 +1049,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        cancel_work_sync(&local->restart_work);
        cancel_work_sync(&local->reconfig_filter);
+       flush_work(&local->sched_scan_stopped_work);
 
        ieee80211_clear_tx_pending(local);
        rate_control_deinitialize(local);
index 896fe3bd599e9bedd5db13dbc8ed04ab76e5bd88..ba105257d03f1cffc4398f42c52e67b1e8d3eaaa 100644 (file)
@@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
                 params.chandef.chan->center_freq);
 
        params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
-       if (beacon)
+       if (beacon) {
                ifmsh->chsw_ttl = csa_ie.ttl - 1;
-       else
-               ifmsh->chsw_ttl = 0;
+               if (ifmsh->pre_value >= csa_ie.pre_value)
+                       return false;
+               ifmsh->pre_value = csa_ie.pre_value;
+       }
 
-       if (ifmsh->chsw_ttl > 0)
+       if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
                if (ieee80211_mesh_csa_beacon(sdata, &params, false) < 0)
                        return false;
+       } else {
+               return false;
+       }
 
        sdata->csa_radar_required = params.radar_required;
 
@@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
        offset_ttl = (len < 42) ? 7 : 10;
        *(pos + offset_ttl) -= 1;
        *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
-       sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
 
        memcpy(mgmt_fwd, mgmt, len);
        eth_broadcast_addr(mgmt_fwd->da);
@@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
        u16 pre_value;
        bool fwd_csa = true;
        size_t baselen;
-       u8 *pos, ttl;
+       u8 *pos;
 
        if (mgmt->u.action.u.measurement.action_code !=
            WLAN_ACTION_SPCT_CHL_SWITCH)
@@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
                           u.action.u.chan_switch.variable);
        ieee802_11_parse_elems(pos, len - baselen, false, &elems);
 
-       ttl = elems.mesh_chansw_params_ie->mesh_ttl;
-       if (!--ttl)
+       ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
+       if (!--ifmsh->chsw_ttl)
                fwd_csa = false;
 
        pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
index d7504ab61a34c7ef6a51f8adce10e58c021408d0..b3a3ce316656ce8406859a3cdc325fa262e024a5 100644 (file)
@@ -1910,6 +1910,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
                already = true;
 
+       ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
+
        mutex_unlock(&sdata->local->mtx);
 
        if (already)
index 5d60779a0c1be89e987b2cd478af865ec806d4bb..4096ff6cc24fe8a5c3505411c5b232e0d800e050 100644 (file)
@@ -226,7 +226,7 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
                nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
 
        nsecs += minstrel_mcs_groups[group].duration[rate];
-       tp = 1000000 * ((mr->probability * 1000) / nsecs);
+       tp = 1000000 * ((prob * 1000) / nsecs);
 
        mr->cur_tp = MINSTREL_TRUNC(tp);
 }
@@ -277,13 +277,15 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
                        if (!(mg->supported & BIT(i)))
                                continue;
 
+                       index = MCS_GROUP_RATES * group + i;
+
                        /* initialize rates selections starting indexes */
                        if (!mg_rates_valid) {
                                mg->max_tp_rate = mg->max_tp_rate2 =
                                        mg->max_prob_rate = i;
                                if (!mi_rates_valid) {
                                        mi->max_tp_rate = mi->max_tp_rate2 =
-                                               mi->max_prob_rate = i;
+                                               mi->max_prob_rate = index;
                                        mi_rates_valid = true;
                                }
                                mg_rates_valid = true;
@@ -291,7 +293,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 
                        mr = &mg->rates[i];
                        mr->retry_updated = false;
-                       index = MCS_GROUP_RATES * group + i;
                        minstrel_calc_rate_ewma(mr);
                        minstrel_ht_calc_tp(mi, group, i);
 
index caecef870c0e44e3562cdc0a874bcfd233fc77a1..2b0debb0422b91d89a0a7982b94726f3b9ceae11 100644 (file)
@@ -911,7 +911,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        u16 sc;
        u8 tid, ack_policy;
 
-       if (!ieee80211_is_data_qos(hdr->frame_control))
+       if (!ieee80211_is_data_qos(hdr->frame_control) ||
+           is_multicast_ether_addr(hdr->addr1))
                goto dont_reorder;
 
        /*
index 5ad66a83ef7f4d4525de163c2c2f1fe9d6931a04..bcc4833d7542b91e1b754ed490d1dedcaee559c1 100644 (file)
@@ -1088,6 +1088,6 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
 
        trace_api_sched_scan_stopped(local);
 
-       ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work);
+       schedule_work(&local->sched_scan_stopped_work);
 }
 EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
index a40da20b32e074a3923f844edf104eca33a6134c..6ab00907008461fb14d551b2633a8dbcd4fef623 100644 (file)
@@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
        if (elems->mesh_chansw_params_ie) {
                csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
                csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
+               csa_ie->pre_value = le16_to_cpu(
+                               elems->mesh_chansw_params_ie->mesh_pre_value);
        }
 
        new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
index 592a18171f95e9ec5273b03307235dff2bd1c946..9f9b9bd3fd44798e7030fb3a44c46da962cfd7ba 100644 (file)
@@ -2278,17 +2278,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
 {
        struct ieee80211_local *local =
                container_of(work, struct ieee80211_local, radar_detected_work);
-       struct cfg80211_chan_def chandef;
+       struct cfg80211_chan_def chandef = local->hw.conf.chandef;
 
        ieee80211_dfs_cac_cancel(local);
 
        if (local->use_chanctx)
                /* currently not handled */
                WARN_ON(1);
-       else {
-               chandef = local->hw.conf.chandef;
+       else
                cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
-       }
 }
 
 void ieee80211_radar_detected(struct ieee80211_hw *hw)
@@ -2459,14 +2457,9 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
                          WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
                put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
                pos += 2;
-               if (!ifmsh->pre_value)
-                       ifmsh->pre_value = 1;
-               else
-                       ifmsh->pre_value++;
                pre_value = cpu_to_le16(ifmsh->pre_value);
                memcpy(pos, &pre_value, 2);             /* Precedence Value */
                pos += 2;
-               ifmsh->chsw_init = true;
        }
 
        ieee80211_tx_skb(sdata, skb);
index 2bc2dec20b007026e78aba74451e70039c6e5988..6226803fc490ce33c53994c344a1c034b9b0cce9 100644 (file)
@@ -59,7 +59,7 @@ hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1,
                     u32 *multi)
 {
        return ip1->ipcmp == ip2->ipcmp &&
-              ip2->ccmp == ip2->ccmp;
+              ip1->ccmp == ip2->ccmp;
 }
 
 static inline int
index dcddc49c0e08363044195695138543e4277f83f0..f93b7d06f4be9525ad4ab4314a106b01e85749ba 100644 (file)
@@ -1717,6 +1717,19 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
        return -ENOENT;
 }
 
+static int nf_table_delrule_by_chain(struct nft_ctx *ctx)
+{
+       struct nft_rule *rule;
+       int err;
+
+       list_for_each_entry(rule, &ctx->chain->rules, list) {
+               err = nf_tables_delrule_one(ctx, rule);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
 static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
                             const struct nlmsghdr *nlh,
                             const struct nlattr * const nla[])
@@ -1725,8 +1738,8 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
        const struct nft_af_info *afi;
        struct net *net = sock_net(skb->sk);
        const struct nft_table *table;
-       struct nft_chain *chain;
-       struct nft_rule *rule, *tmp;
+       struct nft_chain *chain = NULL;
+       struct nft_rule *rule;
        int family = nfmsg->nfgen_family, err = 0;
        struct nft_ctx ctx;
 
@@ -1738,22 +1751,29 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(table))
                return PTR_ERR(table);
 
-       chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
-       if (IS_ERR(chain))
-               return PTR_ERR(chain);
+       if (nla[NFTA_RULE_CHAIN]) {
+               chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
+               if (IS_ERR(chain))
+                       return PTR_ERR(chain);
+       }
 
        nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
 
-       if (nla[NFTA_RULE_HANDLE]) {
-               rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
-               if (IS_ERR(rule))
-                       return PTR_ERR(rule);
+       if (chain) {
+               if (nla[NFTA_RULE_HANDLE]) {
+                       rule = nf_tables_rule_lookup(chain,
+                                                    nla[NFTA_RULE_HANDLE]);
+                       if (IS_ERR(rule))
+                               return PTR_ERR(rule);
 
-               err = nf_tables_delrule_one(&ctx, rule);
-       } else {
-               /* Remove all rules in this chain */
-               list_for_each_entry_safe(rule, tmp, &chain->rules, list) {
                        err = nf_tables_delrule_one(&ctx, rule);
+               } else {
+                       err = nf_table_delrule_by_chain(&ctx);
+               }
+       } else {
+               list_for_each_entry(chain, &table->chains, list) {
+                       ctx.chain = chain;
+                       err = nf_table_delrule_by_chain(&ctx);
                        if (err < 0)
                                break;
                }
index 9ff035c7140324632965fbf82764d532d4d0a284..a3910fc2122bc1aa560815394b525098cb02e85c 100644 (file)
@@ -325,21 +325,24 @@ static void htable_gc(unsigned long htlong)
        add_timer(&ht->timer);
 }
 
-static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo)
 {
        struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net);
        struct proc_dir_entry *parent;
 
-       del_timer_sync(&hinfo->timer);
-
        if (hinfo->family == NFPROTO_IPV4)
                parent = hashlimit_net->ipt_hashlimit;
        else
                parent = hashlimit_net->ip6t_hashlimit;
 
-       if(parent != NULL)
+       if (parent != NULL)
                remove_proc_entry(hinfo->name, parent);
+}
 
+static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+{
+       del_timer_sync(&hinfo->timer);
+       htable_remove_proc_entry(hinfo);
        htable_selective_cleanup(hinfo, select_all);
        kfree(hinfo->name);
        vfree(hinfo);
@@ -883,21 +886,15 @@ static int __net_init hashlimit_proc_net_init(struct net *net)
 static void __net_exit hashlimit_proc_net_exit(struct net *net)
 {
        struct xt_hashlimit_htable *hinfo;
-       struct proc_dir_entry *pde;
        struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
 
-       /* recent_net_exit() is called before recent_mt_destroy(). Make sure
-        * that the parent xt_recent proc entry is is empty before trying to
-        * remove it.
+       /* hashlimit_net_exit() is called before hashlimit_mt_destroy().
+        * Make sure that the parent ipt_hashlimit and ip6t_hashlimit proc
+        * entries is empty before trying to remove it.
         */
        mutex_lock(&hashlimit_mutex);
-       pde = hashlimit_net->ipt_hashlimit;
-       if (pde == NULL)
-               pde = hashlimit_net->ip6t_hashlimit;
-
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node)
-               remove_proc_entry(hinfo->name, pde);
-
+               htable_remove_proc_entry(hinfo);
        hashlimit_net->ipt_hashlimit = NULL;
        hashlimit_net->ip6t_hashlimit = NULL;
        mutex_unlock(&hashlimit_mutex);
index 4518a57aa5febb14db1c1d750f217102dd8fd2a9..713671ae45aff688e693d6087ae4d8ce9e986f48 100644 (file)
@@ -74,9 +74,12 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
  * Bit 17 is marked as already used since the VFS quota code
  * also abused this API and relied on family == group ID, we
  * cater to that by giving it a static family and group ID.
+ * Bit 18 is marked as already used since the PMCRAID driver
+ * did the same thing as the VFS quota code (maybe copied?)
  */
 static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
-                                     BIT(GENL_ID_VFS_DQUOT);
+                                     BIT(GENL_ID_VFS_DQUOT) |
+                                     BIT(GENL_ID_PMCRAID);
 static unsigned long *mc_groups = &mc_group_start;
 static unsigned long mc_groups_longs = 1;
 
@@ -139,6 +142,7 @@ static u16 genl_generate_id(void)
 
        for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
                if (id_gen_idx != GENL_ID_VFS_DQUOT &&
+                   id_gen_idx != GENL_ID_PMCRAID &&
                    !genl_family_find_byid(id_gen_idx))
                        return id_gen_idx;
                if (++id_gen_idx > GENL_MAX_ID)
@@ -214,7 +218,7 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
 {
        int first_id;
        int n_groups = family->n_mcgrps;
-       int err, i;
+       int err = 0, i;
        bool groups_allocated = false;
 
        if (!n_groups)
@@ -236,9 +240,12 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
        } else if (strcmp(family->name, "NET_DM") == 0) {
                first_id = 1;
                BUG_ON(n_groups != 1);
-       } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
+       } else if (family->id == GENL_ID_VFS_DQUOT) {
                first_id = GENL_ID_VFS_DQUOT;
                BUG_ON(n_groups != 1);
+       } else if (family->id == GENL_ID_PMCRAID) {
+               first_id = GENL_ID_PMCRAID;
+               BUG_ON(n_groups != 1);
        } else {
                groups_allocated = true;
                err = genl_allocate_reserve_groups(n_groups, &first_id);
index ac27c86ef6d11e00c2ecb1512b09bbda73c3eefc..88cfbc189558f75b4b508b849827eea18c3be7c0 100644 (file)
@@ -237,6 +237,30 @@ struct packet_skb_cb {
 static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
 static void __fanout_link(struct sock *sk, struct packet_sock *po);
 
+static struct net_device *packet_cached_dev_get(struct packet_sock *po)
+{
+       struct net_device *dev;
+
+       rcu_read_lock();
+       dev = rcu_dereference(po->cached_dev);
+       if (likely(dev))
+               dev_hold(dev);
+       rcu_read_unlock();
+
+       return dev;
+}
+
+static void packet_cached_dev_assign(struct packet_sock *po,
+                                    struct net_device *dev)
+{
+       rcu_assign_pointer(po->cached_dev, dev);
+}
+
+static void packet_cached_dev_reset(struct packet_sock *po)
+{
+       RCU_INIT_POINTER(po->cached_dev, NULL);
+}
+
 /* register_prot_hook must be invoked with the po->bind_lock held,
  * or from a context in which asynchronous accesses to the packet
  * socket is not possible (packet_create()).
@@ -246,12 +270,10 @@ static void register_prot_hook(struct sock *sk)
        struct packet_sock *po = pkt_sk(sk);
 
        if (!po->running) {
-               if (po->fanout) {
+               if (po->fanout)
                        __fanout_link(sk, po);
-               } else {
+               else
                        dev_add_pack(&po->prot_hook);
-                       rcu_assign_pointer(po->cached_dev, po->prot_hook.dev);
-               }
 
                sock_hold(sk);
                po->running = 1;
@@ -270,12 +292,11 @@ static void __unregister_prot_hook(struct sock *sk, bool sync)
        struct packet_sock *po = pkt_sk(sk);
 
        po->running = 0;
-       if (po->fanout) {
+
+       if (po->fanout)
                __fanout_unlink(sk, po);
-       } else {
+       else
                __dev_remove_pack(&po->prot_hook);
-               RCU_INIT_POINTER(po->cached_dev, NULL);
-       }
 
        __sock_put(sk);
 
@@ -439,9 +460,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po,
 
        pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
 
-       spin_lock(&rb_queue->lock);
+       spin_lock_bh(&rb_queue->lock);
        pkc->delete_blk_timer = 1;
-       spin_unlock(&rb_queue->lock);
+       spin_unlock_bh(&rb_queue->lock);
 
        prb_del_retire_blk_timer(pkc);
 }
@@ -2059,19 +2080,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
        return tp_len;
 }
 
-static struct net_device *packet_cached_dev_get(struct packet_sock *po)
-{
-       struct net_device *dev;
-
-       rcu_read_lock();
-       dev = rcu_dereference(po->cached_dev);
-       if (dev)
-               dev_hold(dev);
-       rcu_read_unlock();
-
-       return dev;
-}
-
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 {
        struct sk_buff *skb;
@@ -2088,7 +2096,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
-       if (saddr == NULL) {
+       if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
                addr    = NULL;
@@ -2242,7 +2250,7 @@ static int packet_snd(struct socket *sock,
         *      Get and verify the address.
         */
 
-       if (saddr == NULL) {
+       if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
                addr    = NULL;
@@ -2451,6 +2459,8 @@ static int packet_release(struct socket *sock)
 
        spin_lock(&po->bind_lock);
        unregister_prot_hook(sk, false);
+       packet_cached_dev_reset(po);
+
        if (po->prot_hook.dev) {
                dev_put(po->prot_hook.dev);
                po->prot_hook.dev = NULL;
@@ -2506,14 +2516,17 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
 
        spin_lock(&po->bind_lock);
        unregister_prot_hook(sk, true);
+
        po->num = protocol;
        po->prot_hook.type = protocol;
        if (po->prot_hook.dev)
                dev_put(po->prot_hook.dev);
-       po->prot_hook.dev = dev;
 
+       po->prot_hook.dev = dev;
        po->ifindex = dev ? dev->ifindex : 0;
 
+       packet_cached_dev_assign(po, dev);
+
        if (protocol == 0)
                goto out_unlock;
 
@@ -2626,7 +2639,8 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
        po = pkt_sk(sk);
        sk->sk_family = PF_PACKET;
        po->num = proto;
-       RCU_INIT_POINTER(po->cached_dev, NULL);
+
+       packet_cached_dev_reset(po);
 
        sk->sk_destruct = packet_sock_destruct;
        sk_refcnt_debug_inc(sk);
@@ -3337,6 +3351,7 @@ static int packet_notifier(struct notifier_block *this,
                                                sk->sk_error_report(sk);
                                }
                                if (msg == NETDEV_UNREGISTER) {
+                                       packet_cached_dev_reset(po);
                                        po->ifindex = -1;
                                        if (po->prot_hook.dev)
                                                dev_put(po->prot_hook.dev);
index e59094981175cd6c390b5ed83a2dec15d8e2407e..37be6e226d1b46fefe8e0cf554580b1faf19cfb8 100644 (file)
@@ -552,9 +552,8 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
            && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
                rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
                scat = &rm->data.op_sg[sg];
-               ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
-               ret = min_t(int, ret, scat->length - conn->c_xmit_data_off);
-               return ret;
+               ret = max_t(int, RDS_CONG_MAP_BYTES, scat->length);
+               return sizeof(struct rds_header) + ret;
        }
 
        /* FIXME we may overallocate here */
index fd7072827a40139c4ffba595aaa261282641e37f..69cb848e83455035a3e9ad85b2d7922434069d7e 100644 (file)
@@ -270,6 +270,16 @@ int tcf_register_action(struct tc_action_ops *act)
 {
        struct tc_action_ops *a, **ap;
 
+       /* Must supply act, dump, cleanup and init */
+       if (!act->act || !act->dump || !act->cleanup || !act->init)
+               return -EINVAL;
+
+       /* Supply defaults */
+       if (!act->lookup)
+               act->lookup = tcf_hash_search;
+       if (!act->walk)
+               act->walk = tcf_generic_walker;
+
        write_lock(&act_mod_lock);
        for (ap = &act_base; (a = *ap) != NULL; ap = &a->next) {
                if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
@@ -381,7 +391,7 @@ int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
        }
        while ((a = act) != NULL) {
 repeat:
-               if (a->ops && a->ops->act) {
+               if (a->ops) {
                        ret = a->ops->act(skb, a, res);
                        if (TC_MUNGED & skb->tc_verd) {
                                /* copied already, allow trampling */
@@ -405,7 +415,7 @@ void tcf_action_destroy(struct tc_action *act, int bind)
        struct tc_action *a;
 
        for (a = act; a; a = act) {
-               if (a->ops && a->ops->cleanup) {
+               if (a->ops) {
                        if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
                                module_put(a->ops->owner);
                        act = act->next;
@@ -424,7 +434,7 @@ tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        int err = -EINVAL;
 
-       if (a->ops == NULL || a->ops->dump == NULL)
+       if (a->ops == NULL)
                return err;
        return a->ops->dump(skb, a, bind, ref);
 }
@@ -436,7 +446,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
 
-       if (a->ops == NULL || a->ops->dump == NULL)
+       if (a->ops == NULL)
                return err;
 
        if (nla_put_string(skb, TCA_KIND, a->ops->kind))
@@ -723,8 +733,6 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
        a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
        if (a->ops == NULL)
                goto err_free;
-       if (a->ops->lookup == NULL)
-               goto err_mod;
        err = -ENOENT;
        if (a->ops->lookup(a, index) == 0)
                goto err_mod;
@@ -1084,12 +1092,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
        memset(&a, 0, sizeof(struct tc_action));
        a.ops = a_o;
 
-       if (a_o->walk == NULL) {
-               WARN(1, "tc_dump_action: %s !capable of dumping table\n",
-                    a_o->kind);
-               goto out_module_put;
-       }
-
        nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
                        cb->nlh->nlmsg_type, sizeof(*t), 0);
        if (!nlh)
index 3a4c0caa1f7de0fdfdb618bac9308aa32330c7f7..5c5edf56adbd4fc9a4d64a509a9103511f995db4 100644 (file)
@@ -585,9 +585,7 @@ static struct tc_action_ops act_csum_ops = {
        .act            = tcf_csum,
        .dump           = tcf_csum_dump,
        .cleanup        = tcf_csum_cleanup,
-       .lookup         = tcf_hash_search,
        .init           = tcf_csum_init,
-       .walk           = tcf_generic_walker
 };
 
 MODULE_DESCRIPTION("Checksum updating actions");
index fd2b3cff5fa28cf4da25690da9e7bad410c60a78..5645a4d32abdd187f59d9f6301842e35d08762df 100644 (file)
@@ -206,9 +206,7 @@ static struct tc_action_ops act_gact_ops = {
        .act            =       tcf_gact,
        .dump           =       tcf_gact_dump,
        .cleanup        =       tcf_gact_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_gact_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
index 60d88b6b9560bc0a7836fa0cba845ddd6a57cb3c..882a89762f77c2edb8b6d10d0c8ef69cf3e39aac 100644 (file)
@@ -298,9 +298,7 @@ static struct tc_action_ops act_ipt_ops = {
        .act            =       tcf_ipt,
        .dump           =       tcf_ipt_dump,
        .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
 };
 
 static struct tc_action_ops act_xt_ops = {
@@ -312,9 +310,7 @@ static struct tc_action_ops act_xt_ops = {
        .act            =       tcf_ipt,
        .dump           =       tcf_ipt_dump,
        .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");
index 977c10e0631b6dfe4ead45af617c0ad93c4a0759..252378121ce7cd1848beab20aa666389937bf610 100644 (file)
@@ -271,9 +271,7 @@ static struct tc_action_ops act_mirred_ops = {
        .act            =       tcf_mirred,
        .dump           =       tcf_mirred_dump,
        .cleanup        =       tcf_mirred_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_mirred_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002)");
index 876f0ef29694a3f28260a221d0862d4fe3756f8d..6a15ace002411a8c11efeed6156d72324b9eb2ff 100644 (file)
@@ -308,9 +308,7 @@ static struct tc_action_ops act_nat_ops = {
        .act            =       tcf_nat,
        .dump           =       tcf_nat_dump,
        .cleanup        =       tcf_nat_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_nat_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_DESCRIPTION("Stateless NAT actions");
index 7ed78c9e505cf7e18bc5a0b066837d19d33d4b10..03b67674169c5db79eb546d93d0b4833324786d3 100644 (file)
@@ -243,9 +243,7 @@ static struct tc_action_ops act_pedit_ops = {
        .act            =       tcf_pedit,
        .dump           =       tcf_pedit_dump,
        .cleanup        =       tcf_pedit_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_pedit_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
index 272d8e924cf6b2467e2772898aca2d7895131545..16a62c36928a78110923d36d5b87808936d8f90a 100644 (file)
@@ -407,7 +407,6 @@ static struct tc_action_ops act_police_ops = {
        .act            =       tcf_act_police,
        .dump           =       tcf_act_police_dump,
        .cleanup        =       tcf_act_police_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_act_police_locate,
        .walk           =       tcf_act_police_walker
 };
index 7725eb4ab756caa841eca2e0f4778880c310e5c4..31157d3e729c8c29e8bb89ce03fa68c5ad8e7f39 100644 (file)
@@ -201,7 +201,6 @@ static struct tc_action_ops act_simp_ops = {
        .dump           =       tcf_simp_dump,
        .cleanup        =       tcf_simp_cleanup,
        .init           =       tcf_simp_init,
-       .walk           =       tcf_generic_walker,
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2005)");
index cb4221171f93f0c5b8fbb98f41b11241aa17d02a..35ea643b4325562d74c4c05d9950a4f8a8a7ad32 100644 (file)
@@ -203,7 +203,6 @@ static struct tc_action_ops act_skbedit_ops = {
        .dump           =       tcf_skbedit_dump,
        .cleanup        =       tcf_skbedit_cleanup,
        .init           =       tcf_skbedit_init,
-       .walk           =       tcf_generic_walker,
 };
 
 MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
index 0e1e38b40025fd111f50bfce339a6d2e7cae1252..717b2108f852b52399270a5be516441d9c79ed83 100644 (file)
@@ -1477,11 +1477,22 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                sch_tree_lock(sch);
        }
 
+       rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
+
+       ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
+
+       psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
+       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
+
        /* it used to be a nasty bug here, we have to check that node
         * is really leaf before changing cl->un.leaf !
         */
        if (!cl->level) {
-               cl->quantum = hopt->rate.rate / q->rate2quantum;
+               u64 quantum = cl->rate.rate_bytes_ps;
+
+               do_div(quantum, q->rate2quantum);
+               cl->quantum = min_t(u64, quantum, INT_MAX);
+
                if (!hopt->quantum && cl->quantum < 1000) {
                        pr_warning(
                               "HTB: quantum of class %X is small. Consider r2q change.\n",
@@ -1500,13 +1511,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                        cl->prio = TC_HTB_NUMPRIO - 1;
        }
 
-       rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
-
-       ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
-
-       psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
-       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
-
        cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
        cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer);
 
index 75c94e59a3bd3889cd87460afe87ac611eeb024e..bccd52b36e97be79d446e233dedc960fe65d5f16 100644 (file)
@@ -215,10 +215,10 @@ static bool loss_4state(struct netem_sched_data *q)
                if (rnd < clg->a4) {
                        clg->state = 4;
                        return true;
-               } else if (clg->a4 < rnd && rnd < clg->a1) {
+               } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
                        clg->state = 3;
                        return true;
-               } else if (clg->a1 < rnd)
+               } else if (clg->a1 + clg->a4 < rnd)
                        clg->state = 1;
 
                break;
@@ -268,10 +268,11 @@ static bool loss_gilb_ell(struct netem_sched_data *q)
                        clg->state = 2;
                if (net_random() < clg->a4)
                        return true;
+               break;
        case 2:
                if (net_random() < clg->a2)
                        clg->state = 1;
-               if (clg->a3 > net_random())
+               if (net_random() > clg->a3)
                        return true;
        }
 
index 68f98595819c1224f7e64ad368ad51155ff07fea..887e672f9d7d4b185542957bcb7e10b7d8a70cec 100644 (file)
@@ -21,6 +21,7 @@
 #include <net/netlink.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
+#include <net/tcp.h>
 
 
 /*     Simple Token Bucket Filter.
@@ -117,6 +118,48 @@ struct tbf_sched_data {
 };
 
 
+/* Time to Length, convert time in ns to length in bytes
+ * to determinate how many bytes can be sent in given time.
+ */
+static u64 psched_ns_t2l(const struct psched_ratecfg *r,
+                        u64 time_in_ns)
+{
+       /* The formula is :
+        * len = (time_in_ns * r->rate_bytes_ps) / NSEC_PER_SEC
+        */
+       u64 len = time_in_ns * r->rate_bytes_ps;
+
+       do_div(len, NSEC_PER_SEC);
+
+       if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) {
+               do_div(len, 53);
+               len = len * 48;
+       }
+
+       if (len > r->overhead)
+               len -= r->overhead;
+       else
+               len = 0;
+
+       return len;
+}
+
+/*
+ * Return length of individual segments of a gso packet,
+ * including all headers (MAC, IP, TCP/UDP)
+ */
+static unsigned int skb_gso_seglen(const struct sk_buff *skb)
+{
+       unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
+       const struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+       if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
+               hdr_len += tcp_hdrlen(skb);
+       else
+               hdr_len += sizeof(struct udphdr);
+       return hdr_len + shinfo->gso_size;
+}
+
 /* GSO packet is too big, segment it so that tbf can transmit
  * each segment in time
  */
@@ -136,12 +179,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
        while (segs) {
                nskb = segs->next;
                segs->next = NULL;
-               if (likely(segs->len <= q->max_size)) {
-                       qdisc_skb_cb(segs)->pkt_len = segs->len;
-                       ret = qdisc_enqueue(segs, q->qdisc);
-               } else {
-                       ret = qdisc_reshape_fail(skb, sch);
-               }
+               qdisc_skb_cb(segs)->pkt_len = segs->len;
+               ret = qdisc_enqueue(segs, q->qdisc);
                if (ret != NET_XMIT_SUCCESS) {
                        if (net_xmit_drop_count(ret))
                                sch->qstats.drops++;
@@ -163,7 +202,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
-               if (skb_is_gso(skb))
+               if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size)
                        return tbf_segment(skb, sch);
                return qdisc_reshape_fail(skb, sch);
        }
@@ -276,10 +315,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        struct tbf_sched_data *q = qdisc_priv(sch);
        struct nlattr *tb[TCA_TBF_MAX + 1];
        struct tc_tbf_qopt *qopt;
-       struct qdisc_rate_table *rtab = NULL;
-       struct qdisc_rate_table *ptab = NULL;
        struct Qdisc *child = NULL;
-       int max_size, n;
+       struct psched_ratecfg rate;
+       struct psched_ratecfg peak;
+       u64 max_size;
+       s64 buffer, mtu;
        u64 rate64 = 0, prate64 = 0;
 
        err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy);
@@ -291,33 +331,13 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                goto done;
 
        qopt = nla_data(tb[TCA_TBF_PARMS]);
-       rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]);
-       if (rtab == NULL)
-               goto done;
+       if (qopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
+               qdisc_put_rtab(qdisc_get_rtab(&qopt->rate,
+                                             tb[TCA_TBF_RTAB]));
 
-       if (qopt->peakrate.rate) {
-               if (qopt->peakrate.rate > qopt->rate.rate)
-                       ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]);
-               if (ptab == NULL)
-                       goto done;
-       }
-
-       for (n = 0; n < 256; n++)
-               if (rtab->data[n] > qopt->buffer)
-                       break;
-       max_size = (n << qopt->rate.cell_log) - 1;
-       if (ptab) {
-               int size;
-
-               for (n = 0; n < 256; n++)
-                       if (ptab->data[n] > qopt->mtu)
-                               break;
-               size = (n << qopt->peakrate.cell_log) - 1;
-               if (size < max_size)
-                       max_size = size;
-       }
-       if (max_size < 0)
-               goto done;
+       if (qopt->peakrate.linklayer == TC_LINKLAYER_UNAWARE)
+                       qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate,
+                                                     tb[TCA_TBF_PTAB]));
 
        if (q->qdisc != &noop_qdisc) {
                err = fifo_set_limit(q->qdisc, qopt->limit);
@@ -331,6 +351,39 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                }
        }
 
+       buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
+       mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
+
+       if (tb[TCA_TBF_RATE64])
+               rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
+       psched_ratecfg_precompute(&rate, &qopt->rate, rate64);
+
+       max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+
+       if (qopt->peakrate.rate) {
+               if (tb[TCA_TBF_PRATE64])
+                       prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
+               psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64);
+               if (peak.rate_bytes_ps <= rate.rate_bytes_ps) {
+                       pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n",
+                                           peak.rate_bytes_ps, rate.rate_bytes_ps);
+                       err = -EINVAL;
+                       goto done;
+               }
+
+               max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+       }
+
+       if (max_size < psched_mtu(qdisc_dev(sch)))
+               pr_warn_ratelimited("sch_tbf: burst %llu is lower than device %s mtu (%u) !\n",
+                                   max_size, qdisc_dev(sch)->name,
+                                   psched_mtu(qdisc_dev(sch)));
+
+       if (!max_size) {
+               err = -EINVAL;
+               goto done;
+       }
+
        sch_tree_lock(sch);
        if (child) {
                qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
@@ -344,13 +397,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
 
-       if (tb[TCA_TBF_RATE64])
-               rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
-       psched_ratecfg_precompute(&q->rate, &rtab->rate, rate64);
-       if (ptab) {
-               if (tb[TCA_TBF_PRATE64])
-                       prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
-               psched_ratecfg_precompute(&q->peak, &ptab->rate, prate64);
+       memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg));
+       if (qopt->peakrate.rate) {
+               memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg));
                q->peak_present = true;
        } else {
                q->peak_present = false;
@@ -359,10 +408,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        sch_tree_unlock(sch);
        err = 0;
 done:
-       if (rtab)
-               qdisc_put_rtab(rtab);
-       if (ptab)
-               qdisc_put_rtab(ptab);
        return err;
 }
 
index 68a27f9796d2ece54bcb53b98a47e8f98645077b..31ed008c8e13e88b88935c5d83a503bdc089076e 100644 (file)
@@ -154,8 +154,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
-               min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ;
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
 
        /* Initializes the timers */
        for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -291,8 +290,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
                asoc->peer.ipv6_address = 1;
        INIT_LIST_HEAD(&asoc->asocs);
 
-       asoc->autoclose = sp->autoclose;
-
        asoc->default_stream = sp->default_stream;
        asoc->default_ppid = sp->default_ppid;
        asoc->default_flags = sp->default_flags;
index e650978daf279abe9b1277dabb22f2e865c64a7a..0fb140f8f088abe9421c401680731fb1c916a154 100644 (file)
@@ -474,10 +474,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                         * for a given destination transport address.
                         */
 
-                       if (!tp->rto_pending) {
+                       if (!chunk->resent && !tp->rto_pending) {
                                chunk->rtt_in_progress = 1;
                                tp->rto_pending = 1;
                        }
+
                        has_data = 1;
                }
 
@@ -580,7 +581,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                unsigned long timeout;
 
                /* Restart the AUTOCLOSE timer when sending data. */
-               if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
+               if (sctp_state(asoc, ESTABLISHED) &&
+                   asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                        timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
                        timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
 
index 94df7587786992fa0a6341caaed284beb1df42e0..f51ba985a36eaaf0b021adba700cf16d42394e6f 100644 (file)
@@ -446,6 +446,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                                transport->rto_pending = 0;
                        }
 
+                       chunk->resent = 1;
+
                        /* Move the chunk to the retransmit queue. The chunks
                         * on the retransmit queue are always kept in order.
                         */
@@ -1375,6 +1377,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                 * instance).
                                 */
                                if (!tchunk->tsn_gap_acked &&
+                                   !tchunk->resent &&
                                    tchunk->rtt_in_progress) {
                                        tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
@@ -1391,7 +1394,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                         */
                        if (!tchunk->tsn_gap_acked) {
                                tchunk->tsn_gap_acked = 1;
-                               *highest_new_tsn_in_sack = tsn;
+                               if (TSN_lt(*highest_new_tsn_in_sack, tsn))
+                                       *highest_new_tsn_in_sack = tsn;
                                bytes_acked += sctp_data_size(tchunk);
                                if (!tchunk->transport)
                                        migrate_bytes += sctp_data_size(tchunk);
index 53c452efb40b4ab761a54acc37f8c1333fc73fd7..5e68b94ee64012571bc4d5f277a9cc594467cc3b 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
+MODULE_SOFTDEP("pre: sctp");
 MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>");
 MODULE_DESCRIPTION("SCTP snooper");
 MODULE_LICENSE("GPL");
@@ -182,6 +183,20 @@ static struct jprobe sctp_recv_probe = {
        .entry  = jsctp_sf_eat_sack,
 };
 
+static __init int sctp_setup_jprobe(void)
+{
+       int ret = register_jprobe(&sctp_recv_probe);
+
+       if (ret) {
+               if (request_module("sctp"))
+                       goto out;
+               ret = register_jprobe(&sctp_recv_probe);
+       }
+
+out:
+       return ret;
+}
+
 static __init int sctpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -202,7 +217,7 @@ static __init int sctpprobe_init(void)
                         &sctpprobe_fops))
                goto free_kfifo;
 
-       ret = register_jprobe(&sctp_recv_probe);
+       ret = sctp_setup_jprobe();
        if (ret)
                goto remove_proc;
 
index dfe3f36ff2aa27165b35a39d382583759cd3ebae..a26065be728901ed3c7e35690bafc51deabab115 100644 (file)
@@ -820,7 +820,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
 
-       if (new_asoc->autoclose)
+       if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -908,7 +908,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
        SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -2970,7 +2970,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net,
        if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
                force = SCTP_FORCE();
 
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@ -3878,7 +3878,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net,
                                SCTP_CHUNK(chunk));
 
        /* Count this as receiving DATA. */
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@ -5267,7 +5267,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
 
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -5346,7 +5346,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
index 72046b9729a8a6a669fb9c75446de8ef2fe345c6..42b709c95cf3d0f97b1de88d727a4258e8835396 100644 (file)
@@ -2196,6 +2196,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
                                     unsigned int optlen)
 {
        struct sctp_sock *sp = sctp_sk(sk);
+       struct net *net = sock_net(sk);
 
        /* Applicable to UDP-style socket only */
        if (sctp_style(sk, TCP))
@@ -2205,6 +2206,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
        if (copy_from_user(&sp->autoclose, optval, optlen))
                return -EFAULT;
 
+       if (sp->autoclose > net->sctp.max_autoclose)
+               sp->autoclose = net->sctp.max_autoclose;
+
        return 0;
 }
 
@@ -2811,6 +2815,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne
 {
        struct sctp_rtoinfo rtoinfo;
        struct sctp_association *asoc;
+       unsigned long rto_min, rto_max;
+       struct sctp_sock *sp = sctp_sk(sk);
 
        if (optlen != sizeof (struct sctp_rtoinfo))
                return -EINVAL;
@@ -2824,26 +2830,36 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne
        if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
                return -EINVAL;
 
+       rto_max = rtoinfo.srto_max;
+       rto_min = rtoinfo.srto_min;
+
+       if (rto_max)
+               rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max;
+       else
+               rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max;
+
+       if (rto_min)
+               rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min;
+       else
+               rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min;
+
+       if (rto_min > rto_max)
+               return -EINVAL;
+
        if (asoc) {
                if (rtoinfo.srto_initial != 0)
                        asoc->rto_initial =
                                msecs_to_jiffies(rtoinfo.srto_initial);
-               if (rtoinfo.srto_max != 0)
-                       asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
-               if (rtoinfo.srto_min != 0)
-                       asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);
+               asoc->rto_max = rto_max;
+               asoc->rto_min = rto_min;
        } else {
                /* If there is no association or the association-id = 0
                 * set the values to the endpoint.
                 */
-               struct sctp_sock *sp = sctp_sk(sk);
-
                if (rtoinfo.srto_initial != 0)
                        sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
-               if (rtoinfo.srto_max != 0)
-                       sp->rtoinfo.srto_max = rtoinfo.srto_max;
-               if (rtoinfo.srto_min != 0)
-                       sp->rtoinfo.srto_min = rtoinfo.srto_min;
+               sp->rtoinfo.srto_max = rto_max;
+               sp->rtoinfo.srto_min = rto_min;
        }
 
        return 0;
index 6b36561a1b3b7cceab5f5a4a9dce7aa2bc362266..b0565afb61c740bcd0ed9863049dc74cd62072f0 100644 (file)
@@ -56,11 +56,16 @@ extern long sysctl_sctp_mem[3];
 extern int sysctl_sctp_rmem[3];
 extern int sysctl_sctp_wmem[3];
 
-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
-
                                loff_t *ppos);
+
 static struct ctl_table sctp_table[] = {
        {
                .procname       = "sctp_mem",
@@ -102,17 +107,17 @@ static struct ctl_table sctp_net_table[] = {
                .data           = &init_net.sctp.rto_min,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_sctp_do_rto_min,
                .extra1         = &one,
-               .extra2         = &timer_max
+               .extra2         = &init_net.sctp.rto_max
        },
        {
                .procname       = "rto_max",
                .data           = &init_net.sctp.rto_max,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .proc_handler   = proc_sctp_do_rto_max,
+               .extra1         = &init_net.sctp.rto_min,
                .extra2         = &timer_max
        },
        {
@@ -294,8 +299,7 @@ static struct ctl_table sctp_net_table[] = {
        { /* sentinel */ }
 };
 
-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
                                loff_t *ppos)
 {
@@ -342,6 +346,60 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
        return ret;
 }
 
+static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_min;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_min = new_value;
+       }
+       return ret;
+}
+
+static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_max;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_max = new_value;
+       }
+       return ret;
+}
+
 int sctp_sysctl_net_register(struct net *net)
 {
        struct ctl_table *table;
index e332efb124cc0c34f93786232353c37dd2e10ea1..efc46ffed1fd63a5fb510046bc6fd013dd99c252 100644 (file)
@@ -573,7 +573,7 @@ void sctp_transport_burst_limited(struct sctp_transport *t)
        u32 old_cwnd = t->cwnd;
        u32 max_burst_bytes;
 
-       if (t->burst_limited)
+       if (t->burst_limited || asoc->max_burst == 0)
                return;
 
        max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
index 0b18693f2be6deb2f6f6b6bbf99aa131c767e830..e83c416708af5554f89c98723bba150b8750b3f0 100644 (file)
@@ -1973,7 +1973,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
        if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
                return -EFAULT;
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-               return -EINVAL;
+               kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        return 0;
 }
 
index 97912b40c254d8a270e18f71e9e5b714e0dbcba8..42fdfc634e568a58bda35d2dbb1effbf44dd1bd4 100644 (file)
@@ -1517,7 +1517,7 @@ out:
 static int
 gss_refresh_null(struct rpc_task *task)
 {
-       return -EACCES;
+       return 0;
 }
 
 static __be32 *
index fd4eeeaa972a6f4226f1dce420d7fb0b17670c78..c6d3f75a9e1bba6f99cff5aed75d8e5a96f94484 100644 (file)
@@ -113,7 +113,6 @@ err:
 static void tipc_core_stop(void)
 {
        tipc_netlink_stop();
-       tipc_handler_stop();
        tipc_cfg_stop();
        tipc_subscr_stop();
        tipc_nametbl_stop();
@@ -146,9 +145,10 @@ static int tipc_core_start(void)
                res = tipc_subscr_start();
        if (!res)
                res = tipc_cfg_init();
-       if (res)
+       if (res) {
+               tipc_handler_stop();
                tipc_core_stop();
-
+       }
        return res;
 }
 
@@ -178,6 +178,7 @@ static int __init tipc_init(void)
 
 static void __exit tipc_exit(void)
 {
+       tipc_handler_stop();
        tipc_core_stop_net();
        tipc_core_stop();
        pr_info("Deactivated\n");
index b36f0fcd9bdfe76d04adf287687190ada3e9ccca..e4bc8a2967447fbde1f39d0d19146f2c7848ac99 100644 (file)
@@ -56,12 +56,13 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument)
 {
        struct queue_item *item;
 
+       spin_lock_bh(&qitem_lock);
        if (!handler_enabled) {
                pr_err("Signal request ignored by handler\n");
+               spin_unlock_bh(&qitem_lock);
                return -ENOPROTOOPT;
        }
 
-       spin_lock_bh(&qitem_lock);
        item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
        if (!item) {
                pr_err("Signal queue out of memory\n");
@@ -112,10 +113,14 @@ void tipc_handler_stop(void)
        struct list_head *l, *n;
        struct queue_item *item;
 
-       if (!handler_enabled)
+       spin_lock_bh(&qitem_lock);
+       if (!handler_enabled) {
+               spin_unlock_bh(&qitem_lock);
                return;
-
+       }
        handler_enabled = 0;
+       spin_unlock_bh(&qitem_lock);
+
        tasklet_kill(&tipc_tasklet);
 
        spin_lock_bh(&qitem_lock);
index 01625ccc3ae64ac3b5b1c664feec7f0136973e04..a427623ee574e88d9926c7972a0650c5c6f9a3eb 100644 (file)
@@ -530,13 +530,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
 static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t, int);
 
-static void unix_set_peek_off(struct sock *sk, int val)
+static int unix_set_peek_off(struct sock *sk, int val)
 {
        struct unix_sock *u = unix_sk(sk);
 
-       mutex_lock(&u->readlock);
+       if (mutex_lock_interruptible(&u->readlock))
+               return -EINTR;
+
        sk->sk_peek_off = val;
        mutex_unlock(&u->readlock);
+
+       return 0;
 }
 
 
@@ -714,7 +718,9 @@ static int unix_autobind(struct socket *sock)
        int err;
        unsigned int retries = 0;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               return err;
 
        err = 0;
        if (u->addr)
@@ -873,7 +879,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        addr_len = err;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               goto out;
 
        err = -EINVAL;
        if (u->addr)
index aff959e5a1b360e7cb467cade7f7d617544b3909..52b865fb7351ac3c221c120bc0cc236687a12513 100644 (file)
@@ -451,6 +451,15 @@ int wiphy_register(struct wiphy *wiphy)
        int i;
        u16 ifmodes = wiphy->interface_modes;
 
+       /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
+       wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
+
+       /*
+        * There are major locking problems in nl80211/mac80211 for CSA,
+        * disable for all drivers until this has been reworked.
+        */
+       wiphy->flags &= ~WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
 #ifdef CONFIG_PM
        if (WARN_ON(wiphy->wowlan &&
                    (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
index 9d797df56649c5a47fdf1f61e665ee31e4b77e7c..89737ee2669a8de9bc8f02aa1c392052369d210b 100644 (file)
@@ -262,7 +262,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 
        /* try to find an IBSS channel if none requested ... */
        if (!wdev->wext.ibss.chandef.chan) {
-               wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+               struct ieee80211_channel *new_chan = NULL;
 
                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                        struct ieee80211_supported_band *sband;
@@ -278,18 +278,19 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
                                        continue;
                                if (chan->flags & IEEE80211_CHAN_DISABLED)
                                        continue;
-                               wdev->wext.ibss.chandef.chan = chan;
-                               wdev->wext.ibss.chandef.center_freq1 =
-                                       chan->center_freq;
+                               new_chan = chan;
                                break;
                        }
 
-                       if (wdev->wext.ibss.chandef.chan)
+                       if (new_chan)
                                break;
                }
 
-               if (!wdev->wext.ibss.chandef.chan)
+               if (!new_chan)
                        return -EINVAL;
+
+               cfg80211_chandef_create(&wdev->wext.ibss.chandef, new_chan,
+                                       NL80211_CHAN_NO_HT);
        }
 
        /* don't join -- SSID is not there */
@@ -363,9 +364,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
                return err;
 
        if (chan) {
-               wdev->wext.ibss.chandef.chan = chan;
-               wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
-               wdev->wext.ibss.chandef.center_freq1 = freq;
+               cfg80211_chandef_create(&wdev->wext.ibss.chandef, chan,
+                                       NL80211_CHAN_NO_HT);
                wdev->wext.ibss.channel_fixed = true;
        } else {
                /* cfg80211_ibss_wext_join will pick one if needed */
index a1eb21073176115a587f9eb1edf5d36dba582484..138dc3bb8b67d8c345531a95ce0c8342271ce79e 100644 (file)
@@ -2687,7 +2687,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_NEW_KEY);
        if (!hdr)
-               return -ENOBUFS;
+               goto nla_put_failure;
 
        cookie.msg = msg;
        cookie.idx = key_idx;
@@ -5349,6 +5349,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                                err = -EINVAL;
                                goto out_free;
                        }
+
+                       if (!wiphy->bands[band])
+                               continue;
+
                        err = ieee80211_get_ratemask(wiphy->bands[band],
                                                     nla_data(attr),
                                                     nla_len(attr),
@@ -9633,8 +9637,9 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
            nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
                goto nla_put_failure;
 
-       if (req->flags)
-               nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+       if (req->flags &&
+           nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
+               goto nla_put_failure;
 
        return 0;
  nla_put_failure:
@@ -11093,6 +11098,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                struct nlattr *reasons;
 
                reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+               if (!reasons)
+                       goto free_msg;
 
                if (wakeup->disconnect &&
                    nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
@@ -11118,16 +11125,18 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                                wakeup->pattern_idx))
                        goto free_msg;
 
-               if (wakeup->tcp_match)
-                       nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH);
+               if (wakeup->tcp_match &&
+                   nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
+                       goto free_msg;
 
-               if (wakeup->tcp_connlost)
-                       nla_put_flag(msg,
-                                    NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST);
+               if (wakeup->tcp_connlost &&
+                   nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
+                       goto free_msg;
 
-               if (wakeup->tcp_nomoretokens)
-                       nla_put_flag(msg,
-                               NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS);
+               if (wakeup->tcp_nomoretokens &&
+                   nla_put_flag(msg,
+                                NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
+                       goto free_msg;
 
                if (wakeup->packet) {
                        u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
@@ -11263,24 +11272,29 @@ void cfg80211_ft_event(struct net_device *netdev,
                return;
 
        hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
-       if (!hdr) {
-               nlmsg_free(msg);
-               return;
-       }
+       if (!hdr)
+               goto out;
 
-       nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
-       nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
-       nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap);
-       if (ft_event->ies)
-               nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
-       if (ft_event->ric_ies)
-               nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
-                       ft_event->ric_ies);
+       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
+               goto out;
+
+       if (ft_event->ies &&
+           nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
+               goto out;
+       if (ft_event->ric_ies &&
+           nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+                   ft_event->ric_ies))
+               goto out;
 
        genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
                                NL80211_MCGRP_MLME, GFP_KERNEL);
+       return;
+ out:
+       nlmsg_free(msg);
 }
 EXPORT_SYMBOL(cfg80211_ft_event);
 
index 32b10f53d0b4cbad76b13ef86d547ad864ae19c2..2dcb37736d8469a0e18e4c1ba262281e3fd8cf37 100644 (file)
@@ -82,7 +82,9 @@ kallsyms()
                kallsymopt="${kallsymopt} --all-symbols"
        fi
 
-       kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
+               kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       fi
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
index d0da66396f6201b5dbce7e8b9aa2ae421aefd40a..91280b82da0874787e6947a18ed8381d1567b483 100755 (executable)
@@ -364,7 +364,8 @@ if ($arch eq "x86_64") {
 } elsif ($arch eq "blackfin") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $mcount_adjust = -4;
-} elsif ($arch eq "tilegx") {
+} elsif ($arch eq "tilegx" || $arch eq "tile") {
+    # Default to the newer TILE-Gx architecture if only "tile" is given.
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $type = ".quad";
     $alignment = 8;
index 5f7a8b663cb9c9eb59b32f4ce63076a6a86914cc..7941fbdfb050e573120f36b770ae8321130d8d01 100644 (file)
 #include <tools/be_byteshift.h>
 #include <tools/le_byteshift.h>
 
+#ifndef EM_ARCOMPACT
+#define EM_ARCOMPACT   93
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64     183
 #endif
@@ -268,6 +272,7 @@ do_file(char const *const fname)
        case EM_S390:
                custom_sort = sort_relative_table;
                break;
+       case EM_ARCOMPACT:
        case EM_ARM:
        case EM_AARCH64:
        case EM_MIPS:
index 77ca965ab684e67e2809dc16f024728d8df41c70..b4af4ebc5be284d7f2665a5266be6a5bf267a683 100644 (file)
@@ -13,9 +13,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/err.h>
-#include <linux/sched.h>
 #include <linux/rbtree.h>
-#include <linux/cred.h>
 #include <linux/key-type.h>
 #include <linux/digsig.h>
 
 
 static struct key *keyring[INTEGRITY_KEYRING_MAX];
 
-#ifdef CONFIG_IMA_TRUSTED_KEYRING
-static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
-       ".evm",
-       ".module",
-       ".ima",
-};
-#else
 static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
        "_evm",
        "_module",
        "_ima",
 };
-#endif
 
 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
                            const char *digest, int digestlen)
@@ -45,7 +35,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
 
        if (!keyring[id]) {
                keyring[id] =
-                   request_key(&key_type_keyring, keyring_name[id], NULL);
+                       request_key(&key_type_keyring, keyring_name[id], NULL);
                if (IS_ERR(keyring[id])) {
                        int err = PTR_ERR(keyring[id]);
                        pr_err("no %s keyring: %d\n", keyring_name[id], err);
@@ -66,21 +56,3 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
 
        return -EOPNOTSUPP;
 }
-
-int integrity_init_keyring(const unsigned int id)
-{
-       const struct cred *cred = current_cred();
-       const struct user_struct *user = cred->user;
-
-       keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
-                                   KGIDT_INIT(0), cred,
-                                   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                                    KEY_USR_VIEW | KEY_USR_READ),
-                                   KEY_ALLOC_NOT_IN_QUOTA, user->uid_keyring);
-       if (!IS_ERR(keyring[id]))
-               set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
-       else
-               pr_info("Can't allocate %s keyring (%ld)\n",
-                       keyring_name[id], PTR_ERR(keyring[id]));
-       return 0;
-}
index dad8d4ca2437fd608b73218993b23c3275c65b8d..81a27971d884215bc20e71d756f6778893ae1d67 100644 (file)
@@ -123,11 +123,3 @@ config IMA_APPRAISE
          For more information on integrity appraisal refer to:
          <http://linux-ima.sourceforge.net>
          If unsure, say N.
-
-config IMA_TRUSTED_KEYRING
-       bool "Require all keys on the _ima keyring be signed"
-       depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
-       default y
-       help
-          This option requires that all keys added to the _ima
-          keyring be signed by a key on the system trusted keyring.
index bf03c6a16cc83ace2f47a3ea7571ef79a63ed1d9..0356e1d437ca31cde30910567128168dbfd0a5ca 100644 (file)
@@ -26,7 +26,8 @@
 
 #include "../integrity.h"
 
-enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
+enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
+                    IMA_SHOW_ASCII };
 enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 
 /* digest size for IMA, fits SHA1 or MD5 */
@@ -97,7 +98,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
                           const char *op, struct inode *inode,
                           const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
-int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
+int ima_calc_field_array_hash(struct ima_field_data *field_data,
+                             struct ima_template_desc *desc, int num_fields,
                              struct ima_digest_data *hash);
 int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
 void ima_add_violation(struct file *file, const unsigned char *filename,
@@ -146,6 +148,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                            int xattr_len, struct ima_template_entry **entry);
 int ima_store_template(struct ima_template_entry *entry, int violation,
                       struct inode *inode, const unsigned char *filename);
+void ima_free_template_entry(struct ima_template_entry *entry);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* rbtree tree calls to lookup, insert, delete
index 0e7540863fc299687877ae4591961b13b60fcaa9..c38bbce8c6a629e246d8f6bef7557e224707d88b 100644 (file)
 #include <crypto/hash_info.h>
 #include "ima.h"
 
+/*
+ * ima_free_template_entry - free an existing template entry
+ */
+void ima_free_template_entry(struct ima_template_entry *entry)
+{
+       int i;
+
+       for (i = 0; i < entry->template_desc->num_fields; i++)
+               kfree(entry->template_data[i].data);
+
+       kfree(entry);
+}
+
 /*
  * ima_alloc_init_template - create and initialize a new template entry
  */
@@ -37,6 +50,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
        if (!*entry)
                return -ENOMEM;
 
+       (*entry)->template_desc = template_desc;
        for (i = 0; i < template_desc->num_fields; i++) {
                struct ima_template_field *field = template_desc->fields[i];
                u32 len;
@@ -51,10 +65,9 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                (*entry)->template_data_len += sizeof(len);
                (*entry)->template_data_len += len;
        }
-       (*entry)->template_desc = template_desc;
        return 0;
 out:
-       kfree(*entry);
+       ima_free_template_entry(*entry);
        *entry = NULL;
        return result;
 }
@@ -94,6 +107,7 @@ int ima_store_template(struct ima_template_entry *entry,
                /* this function uses default algo */
                hash.hdr.algo = HASH_ALGO_SHA1;
                result = ima_calc_field_array_hash(&entry->template_data[0],
+                                                  entry->template_desc,
                                                   num_fields, &hash.hdr);
                if (result < 0) {
                        integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
@@ -133,7 +147,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
        }
        result = ima_store_template(entry, violation, inode, filename);
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
 err_out:
        integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
                            op, cause, result, 0);
@@ -268,7 +282,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        if (!result || result == -EEXIST)
                iint->flags |= IMA_MEASURED;
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
 }
 
 void ima_audit_measurement(struct integrity_iint_cache *iint,
index 46353ee517f6f321a738b067584d7e62dd8872fe..734e9468aca01c9a3724a57136f6d8bf371951f3 100644 (file)
@@ -381,14 +381,3 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
        }
        return result;
 }
-
-#ifdef CONFIG_IMA_TRUSTED_KEYRING
-static int __init init_ima_keyring(void)
-{
-       int ret;
-
-       ret = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
-       return 0;
-}
-late_initcall(init_ima_keyring);
-#endif
index 676e0292dfecf6744b720b8a7e103415b924cc37..fdf60def52e90c93799e7d6ff6298ab4dd68c6d3 100644 (file)
@@ -140,6 +140,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
  * Calculate the hash of template data
  */
 static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
+                                        struct ima_template_desc *td,
                                         int num_fields,
                                         struct ima_digest_data *hash,
                                         struct crypto_shash *tfm)
@@ -160,9 +161,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
                return rc;
 
        for (i = 0; i < num_fields; i++) {
-               rc = crypto_shash_update(&desc.shash,
-                                        (const u8 *) &field_data[i].len,
-                                        sizeof(field_data[i].len));
+               if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
+                       rc = crypto_shash_update(&desc.shash,
+                                               (const u8 *) &field_data[i].len,
+                                               sizeof(field_data[i].len));
+                       if (rc)
+                               break;
+               }
                rc = crypto_shash_update(&desc.shash, field_data[i].data,
                                         field_data[i].len);
                if (rc)
@@ -175,7 +180,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
        return rc;
 }
 
-int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
+int ima_calc_field_array_hash(struct ima_field_data *field_data,
+                             struct ima_template_desc *desc, int num_fields,
                              struct ima_digest_data *hash)
 {
        struct crypto_shash *tfm;
@@ -185,7 +191,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
-       rc = ima_calc_field_array_hash_tfm(field_data, num_fields, hash, tfm);
+       rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields,
+                                          hash, tfm);
 
        ima_free_tfm(tfm);
 
index d47a7c86a21d0d94f6c41933fd18311e553dafce..db01125926bdb1e696165389bcdd26117e9d25fc 100644 (file)
@@ -120,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v)
        struct ima_template_entry *e;
        int namelen;
        u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+       bool is_ima_template = false;
        int i;
 
        /* get entry */
@@ -145,14 +146,21 @@ static int ima_measurements_show(struct seq_file *m, void *v)
        ima_putc(m, e->template_desc->name, namelen);
 
        /* 5th:  template length (except for 'ima' template) */
-       if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
+       if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0)
+               is_ima_template = true;
+
+       if (!is_ima_template)
                ima_putc(m, &e->template_data_len,
                         sizeof(e->template_data_len));
 
        /* 6th:  template specific data */
        for (i = 0; i < e->template_desc->num_fields; i++) {
-               e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY,
-                                                       &e->template_data[i]);
+               enum ima_show_type show = IMA_SHOW_BINARY;
+               struct ima_template_field *field = e->template_desc->fields[i];
+
+               if (is_ima_template && strcmp(field->field_id, "d") == 0)
+                       show = IMA_SHOW_BINARY_NO_FIELD_LEN;
+               field->field_show(m, show, &e->template_data[i]);
        }
        return 0;
 }
index 15f34bd40abed1530216be53c59658b6245d280b..37122768554a9e69d4866f9c9a72864f157afef3 100644 (file)
@@ -63,7 +63,6 @@ static void __init ima_add_boot_aggregate(void)
                result = ima_calc_boot_aggregate(&hash.hdr);
                if (result < 0) {
                        audit_cause = "hashing_error";
-                       kfree(entry);
                        goto err_out;
                }
        }
@@ -76,7 +75,7 @@ static void __init ima_add_boot_aggregate(void)
        result = ima_store_template(entry, violation, NULL,
                                    boot_aggregate_name);
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
        return;
 err_out:
        integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
index 4e5da990630beca2c179894db96fd9f20d31bc17..635695f6a185a1d24ee3d1bfb05d4f7ebe8cedb0 100644 (file)
@@ -90,7 +90,7 @@ static struct ima_template_field *lookup_template_field(const char *field_id)
        return NULL;
 }
 
-static int template_fmt_size(char *template_fmt)
+static int template_fmt_size(const char *template_fmt)
 {
        char c;
        int template_fmt_len = strlen(template_fmt);
@@ -106,22 +106,29 @@ static int template_fmt_size(char *template_fmt)
        return j + 1;
 }
 
-static int template_desc_init_fields(char *template_fmt,
+static int template_desc_init_fields(const char *template_fmt,
                                     struct ima_template_field ***fields,
                                     int *num_fields)
 {
-       char *c, *template_fmt_ptr = template_fmt;
+       char *c, *template_fmt_copy, *template_fmt_ptr;
        int template_num_fields = template_fmt_size(template_fmt);
        int i, result = 0;
 
        if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX)
                return -EINVAL;
 
+       /* copying is needed as strsep() modifies the original buffer */
+       template_fmt_copy = kstrdup(template_fmt, GFP_KERNEL);
+       if (template_fmt_copy == NULL)
+               return -ENOMEM;
+
        *fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL);
        if (*fields == NULL) {
                result = -ENOMEM;
                goto out;
        }
+
+       template_fmt_ptr = template_fmt_copy;
        for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL &&
             i < template_num_fields; i++) {
                struct ima_template_field *f = lookup_template_field(c);
@@ -133,10 +140,12 @@ static int template_desc_init_fields(char *template_fmt,
                (*fields)[i] = f;
        }
        *num_fields = i;
-       return 0;
 out:
-       kfree(*fields);
-       *fields = NULL;
+       if (result < 0) {
+               kfree(*fields);
+               *fields = NULL;
+       }
+       kfree(template_fmt_copy);
        return result;
 }
 
index 6d66ad6ed265f8f6422c0d9d7f7a64aa732f0779..c38adcc910fbb91f2c6f34255c3940b257bd7f35 100644 (file)
@@ -109,9 +109,12 @@ static void ima_show_template_data_binary(struct seq_file *m,
                                          enum data_formats datafmt,
                                          struct ima_field_data *field_data)
 {
-       ima_putc(m, &field_data->len, sizeof(u32));
+       if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
+               ima_putc(m, &field_data->len, sizeof(u32));
+
        if (!field_data->len)
                return;
+
        ima_putc(m, field_data->data, field_data->len);
 }
 
@@ -125,6 +128,7 @@ static void ima_show_template_field_data(struct seq_file *m,
                ima_show_template_data_ascii(m, show, datafmt, field_data);
                break;
        case IMA_SHOW_BINARY:
+       case IMA_SHOW_BINARY_NO_FIELD_LEN:
                ima_show_template_data_binary(m, show, datafmt, field_data);
                break;
        default:
index b9e7c133734a2dc5796fe98f5c15f8c81ebc5d26..2fb5e53e927f2bf5432a34af1251c89f359d90f7 100644 (file)
@@ -137,19 +137,12 @@ static inline int integrity_digsig_verify(const unsigned int id,
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
 int asymmetric_verify(struct key *keyring, const char *sig,
                      int siglen, const char *data, int datalen);
-
-int integrity_init_keyring(const unsigned int id);
 #else
 static inline int asymmetric_verify(struct key *keyring, const char *sig,
                                    int siglen, const char *data, int datalen)
 {
        return -EOPNOTSUPP;
 }
-
-static int integrity_init_keyring(const unsigned int id)
-{
-       return 0;
-}
 #endif
 
 #ifdef CONFIG_INTEGRITY_AUDIT
index 7f44c3207a9bb95982d3bb41990568c41f64c54e..8137b27d641dad9080df66c829f8109472dbccc6 100644 (file)
@@ -70,7 +70,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
                 *
                 * TODO: Encrypt the stored data with a temporary key.
                 */
-               file = shmem_file_setup("", datalen, 0);
+               file = shmem_kernel_file_setup("", datalen, 0);
                if (IS_ERR(file)) {
                        ret = PTR_ERR(file);
                        goto err_quota;
index 55d110f0acedc96d17bcc5f5903aaa743ed6cb32..6e21c11e48bc1cd434664d28f83084b54db50bd6 100644 (file)
@@ -272,7 +272,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        }
 
        /* allocate and initialise the key and its description */
-       key = kmem_cache_alloc(key_jar, GFP_KERNEL);
+       key = kmem_cache_zalloc(key_jar, GFP_KERNEL);
        if (!key)
                goto no_memory_2;
 
@@ -293,18 +293,12 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        key->uid = uid;
        key->gid = gid;
        key->perm = perm;
-       key->flags = 0;
-       key->expiry = 0;
-       key->payload.data = NULL;
-       key->security = NULL;
 
        if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
                key->flags |= 1 << KEY_FLAG_IN_QUOTA;
        if (flags & KEY_ALLOC_TRUSTED)
                key->flags |= 1 << KEY_FLAG_TRUSTED;
 
-       memset(&key->type_data, 0, sizeof(key->type_data));
-
 #ifdef KEY_DEBUGGING
        key->magic = KEY_DEBUG_MAGIC;
 #endif
index 69f0cb7bab7e873f8d8997d71db7c42430f72ce6..d46cbc5e335e9c330ccd74a08fcbf78aeafe8c96 100644 (file)
@@ -160,7 +160,7 @@ static u64 mult_64x32_and_fold(u64 x, u32 y)
 static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key)
 {
        const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;
-       const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK;
+       const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK;
        const char *description = index_key->description;
        unsigned long hash, type;
        u32 piece;
@@ -194,10 +194,10 @@ static unsigned long hash_key_type_and_desc(const struct keyring_index_key *inde
         * ordinary keys by making sure the lowest level segment in the hash is
         * zero for keyrings and non-zero otherwise.
         */
-       if (index_key->type != &key_type_keyring && (hash & level_mask) == 0)
+       if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0)
                return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1;
-       if (index_key->type == &key_type_keyring && (hash & level_mask) != 0)
-               return (hash + (hash << level_shift)) & ~level_mask;
+       if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0)
+               return (hash + (hash << level_shift)) & ~fan_mask;
        return hash;
 }
 
@@ -279,12 +279,11 @@ static bool keyring_compare_object(const void *object, const void *data)
  * Compare the index keys of a pair of objects and determine the bit position
  * at which they differ - if they differ.
  */
-static int keyring_diff_objects(const void *_a, const void *_b)
+static int keyring_diff_objects(const void *object, const void *data)
 {
-       const struct key *key_a = keyring_ptr_to_key(_a);
-       const struct key *key_b = keyring_ptr_to_key(_b);
+       const struct key *key_a = keyring_ptr_to_key(object);
        const struct keyring_index_key *a = &key_a->index_key;
-       const struct keyring_index_key *b = &key_b->index_key;
+       const struct keyring_index_key *b = data;
        unsigned long seg_a, seg_b;
        int level, i;
 
@@ -691,8 +690,8 @@ descend_to_node:
                smp_read_barrier_depends();
                ptr = ACCESS_ONCE(shortcut->next_node);
                BUG_ON(!assoc_array_ptr_is_node(ptr));
-               node = assoc_array_ptr_to_node(ptr);
        }
+       node = assoc_array_ptr_to_node(ptr);
 
 begin_node:
        kdebug("begin_node");
index 794c3ca49eac92998caa17be71a4bdc472c2e9c8..6625699f497c7f3889f7b82b325a315c9e51774a 100644 (file)
@@ -53,6 +53,7 @@
 #include <net/ip.h>            /* for local_port_range[] */
 #include <net/sock.h>
 #include <net/tcp.h>           /* struct or_callable used in sock_rcv_skb */
+#include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
 #include <linux/uaccess.h>
 #include "audit.h"
 #include "avc_ss.h"
 
-#define SB_TYPE_FMT "%s%s%s"
-#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
-#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
-
 extern struct security_operations *security_ops;
 
 /* SECMARK reference count */
@@ -413,8 +410,8 @@ static int sb_finish_set_opts(struct super_block *sb)
                   the first boot of the SELinux kernel before we have
                   assigned xattr values to the filesystem. */
                if (!root_inode->i_op->getxattr) {
-                       printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
-                              "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
+                       printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
+                              "xattr support\n", sb->s_id, sb->s_type->name);
                        rc = -EOPNOTSUPP;
                        goto out;
                }
@@ -422,22 +419,22 @@ static int sb_finish_set_opts(struct super_block *sb)
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
-                                      SB_TYPE_FMT") has no security xattr handler\n",
-                                      sb->s_id, SB_TYPE_ARGS(sb));
+                                      "%s) has no security xattr handler\n",
+                                      sb->s_id, sb->s_type->name);
                        else
                                printk(KERN_WARNING "SELinux: (dev %s, type "
-                                      SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
-                                      SB_TYPE_ARGS(sb), -rc);
+                                      "%s) getxattr errno %d\n", sb->s_id,
+                                      sb->s_type->name, -rc);
                        goto out;
                }
        }
 
        if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
-               printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
-                      sb->s_id, SB_TYPE_ARGS(sb));
+               printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
+                      sb->s_id, sb->s_type->name);
        else
-               printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
-                      sb->s_id, SB_TYPE_ARGS(sb),
+               printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
+                      sb->s_id, sb->s_type->name,
                       labeling_behaviors[sbsec->behavior-1]);
 
        sbsec->flags |= SE_SBINITIALIZED;
@@ -600,6 +597,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
        const struct cred *cred = current_cred();
        int rc = 0, i;
        struct superblock_security_struct *sbsec = sb->s_security;
+       const char *name = sb->s_type->name;
        struct inode *inode = sbsec->sb->s_root->d_inode;
        struct inode_security_struct *root_isec = inode->i_security;
        u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -658,8 +656,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                                             strlen(mount_options[i]), &sid);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
-                              "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
-                              mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
+                              "(%s) failed for (dev %s, type %s) errno=%d\n",
+                              mount_options[i], sb->s_id, name, rc);
                        goto out;
                }
                switch (flags[i]) {
@@ -806,8 +804,7 @@ out:
 out_double_mount:
        rc = -EINVAL;
        printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, different "
-              "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
-              SB_TYPE_ARGS(sb));
+              "security settings for (dev %s, type %s)\n", sb->s_id, name);
        goto out;
 }
 
@@ -2480,8 +2477,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
                rc = security_context_to_sid(mount_options[i], len, &sid);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
-                              "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
-                              mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
+                              "(%s) failed for (dev %s, type %s) errno=%d\n",
+                              mount_options[i], sb->s_id, sb->s_type->name, rc);
                        goto out_free_opts;
                }
                rc = -EINVAL;
@@ -2519,8 +2516,8 @@ out_free_secdata:
        return rc;
 out_bad_option:
        printk(KERN_WARNING "SELinux: unable to change security options "
-              "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
-              SB_TYPE_ARGS(sb));
+              "during remount (dev %s, type=%s)\n", sb->s_id,
+              sb->s_type->name);
        goto out_free_opts;
 }
 
@@ -3828,7 +3825,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        u32 nlbl_sid;
        u32 nlbl_type;
 
-       err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+       err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
        if (unlikely(err))
                return -EACCES;
        err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
@@ -3846,6 +3843,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        return 0;
 }
 
+/**
+ * selinux_conn_sid - Determine the child socket label for a connection
+ * @sk_sid: the parent socket's SID
+ * @skb_sid: the packet's SID
+ * @conn_sid: the resulting connection SID
+ *
+ * If @skb_sid is valid then the user:role:type information from @sk_sid is
+ * combined with the MLS information from @skb_sid in order to create
+ * @conn_sid.  If @skb_sid is not valid then then @conn_sid is simply a copy
+ * of @sk_sid.  Returns zero on success, negative values on failure.
+ *
+ */
+static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
+{
+       int err = 0;
+
+       if (skb_sid != SECSID_NULL)
+               err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
+       else
+               *conn_sid = sk_sid;
+
+       return err;
+}
+
 /* socket security operations */
 
 static int socket_sockcreate_sid(const struct task_security_struct *tsec,
@@ -4313,8 +4334,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
-               if (err)
+               if (err) {
                        selinux_netlbl_err(skb, err, 0);
+                       return err;
+               }
        }
 
        if (secmark_active) {
@@ -4452,7 +4475,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
        struct sk_security_struct *sksec = sk->sk_security;
        int err;
        u16 family = sk->sk_family;
-       u32 newsid;
+       u32 connsid;
        u32 peersid;
 
        /* handle mapped IPv4 packets arriving via IPv6 sockets */
@@ -4462,16 +4485,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
        err = selinux_skb_peerlbl_sid(skb, family, &peersid);
        if (err)
                return err;
-       if (peersid == SECSID_NULL) {
-               req->secid = sksec->sid;
-               req->peer_secid = SECSID_NULL;
-       } else {
-               err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
-               if (err)
-                       return err;
-               req->secid = newsid;
-               req->peer_secid = peersid;
-       }
+       err = selinux_conn_sid(sksec->sid, peersid, &connsid);
+       if (err)
+               return err;
+       req->secid = connsid;
+       req->peer_secid = peersid;
 
        return selinux_netlbl_inet_conn_request(req, family);
 }
@@ -4731,6 +4749,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
 static unsigned int selinux_ip_output(struct sk_buff *skb,
                                      u16 family)
 {
+       struct sock *sk;
        u32 sid;
 
        if (!netlbl_enabled())
@@ -4739,8 +4758,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
        /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
         * because we want to make sure we apply the necessary labeling
         * before IPsec is applied so we can leverage AH protection */
-       if (skb->sk) {
-               struct sk_security_struct *sksec = skb->sk->sk_security;
+       sk = skb->sk;
+       if (sk) {
+               struct sk_security_struct *sksec;
+
+               if (sk->sk_state == TCP_LISTEN)
+                       /* if the socket is the listening state then this
+                        * packet is a SYN-ACK packet which means it needs to
+                        * be labeled based on the connection/request_sock and
+                        * not the parent socket.  unfortunately, we can't
+                        * lookup the request_sock yet as it isn't queued on
+                        * the parent socket until after the SYN-ACK is sent.
+                        * the "solution" is to simply pass the packet as-is
+                        * as any IP option based labeling should be copied
+                        * from the initial connection request (in the IP
+                        * layer).  it is far from ideal, but until we get a
+                        * security label in the packet itself this is the
+                        * best we can do. */
+                       return NF_ACCEPT;
+
+               /* standard practice, label using the parent socket */
+               sksec = sk->sk_security;
                sid = sksec->sid;
        } else
                sid = SECINITSID_KERNEL;
@@ -4810,27 +4848,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
         * as fast and as clean as possible. */
        if (!selinux_policycap_netpeer)
                return selinux_ip_postroute_compat(skb, ifindex, family);
+
+       secmark_active = selinux_secmark_enabled();
+       peerlbl_active = selinux_peerlbl_enabled();
+       if (!secmark_active && !peerlbl_active)
+               return NF_ACCEPT;
+
+       sk = skb->sk;
+
 #ifdef CONFIG_XFRM
        /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
         * packet transformation so allow the packet to pass without any checks
         * since we'll have another chance to perform access control checks
         * when the packet is on it's final way out.
         * NOTE: there appear to be some IPv6 multicast cases where skb->dst
-        *       is NULL, in this case go ahead and apply access control. */
-       if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
+        *       is NULL, in this case go ahead and apply access control.
+        * NOTE: if this is a local socket (skb->sk != NULL) that is in the
+        *       TCP listening state we cannot wait until the XFRM processing
+        *       is done as we will miss out on the SA label if we do;
+        *       unfortunately, this means more work, but it is only once per
+        *       connection. */
+       if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
+           !(sk != NULL && sk->sk_state == TCP_LISTEN))
                return NF_ACCEPT;
 #endif
-       secmark_active = selinux_secmark_enabled();
-       peerlbl_active = selinux_peerlbl_enabled();
-       if (!secmark_active && !peerlbl_active)
-               return NF_ACCEPT;
 
-       /* if the packet is being forwarded then get the peer label from the
-        * packet itself; otherwise check to see if it is from a local
-        * application or the kernel, if from an application get the peer label
-        * from the sending socket, otherwise use the kernel's sid */
-       sk = skb->sk;
        if (sk == NULL) {
+               /* Without an associated socket the packet is either coming
+                * from the kernel or it is being forwarded; check the packet
+                * to determine which and if the packet is being forwarded
+                * query the packet directly to determine the security label. */
                if (skb->skb_iif) {
                        secmark_perm = PACKET__FORWARD_OUT;
                        if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
@@ -4839,7 +4886,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
                        secmark_perm = PACKET__SEND;
                        peer_sid = SECINITSID_KERNEL;
                }
+       } else if (sk->sk_state == TCP_LISTEN) {
+               /* Locally generated packet but the associated socket is in the
+                * listening state which means this is a SYN-ACK packet.  In
+                * this particular case the correct security label is assigned
+                * to the connection/request_sock but unfortunately we can't
+                * query the request_sock as it isn't queued on the parent
+                * socket until after the SYN-ACK packet is sent; the only
+                * viable choice is to regenerate the label like we do in
+                * selinux_inet_conn_request().  See also selinux_ip_output()
+                * for similar problems. */
+               u32 skb_sid;
+               struct sk_security_struct *sksec = sk->sk_security;
+               if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
+                       return NF_DROP;
+               /* At this point, if the returned skb peerlbl is SECSID_NULL
+                * and the packet has been through at least one XFRM
+                * transformation then we must be dealing with the "final"
+                * form of labeled IPsec packet; since we've already applied
+                * all of our access controls on this packet we can safely
+                * pass the packet. */
+               if (skb_sid == SECSID_NULL) {
+                       switch (family) {
+                       case PF_INET:
+                               if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
+                                       return NF_ACCEPT;
+                               break;
+                       case PF_INET6:
+                               if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
+                                       return NF_ACCEPT;
+                       default:
+                               return NF_DROP_ERR(-ECONNREFUSED);
+                       }
+               }
+               if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
+                       return NF_DROP;
+               secmark_perm = PACKET__SEND;
        } else {
+               /* Locally generated packet, fetch the security label from the
+                * associated socket. */
                struct sk_security_struct *sksec = sk->sk_security;
                peer_sid = sksec->sid;
                secmark_perm = PACKET__SEND;
@@ -5503,11 +5588,11 @@ static int selinux_setprocattr(struct task_struct *p,
                /* Check for ptracing, and update the task SID if ok.
                   Otherwise, leave SID unchanged and fail. */
                ptsid = 0;
-               task_lock(p);
+               rcu_read_lock();
                tracer = ptrace_parent(p);
                if (tracer)
                        ptsid = task_sid(tracer);
-               task_unlock(p);
+               rcu_read_unlock();
 
                if (tracer) {
                        error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
index 0dec76c64cf53853d0eea6aac983db307c8636b8..48c3cc94c1681718a78e6793c7e961e2d404f3fb 100644 (file)
@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
 int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
                                struct common_audit_data *ad, u8 proto);
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid);
 
 static inline void selinux_xfrm_notify_policyload(void)
 {
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
 static inline void selinux_xfrm_notify_policyload(void)
 {
 }
-#endif
 
-static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
 {
-       return selinux_xfrm_decode_session(skb, sid, 0);
+       *sid = SECSID_NULL;
+       return 0;
 }
+#endif
 
 #endif /* _SELINUX_XFRM_H_ */
index ee470a0b5c27fdad95a59b258792b6182435b999..d106733ad9878d6ee7543ff31c05a51f2c74b523 100644 (file)
@@ -2334,50 +2334,16 @@ int security_fs_use(struct super_block *sb)
        struct ocontext *c;
        struct superblock_security_struct *sbsec = sb->s_security;
        const char *fstype = sb->s_type->name;
-       const char *subtype = (sb->s_subtype && sb->s_subtype[0]) ? sb->s_subtype : NULL;
-       struct ocontext *base = NULL;
 
        read_lock(&policy_rwlock);
 
-       for (c = policydb.ocontexts[OCON_FSUSE]; c; c = c->next) {
-               char *sub;
-               int baselen;
-
-               baselen = strlen(fstype);
-
-               /* if base does not match, this is not the one */
-               if (strncmp(fstype, c->u.name, baselen))
-                       continue;
-
-               /* if there is no subtype, this is the one! */
-               if (!subtype)
-                       break;
-
-               /* skip past the base in this entry */
-               sub = c->u.name + baselen;
-
-               /* entry is only a base. save it. keep looking for subtype */
-               if (sub[0] == '\0') {
-                       base = c;
-                       continue;
-               }
-
-               /* entry is not followed by a subtype, so it is not a match */
-               if (sub[0] != '.')
-                       continue;
-
-               /* whew, we found a subtype of this fstype */
-               sub++; /* move past '.' */
-
-               /* exact match of fstype AND subtype */
-               if (!strcmp(subtype, sub))
+       c = policydb.ocontexts[OCON_FSUSE];
+       while (c) {
+               if (strcmp(fstype, c->u.name) == 0)
                        break;
+               c = c->next;
        }
 
-       /* in case we had found an fstype match but no subtype match */
-       if (!c)
-               c = base;
-
        if (c) {
                sbsec->behavior = c->v.behavior;
                if (!c->sid[0]) {
index a91d205ec0c6094cc9a0fecb5d427d4d24b1ed9a..0462cb3ff0a741a36b279dcef37ee784e8520c5c 100644 (file)
@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
                            NULL) ? 0 : 1);
 }
 
-/*
- * LSM hook implementation that checks and/or returns the xfrm sid for the
- * incoming packet.
- */
-int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
 {
-       u32 sid_session = SECSID_NULL;
-       struct sec_path *sp;
+       struct dst_entry *dst = skb_dst(skb);
+       struct xfrm_state *x;
 
-       if (skb == NULL)
-               goto out;
+       if (dst == NULL)
+               return SECSID_NULL;
+       x = dst->xfrm;
+       if (x == NULL || !selinux_authorizable_xfrm(x))
+               return SECSID_NULL;
+
+       return x->security->ctx_sid;
+}
+
+static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
+                                       u32 *sid, int ckall)
+{
+       u32 sid_session = SECSID_NULL;
+       struct sec_path *sp = skb->sp;
 
-       sp = skb->sp;
        if (sp) {
                int i;
 
@@ -247,6 +254,30 @@ out:
        return 0;
 }
 
+/*
+ * LSM hook implementation that checks and/or returns the xfrm sid for the
+ * incoming packet.
+ */
+int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+{
+       if (skb == NULL) {
+               *sid = SECSID_NULL;
+               return 0;
+       }
+       return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
+}
+
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
+{
+       int rc;
+
+       rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
+       if (rc == 0 && *sid == SECSID_NULL)
+               *sid = selinux_xfrm_skb_sid_egress(skb);
+
+       return rc;
+}
+
 /*
  * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
  */
@@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
                return rc;
 
        ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
-       if (!ctx)
-               return -ENOMEM;
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto out;
+       }
 
        ctx->ctx_doi = XFRM_SC_DOI_LSM;
        ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
        ctx->ctx_sid = secid;
        ctx->ctx_len = str_len;
        memcpy(ctx->ctx_str, ctx_str, str_len);
-       kfree(ctx_str);
 
        x->security = ctx;
        atomic_inc(&selinux_xfrm_refcount);
-       return 0;
+out:
+       kfree(ctx_str);
+       return rc;
 }
 
 /*
index 1ca8dc2ccb89f21cb0d102d2d4cd4cc0c74e4bf0..c421fdb3c7a12bf76a2584c21831913e57455ce9 100644 (file)
@@ -753,7 +753,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
  * Power Management.
  */
 #ifdef CONFIG_PM
-static int aaci_do_suspend(struct snd_card *card, unsigned int state)
+static int aaci_do_suspend(struct snd_card *card)
 {
        struct aaci *aaci = card->private_data;
        snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
@@ -761,28 +761,28 @@ static int aaci_do_suspend(struct snd_card *card, unsigned int state)
        return 0;
 }
 
-static int aaci_do_resume(struct snd_card *card, unsigned int state)
+static int aaci_do_resume(struct snd_card *card)
 {
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
 
-static int aaci_suspend(struct amba_device *dev, pm_message_t state)
+static int aaci_suspend(struct device *dev)
 {
-       struct snd_card *card = amba_get_drvdata(dev);
+       struct snd_card *card = dev_get_drvdata(dev);
        return card ? aaci_do_suspend(card) : 0;
 }
 
-static int aaci_resume(struct amba_device *dev)
+static int aaci_resume(struct device *dev)
 {
-       struct snd_card *card = amba_get_drvdata(dev);
+       struct snd_card *card = dev_get_drvdata(dev);
        return card ? aaci_do_resume(card) : 0;
 }
+
+static SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);
+#define AACI_DEV_PM_OPS (&aaci_dev_pm_ops)
 #else
-#define aaci_do_suspend                NULL
-#define aaci_do_resume         NULL
-#define aaci_suspend           NULL
-#define aaci_resume            NULL
+#define AACI_DEV_PM_OPS NULL
 #endif
 
 
@@ -1100,11 +1100,10 @@ MODULE_DEVICE_TABLE(amba, aaci_ids);
 static struct amba_driver aaci_driver = {
        .drv            = {
                .name   = DRIVER_NAME,
+               .pm     = AACI_DEV_PM_OPS,
        },
        .probe          = aaci_probe,
        .remove         = aaci_remove,
-       .suspend        = aaci_suspend,
-       .resume         = aaci_resume,
        .id_table       = aaci_ids,
 };
 
index 872d59e35ee23583cc60a2be24afa5ba1bf3c88d..3519518e25a09612c71f1888bc097e9f088ca6ee 100644 (file)
@@ -354,10 +354,11 @@ static int set_sample_rates(struct atmel_abdac *dac)
        /* we start at 192 kHz and work our way down to 5112 Hz */
        while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
                new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
-               if (new_rate < 0)
+               if (new_rate <= 0)
                        break;
                /* make sure we are below the ABDAC clock */
-               if (new_rate <= clk_get_rate(dac->pclk)) {
+               if (index < MAX_NUM_RATES &&
+                   new_rate <= clk_get_rate(dac->pclk)) {
                        dac->rates[index] = new_rate / 256;
                        index++;
                }
index 5e890cfed42363e1aa1b1ebfbfba76d0d16f0326..394a38909f6b04ef26a5a9f6682f76c294b04c33 100644 (file)
@@ -10,14 +10,12 @@ snd-$(CONFIG_SND_VMASTER) += vmaster.o
 snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o
 snd-$(CONFIG_SND_JACK)   += jack.o
 
-snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
-               pcm_memory.o
+snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
+               pcm_memory.o memalloc.o
+snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
 
 snd-pcm-dmaengine-objs := pcm_dmaengine.o
 
-snd-page-alloc-y := memalloc.o
-snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
-
 snd-rawmidi-objs  := rawmidi.o
 snd-timer-objs    := timer.o
 snd-hrtimer-objs  := hrtimer.o
@@ -31,7 +29,7 @@ obj-$(CONFIG_SND_HWDEP)               += snd-hwdep.o
 obj-$(CONFIG_SND_TIMER)                += snd-timer.o
 obj-$(CONFIG_SND_HRTIMER)      += snd-hrtimer.o
 obj-$(CONFIG_SND_RTCTIMER)     += snd-rtctimer.o
-obj-$(CONFIG_SND_PCM)          += snd-pcm.o snd-page-alloc.o
+obj-$(CONFIG_SND_PCM)          += snd-pcm.o
 obj-$(CONFIG_SND_DMAENGINE_PCM)        += snd-pcm-dmaengine.o
 obj-$(CONFIG_SND_RAWMIDI)      += snd-rawmidi.o
 
index 9d518ac73eea064a6b4d918d3dba072cb50102f5..7a20897d33dbc1147b381ca6884f87dc88eb7ff1 100644 (file)
@@ -501,9 +501,6 @@ static int snd_compress_check_input(struct snd_compr_params *params)
        if (params->codec.ch_in == 0 || params->codec.ch_out == 0)
                return -EINVAL;
 
-       if (!(params->codec.sample_rate & SNDRV_PCM_RATE_8000_192000))
-               return -EINVAL;
-
        return 0;
 }
 
index 5e1c7bc73b290b8dba62f6f598eb765ebf054a7f..4595f93d151e0e5fb82073a788ebe6a725826296 100644 (file)
  *
  */
 
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
 #include <linux/dma-mapping.h>
 #include <linux/genalloc.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
 #include <sound/memalloc.h>
 
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Memory allocator for ALSA system.");
-MODULE_LICENSE("GPL");
-
-
-/*
- */
-
-static DEFINE_MUTEX(list_mutex);
-static LIST_HEAD(mem_list_head);
-
-/* buffer preservation list */
-struct snd_mem_list {
-       struct snd_dma_buffer buffer;
-       unsigned int id;
-       struct list_head list;
-};
-
-/* id for pre-allocated buffers */
-#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
-
 /*
  *
  *  Generic memory allocators
  *
  */
 
-static long snd_allocated_pages; /* holding the number of allocated pages */
-
-static inline void inc_snd_pages(int order)
-{
-       snd_allocated_pages += 1 << order;
-}
-
-static inline void dec_snd_pages(int order)
-{
-       snd_allocated_pages -= 1 << order;
-}
-
 /**
  * snd_malloc_pages - allocate pages with the given size
  * @size: the size to allocate in bytes
@@ -87,7 +45,6 @@ static inline void dec_snd_pages(int order)
 void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
 {
        int pg;
-       void *res;
 
        if (WARN_ON(!size))
                return NULL;
@@ -95,9 +52,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
                return NULL;
        gfp_flags |= __GFP_COMP;        /* compound page lets parts be mapped */
        pg = get_order(size);
-       if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
-               inc_snd_pages(pg);
-       return res;
+       return (void *) __get_free_pages(gfp_flags, pg);
 }
 
 /**
@@ -114,7 +69,6 @@ void snd_free_pages(void *ptr, size_t size)
        if (ptr == NULL)
                return;
        pg = get_order(size);
-       dec_snd_pages(pg);
        free_pages((unsigned long) ptr, pg);
 }
 
@@ -129,7 +83,6 @@ void snd_free_pages(void *ptr, size_t size)
 static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
 {
        int pg;
-       void *res;
        gfp_t gfp_flags;
 
        if (WARN_ON(!dma))
@@ -139,11 +92,7 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
                | __GFP_COMP    /* compound page lets parts be mapped */
                | __GFP_NORETRY /* don't trigger OOM-killer */
                | __GFP_NOWARN; /* no stack trace print - this call is non-critical */
-       res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
-       if (res != NULL)
-               inc_snd_pages(pg);
-
-       return res;
+       return dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
 }
 
 /* free the coherent DMA pages */
@@ -155,7 +104,6 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
        if (ptr == NULL)
                return;
        pg = get_order(size);
-       dec_snd_pages(pg);
        dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
 }
 
@@ -340,256 +288,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
        }
 }
 
-
-/**
- * snd_dma_get_reserved - get the reserved buffer for the given device
- * @dmab: the buffer allocation record to store
- * @id: the buffer id
- *
- * Looks for the reserved-buffer list and re-uses if the same buffer
- * is found in the list.  When the buffer is found, it's removed from the free list.
- *
- * Return: The size of buffer if the buffer is found, or zero if not found.
- */
-size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
-{
-       struct snd_mem_list *mem;
-
-       if (WARN_ON(!dmab))
-               return 0;
-
-       mutex_lock(&list_mutex);
-       list_for_each_entry(mem, &mem_list_head, list) {
-               if (mem->id == id &&
-                   (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
-                    ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
-                       struct device *dev = dmab->dev.dev;
-                       list_del(&mem->list);
-                       *dmab = mem->buffer;
-                       if (dmab->dev.dev == NULL)
-                               dmab->dev.dev = dev;
-                       kfree(mem);
-                       mutex_unlock(&list_mutex);
-                       return dmab->bytes;
-               }
-       }
-       mutex_unlock(&list_mutex);
-       return 0;
-}
-
-/**
- * snd_dma_reserve_buf - reserve the buffer
- * @dmab: the buffer to reserve
- * @id: the buffer id
- *
- * Reserves the given buffer as a reserved buffer.
- *
- * Return: Zero if successful, or a negative code on error.
- */
-int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
-{
-       struct snd_mem_list *mem;
-
-       if (WARN_ON(!dmab))
-               return -EINVAL;
-       mem = kmalloc(sizeof(*mem), GFP_KERNEL);
-       if (! mem)
-               return -ENOMEM;
-       mutex_lock(&list_mutex);
-       mem->buffer = *dmab;
-       mem->id = id;
-       list_add_tail(&mem->list, &mem_list_head);
-       mutex_unlock(&list_mutex);
-       return 0;
-}
-
-/*
- * purge all reserved buffers
- */
-static void free_all_reserved_pages(void)
-{
-       struct list_head *p;
-       struct snd_mem_list *mem;
-
-       mutex_lock(&list_mutex);
-       while (! list_empty(&mem_list_head)) {
-               p = mem_list_head.next;
-               mem = list_entry(p, struct snd_mem_list, list);
-               list_del(p);
-               snd_dma_free_pages(&mem->buffer);
-               kfree(mem);
-       }
-       mutex_unlock(&list_mutex);
-}
-
-
-#ifdef CONFIG_PROC_FS
-/*
- * proc file interface
- */
-#define SND_MEM_PROC_FILE      "driver/snd-page-alloc"
-static struct proc_dir_entry *snd_mem_proc;
-
-static int snd_mem_proc_read(struct seq_file *seq, void *offset)
-{
-       long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
-       struct snd_mem_list *mem;
-       int devno;
-       static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" };
-
-       mutex_lock(&list_mutex);
-       seq_printf(seq, "pages  : %li bytes (%li pages per %likB)\n",
-                  pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
-       devno = 0;
-       list_for_each_entry(mem, &mem_list_head, list) {
-               devno++;
-               seq_printf(seq, "buffer %d : ID %08x : type %s\n",
-                          devno, mem->id, types[mem->buffer.dev.type]);
-               seq_printf(seq, "  addr = 0x%lx, size = %d bytes\n",
-                          (unsigned long)mem->buffer.addr,
-                          (int)mem->buffer.bytes);
-       }
-       mutex_unlock(&list_mutex);
-       return 0;
-}
-
-static int snd_mem_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, snd_mem_proc_read, NULL);
-}
-
-/* FIXME: for pci only - other bus? */
-#ifdef CONFIG_PCI
-#define gettoken(bufp) strsep(bufp, " \t\n")
-
-static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
-                                 size_t count, loff_t * ppos)
-{
-       char buf[128];
-       char *token, *p;
-
-       if (count > sizeof(buf) - 1)
-               return -EINVAL;
-       if (copy_from_user(buf, buffer, count))
-               return -EFAULT;
-       buf[count] = '\0';
-
-       p = buf;
-       token = gettoken(&p);
-       if (! token || *token == '#')
-               return count;
-       if (strcmp(token, "add") == 0) {
-               char *endp;
-               int vendor, device, size, buffers;
-               long mask;
-               int i, alloced;
-               struct pci_dev *pci;
-
-               if ((token = gettoken(&p)) == NULL ||
-                   (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
-                   (token = gettoken(&p)) == NULL ||
-                   (device = simple_strtol(token, NULL, 0)) <= 0 ||
-                   (token = gettoken(&p)) == NULL ||
-                   (mask = simple_strtol(token, NULL, 0)) < 0 ||
-                   (token = gettoken(&p)) == NULL ||
-                   (size = memparse(token, &endp)) < 64*1024 ||
-                   size > 16*1024*1024 /* too big */ ||
-                   (token = gettoken(&p)) == NULL ||
-                   (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
-                   buffers > 4) {
-                       printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
-                       return count;
-               }
-               vendor &= 0xffff;
-               device &= 0xffff;
-
-               alloced = 0;
-               pci = NULL;
-               while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
-                       if (mask > 0 && mask < 0xffffffff) {
-                               if (pci_set_dma_mask(pci, mask) < 0 ||
-                                   pci_set_consistent_dma_mask(pci, mask) < 0) {
-                                       printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
-                                       pci_dev_put(pci);
-                                       return count;
-                               }
-                       }
-                       for (i = 0; i < buffers; i++) {
-                               struct snd_dma_buffer dmab;
-                               memset(&dmab, 0, sizeof(dmab));
-                               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                                                       size, &dmab) < 0) {
-                                       printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
-                                       pci_dev_put(pci);
-                                       return count;
-                               }
-                               snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
-                       }
-                       alloced++;
-               }
-               if (! alloced) {
-                       for (i = 0; i < buffers; i++) {
-                               struct snd_dma_buffer dmab;
-                               memset(&dmab, 0, sizeof(dmab));
-                               /* FIXME: We can allocate only in ZONE_DMA
-                                * without a device pointer!
-                                */
-                               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
-                                                       size, &dmab) < 0) {
-                                       printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
-                                       break;
-                               }
-                               snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
-                       }
-               }
-       } else if (strcmp(token, "erase") == 0)
-               /* FIXME: need for releasing each buffer chunk? */
-               free_all_reserved_pages();
-       else
-               printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
-       return count;
-}
-#endif /* CONFIG_PCI */
-
-static const struct file_operations snd_mem_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = snd_mem_proc_open,
-       .read           = seq_read,
-#ifdef CONFIG_PCI
-       .write          = snd_mem_proc_write,
-#endif
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-#endif /* CONFIG_PROC_FS */
-
-/*
- * module entry
- */
-
-static int __init snd_mem_init(void)
-{
-#ifdef CONFIG_PROC_FS
-       snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
-                                  &snd_mem_proc_fops);
-#endif
-       return 0;
-}
-
-static void __exit snd_mem_exit(void)
-{
-       remove_proc_entry(SND_MEM_PROC_FILE, NULL);
-       free_all_reserved_pages();
-       if (snd_allocated_pages > 0)
-               printk(KERN_ERR "snd-malloc: Memory leak?  pages not freed = %li\n", snd_allocated_pages);
-}
-
-
-module_init(snd_mem_init)
-module_exit(snd_mem_exit)
-
-
 /*
  * exports
  */
@@ -597,8 +295,5 @@ EXPORT_SYMBOL(snd_dma_alloc_pages);
 EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
 EXPORT_SYMBOL(snd_dma_free_pages);
 
-EXPORT_SYMBOL(snd_dma_get_reserved_buf);
-EXPORT_SYMBOL(snd_dma_reserve_buf);
-
 EXPORT_SYMBOL(snd_malloc_pages);
 EXPORT_SYMBOL(snd_free_pages);
index 6e03b465e44e3a05f82e93a2d25a61f030cc3cf6..a2104671f51d38df6eec99b3e0aa8ac570ea8988 100644 (file)
@@ -1937,6 +1937,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                case SNDRV_PCM_STATE_DISCONNECTED:
                        err = -EBADFD;
                        goto _endloop;
+               case SNDRV_PCM_STATE_PAUSED:
+                       continue;
                }
                if (!tout) {
                        snd_printd("%s write error (DMA or IRQ trouble?)\n",
index 0af622c34e196dfafd5732ebd3b1f4e7869e77d2..54debc07f5cbb233a2249e4bf957855adbfac25b 100644 (file)
@@ -51,17 +51,9 @@ static const size_t snd_minimum_buffer = 16384;
 static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
 {
        struct snd_dma_buffer *dmab = &substream->dma_buffer;
+       size_t orig_size = size;
        int err;
 
-       /* already reserved? */
-       if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
-               if (dmab->bytes >= size)
-                       return 0; /* yes */
-               /* no, free the reserved block */
-               snd_dma_free_pages(dmab);
-               dmab->bytes = 0;
-       }
-
        do {
                if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
                                               size, dmab)) < 0) {
@@ -72,6 +64,10 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
                size >>= 1;
        } while (size >= snd_minimum_buffer);
        dmab->bytes = 0; /* tell error */
+       pr_warn("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
+               substream->pcm->card->number, substream->pcm->device,
+               substream->stream ? 'c' : 'p', substream->number,
+               substream->pcm->name, orig_size);
        return 0;
 }
 
@@ -82,10 +78,7 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
 {
        if (substream->dma_buffer.area == NULL)
                return;
-       if (substream->dma_buf_id)
-               snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
-       else
-               snd_dma_free_pages(&substream->dma_buffer);
+       snd_dma_free_pages(&substream->dma_buffer);
        substream->dma_buffer.area = NULL;
 }
 
@@ -260,11 +253,6 @@ static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
  *
  * Do pre-allocation for the given DMA buffer type.
  *
- * When substream->dma_buf_id is set, the function tries to look for
- * the reserved buffer, and the buffer is not freed but reserved at
- * destruction time.  The dma_buf_id must be unique for all systems
- * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
- *
  * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
index 43f24cce3dec1b6375edb94e02be9b5819829121..4560ca0e5651ac6c515c589efa18fc8d308b1910 100644 (file)
@@ -514,3 +514,42 @@ unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit)
        return 0;
 }
 EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate);
+
+static unsigned int snd_pcm_rate_mask_sanitize(unsigned int rates)
+{
+       if (rates & SNDRV_PCM_RATE_CONTINUOUS)
+               return SNDRV_PCM_RATE_CONTINUOUS;
+       else if (rates & SNDRV_PCM_RATE_KNOT)
+               return SNDRV_PCM_RATE_KNOT;
+       return rates;
+}
+
+/**
+ * snd_pcm_rate_mask_intersect - computes the intersection between two rate masks
+ * @rates_a: The first rate mask
+ * @rates_b: The second rate mask
+ *
+ * This function computes the rates that are supported by both rate masks passed
+ * to the function. It will take care of the special handling of
+ * SNDRV_PCM_RATE_CONTINUOUS and SNDRV_PCM_RATE_KNOT.
+ *
+ * Return: A rate mask containing the rates that are supported by both rates_a
+ * and rates_b.
+ */
+unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
+       unsigned int rates_b)
+{
+       rates_a = snd_pcm_rate_mask_sanitize(rates_a);
+       rates_b = snd_pcm_rate_mask_sanitize(rates_b);
+
+       if (rates_a & SNDRV_PCM_RATE_CONTINUOUS)
+               return rates_b;
+       else if (rates_b & SNDRV_PCM_RATE_CONTINUOUS)
+               return rates_a;
+       else if (rates_a & SNDRV_PCM_RATE_KNOT)
+               return rates_b;
+       else if (rates_b & SNDRV_PCM_RATE_KNOT)
+               return rates_a;
+       return rates_a & rates_b;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);
index d3226892ad6b44953fd4d980d65874ac40535768..9048777228e2f058430f10636a7d9de74233c550 100644 (file)
@@ -434,17 +434,14 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
                return;
        index = s->packet_index;
 
+       /* this module generate empty packet for 'no data' */
        syt = calculate_syt(s, cycle);
-       if (!(s->flags & CIP_BLOCKING)) {
+       if (!(s->flags & CIP_BLOCKING))
                data_blocks = calculate_data_blocks(s);
-       } else {
-               if (syt != 0xffff) {
-                       data_blocks = s->syt_interval;
-               } else {
-                       data_blocks = 0;
-                       syt = 0xffffff;
-               }
-       }
+       else if (syt != 0xffff)
+               data_blocks = s->syt_interval;
+       else
+               data_blocks = 0;
 
        buffer = s->buffer.packets[index].buffer;
        buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
index 57bcd31fcc123c38cd293cab40b52310734698a2..c0aa64941cee0bd927450a6b69314d14f2f02bce 100644 (file)
@@ -1019,7 +1019,7 @@ static void dice_proc_read(struct snd_info_entry *entry,
 
        if (dice_proc_read_mem(dice, &tx_rx_header, sections[2], 2) < 0)
                return;
-       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx));
+       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx) / 4);
        for (stream = 0; stream < tx_rx_header.number; ++stream) {
                if (dice_proc_read_mem(dice, &buf.tx, sections[2] + 2 +
                                       stream * tx_rx_header.size,
@@ -1045,7 +1045,7 @@ static void dice_proc_read(struct snd_info_entry *entry,
 
        if (dice_proc_read_mem(dice, &tx_rx_header, sections[4], 2) < 0)
                return;
-       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx));
+       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx) / 4);
        for (stream = 0; stream < tx_rx_header.number; ++stream) {
                if (dice_proc_read_mem(dice, &buf.rx, sections[4] + 2 +
                                       stream * tx_rx_header.size,
index 461d94cfecbee6bc0ac02d324db0f3f74c9d4eae..e3f29132d3acef1e43298b6d7cd7d43de5871742 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 #include "sound_config.h"
+#include "sleep.h"
 
 #define DMAP_FREE_ON_CLOSE      0
 #define DMAP_KEEP_ON_CLOSE      1
@@ -351,8 +352,7 @@ static void dma_reset_output(int dev)
        if (!signal_pending(current) && adev->dmap_out->qlen && 
            adev->dmap_out->underrun_count == 0){
                spin_unlock_irqrestore(&dmap->lock,flags);
-               interruptible_sleep_on_timeout(&adev->out_sleeper,
-                                              dmabuf_timeout(dmap));
+               oss_broken_sleep_on(&adev->out_sleeper, dmabuf_timeout(dmap));
                spin_lock_irqsave(&dmap->lock,flags);
        }
        adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
@@ -446,7 +446,7 @@ int DMAbuf_sync(int dev)
                        long t = dmabuf_timeout(dmap);
                        spin_unlock_irqrestore(&dmap->lock,flags);
                        /* FIXME: not safe may miss events */
-                       t = interruptible_sleep_on_timeout(&adev->out_sleeper, t);
+                       t = oss_broken_sleep_on(&adev->out_sleeper, t);
                        spin_lock_irqsave(&dmap->lock,flags);
                        if (!t) {
                                adev->dmap_out->flags &= ~DMA_SYNCING;
@@ -466,7 +466,7 @@ int DMAbuf_sync(int dev)
                        while (!signal_pending(current) &&
                               adev->d->local_qlen(dev)){
                                spin_unlock_irqrestore(&dmap->lock,flags);
-                               interruptible_sleep_on_timeout(&adev->out_sleeper,
+                               oss_broken_sleep_on(&adev->out_sleeper,
                                                               dmabuf_timeout(dmap));
                                spin_lock_irqsave(&dmap->lock,flags);
                        }
@@ -587,8 +587,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
                        timeout = dmabuf_timeout(dmap);
 
                spin_unlock_irqrestore(&dmap->lock,flags);
-               timeout = interruptible_sleep_on_timeout(&adev->in_sleeper,
-                                                        timeout);
+               timeout = oss_broken_sleep_on(&adev->in_sleeper, timeout);
                if (!timeout) {
                        /* FIXME: include device name */
                        err = -EIO;
@@ -768,8 +767,7 @@ static int output_sleep(int dev, int dontblock)
                timeout_value = dmabuf_timeout(dmap);
        else
                timeout_value = MAX_SCHEDULE_TIMEOUT;
-       timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper,
-                                                      timeout_value);
+       timeout_value = oss_broken_sleep_on(&adev->out_sleeper, timeout_value);
        if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) {
                printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
                dma_reset_output(dev);
index 1308d8d3418637df088fdf7b7acb43ec54587ffd..01019f06fa91f21a954abe6d8fe195bd305d6143 100644 (file)
@@ -239,7 +239,6 @@ struct sound_queue {
     int busy, syncing, xruns, died;
 };
 
-#define SLEEP(queue)           interruptible_sleep_on_timeout(&queue, HZ)
 #define WAKE_UP(queue)         (wake_up_interruptible(&queue))
 
 extern struct sound_queue dmasound_write_sq;
index bac43b5b6e95be36ff5fe4fffb955c7b7a078fd9..f4ee85a4c42fb910ae2a234ffb4de3bb815bc155 100644 (file)
@@ -619,15 +619,27 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
        }
 
        while (uLeft) {
+               DEFINE_WAIT(wait);
+
                while (write_sq.count >= write_sq.max_active) {
+                       prepare_to_wait(&write_sq.action_queue, &wait, TASK_INTERRUPTIBLE);
                        sq_play();
-                       if (write_sq.non_blocking)
+                       if (write_sq.non_blocking) {
+                               finish_wait(&write_sq.action_queue, &wait);
                                return uWritten > 0 ? uWritten : -EAGAIN;
-                       SLEEP(write_sq.action_queue);
-                       if (signal_pending(current))
+                       }
+                       if (write_sq.count < write_sq.max_active)
+                               break;
+
+                       schedule_timeout(HZ);
+                       if (signal_pending(current)) {
+                               finish_wait(&write_sq.action_queue, &wait);
                                return uWritten > 0 ? uWritten : -EINTR;
+                       }
                }
 
+               finish_wait(&write_sq.action_queue, &wait);
+
                /* Here, we can avoid disabling the interrupt by first
                 * copying and translating the data, and then updating
                 * the write_sq variables. Until this is done, the interrupt
@@ -707,11 +719,8 @@ static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode,
                        if (file->f_flags & O_NONBLOCK)
                                return rc;
                        rc = -EINTR;
-                       while (sq->busy) {
-                               SLEEP(sq->open_queue);
-                               if (signal_pending(current))
-                                       return rc;
-                       }
+                       if (wait_event_interruptible(sq->open_queue, !sq->busy))
+                               return rc;
                        rc = 0;
 #else
                        /* OSS manual says we will return EBUSY regardless
@@ -844,7 +853,8 @@ static int sq_fsync(void)
        sq_play();      /* there may be an incomplete frame waiting */
 
        while (write_sq.active) {
-               SLEEP(write_sq.sync_queue);
+               wait_event_interruptible_timeout(write_sq.sync_queue,
+                                                !write_sq.active, HZ);
                if (signal_pending(current)) {
                        /* While waiting for audio output to drain, an
                         * interrupt occurred.  Stop audio output immediately
index 8cdb2cfe65c841a7f942a25fde54b9d04e0d3ea6..8f45cd999965cd7695236ae01a23542972a14fd2 100644 (file)
@@ -86,9 +86,8 @@ static void drain_midi_queue(int dev)
         */
 
        if (midi_devs[dev]->buffer_status != NULL)
-               while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev)) 
-                       interruptible_sleep_on_timeout(&midi_sleeper[dev],
-                                                      HZ/10);
+               wait_event_interruptible_timeout(midi_sleeper[dev],
+                               !midi_devs[dev]->buffer_status(dev), HZ/10);
 }
 
 static void midi_input_intr(int dev, unsigned char data)
@@ -233,8 +232,8 @@ void MIDIbuf_release(int dev, struct file *file)
                                                           * devices
                                                         */
 
-               while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev]))
-                         interruptible_sleep_on(&midi_sleeper[dev]);
+               wait_event_interruptible(midi_sleeper[dev],
+                                        !DATA_AVAIL(midi_out_buf[dev]));
                /*
                 *      Sync
                 */
@@ -282,8 +281,8 @@ int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
                                goto out;
                        }
 
-                       interruptible_sleep_on(&midi_sleeper[dev]);
-                       if (signal_pending(current)) 
+                       if (wait_event_interruptible(midi_sleeper[dev],
+                                               SPACE_AVAIL(midi_out_buf[dev])))
                        {
                                c = -EINTR;
                                goto out;
@@ -325,8 +324,9 @@ int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
                        c = -EAGAIN;
                        goto out;
                }
-               interruptible_sleep_on_timeout(&input_sleeper[dev],
-                                              parms[dev].prech_timeout);
+               wait_event_interruptible_timeout(input_sleeper[dev],
+                                                DATA_AVAIL(midi_in_buf[dev]),
+                                                parms[dev].prech_timeout);
 
                if (signal_pending(current))
                        c = -EINTR;     /* The user is getting restless */
index 11ff7c55240cfd28c70bfc5067b6bf73a3b9828f..c23f9f95bfa55ec28fc8f0f028739f20765d6434 100644 (file)
@@ -664,12 +664,15 @@ static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 static void dsp_write_flush(void)
 {
+       int timeout = get_play_delay_jiffies(dev.DAPF.len);
+
        if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags))
                return;
        set_bit(F_WRITEFLUSH, &dev.flags);
-       interruptible_sleep_on_timeout(
-               &dev.writeflush,
-               get_play_delay_jiffies(dev.DAPF.len));
+       wait_event_interruptible_timeout(
+               dev.writeflush,
+               !test_bit(F_WRITEFLUSH, &dev.flags),
+               timeout);
        clear_bit(F_WRITEFLUSH, &dev.flags);
        if (!signal_pending(current)) {
                current->state = TASK_INTERRUPTIBLE;
@@ -897,6 +900,7 @@ static int dsp_read(char __user *buf, size_t len)
 {
        int count = len;
        char *page = (char *)__get_free_page(GFP_KERNEL);
+       int timeout = get_rec_delay_jiffies(DAR_BUFF_SIZE);
 
        if (!page)
                return -ENOMEM;
@@ -936,11 +940,11 @@ static int dsp_read(char __user *buf, size_t len)
 
                if (count > 0) {
                        set_bit(F_READBLOCK, &dev.flags);
-                       if (!interruptible_sleep_on_timeout(
-                               &dev.readblock,
-                               get_rec_delay_jiffies(DAR_BUFF_SIZE)))
+                       if (wait_event_interruptible_timeout(
+                                       dev.readblock,
+                                       test_bit(F_READBLOCK, &dev.flags),
+                                       timeout) <= 0)
                                clear_bit(F_READING, &dev.flags);
-                       clear_bit(F_READBLOCK, &dev.flags);
                        if (signal_pending(current)) {
                                free_page((unsigned long)page);
                                return -EINTR;
@@ -955,6 +959,7 @@ static int dsp_write(const char __user *buf, size_t len)
 {
        int count = len;
        char *page = (char *)__get_free_page(GFP_KERNEL);
+       int timeout = get_play_delay_jiffies(DAP_BUFF_SIZE);
 
        if (!page)
                return -ENOMEM;
@@ -995,10 +1000,10 @@ static int dsp_write(const char __user *buf, size_t len)
 
                if (count > 0) {
                        set_bit(F_WRITEBLOCK, &dev.flags);
-                       interruptible_sleep_on_timeout(
-                               &dev.writeblock,
-                               get_play_delay_jiffies(DAP_BUFF_SIZE));
-                       clear_bit(F_WRITEBLOCK, &dev.flags);
+                       wait_event_interruptible_timeout(
+                               dev.writeblock,
+                               test_bit(F_WRITEBLOCK, &dev.flags),
+                               timeout);
                        if (signal_pending(current)) {
                                free_page((unsigned long)page);
                                return -EINTR;
@@ -1044,7 +1049,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
                        clear_bit(F_WRITING, &dev.flags);
                }
 
-               if (test_bit(F_WRITEBLOCK, &dev.flags))
+               if (test_and_clear_bit(F_WRITEBLOCK, &dev.flags))
                        wake_up_interruptible(&dev.writeblock);
                break;
 
@@ -1055,7 +1060,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
 
                pack_DARQ_to_DARF(dev.last_recbank);
 
-               if (test_bit(F_READBLOCK, &dev.flags))
+               if (test_and_clear_bit(F_READBLOCK, &dev.flags))
                        wake_up_interruptible(&dev.readblock);
                break;
 
index 4ff60a6427d9d8d3ea7cf095bc2766f2d49955fc..9b9f7d385134253f3e5ceac1e10caa2f21fe06a7 100644 (file)
@@ -19,6 +19,7 @@
 #include "sound_config.h"
 
 #include "midi_ctrl.h"
+#include "sleep.h"
 
 static int      sequencer_ok;
 static struct sound_timer_operations *tmr;
@@ -100,8 +101,7 @@ int sequencer_read(int dev, struct file *file, char __user *buf, int count)
                        return -EAGAIN;
                }
 
-               interruptible_sleep_on_timeout(&midi_sleeper,
-                                              pre_event_timeout);
+               oss_broken_sleep_on(&midi_sleeper, pre_event_timeout);
                spin_lock_irqsave(&lock,flags);
                if (!iqlen)
                {
@@ -343,7 +343,7 @@ static int seq_queue(unsigned char *note, char nonblock)
                /*
                 * Sleep until there is enough space on the queue
                 */
-               interruptible_sleep_on(&seq_sleeper);
+               oss_broken_sleep_on(&seq_sleeper, MAX_SCHEDULE_TIMEOUT);
        }
        if (qlen >= SEQ_MAX_QUEUE)
        {
@@ -1122,8 +1122,7 @@ static void seq_drain_midi_queues(void)
                 */
 
                if (n)
-                       interruptible_sleep_on_timeout(&seq_sleeper,
-                                                      HZ/10);
+                       oss_broken_sleep_on(&seq_sleeper, HZ/10);
        }
 }
 
@@ -1145,8 +1144,7 @@ void sequencer_release(int dev, struct file *file)
                while (!signal_pending(current) && qlen > 0)
                {
                        seq_sync();
-                       interruptible_sleep_on_timeout(&seq_sleeper,
-                                                      3*HZ);
+                       oss_broken_sleep_on(&seq_sleeper, 3*HZ);
                        /* Extra delay */
                }
        }
@@ -1201,7 +1199,7 @@ static int seq_sync(void)
                seq_startplay();
 
        if (qlen > 0)
-               interruptible_sleep_on_timeout(&seq_sleeper, HZ);
+               oss_broken_sleep_on(&seq_sleeper, HZ);
        return qlen;
 }
 
@@ -1224,7 +1222,7 @@ static void midi_outc(int dev, unsigned char data)
 
        spin_lock_irqsave(&lock,flags);
        while (n && !midi_devs[dev]->outputc(dev, data)) {
-               interruptible_sleep_on_timeout(&seq_sleeper, HZ/25);
+               oss_broken_sleep_on(&seq_sleeper, HZ/25);
                n--;
        }
        spin_unlock_irqrestore(&lock,flags);
diff --git a/sound/oss/sleep.h b/sound/oss/sleep.h
new file mode 100644 (file)
index 0000000..a20fc92
--- /dev/null
@@ -0,0 +1,18 @@
+#include <linux/wait.h>
+
+/*
+ * Do not use. This is a replacement for the old
+ * "interruptible_sleep_on_timeout" function that has been
+ * deprecated for ages. All users should instead try to use
+ * wait_event_interruptible_timeout.
+ */
+
+static inline long
+oss_broken_sleep_on(wait_queue_head_t *q, long timeout)
+{
+       DEFINE_WAIT(wait);
+       prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
+       timeout = schedule_timeout(timeout);
+       finish_wait(q, &wait);
+       return timeout;
+}
index 7d8803a00b79cc85c06b3566ac909293caf4d69d..f851fd0e199c54579b8447a391581324abee7e39 100644 (file)
@@ -90,6 +90,8 @@
 #include <asm/sibyte/sb1250_mac.h>
 #include <asm/sibyte/sb1250.h>
 
+#include "sleep.h"
+
 struct cs4297a_state;
 
 static DEFINE_MUTEX(swarm_cs4297a_mutex);
@@ -748,7 +750,7 @@ static int serdma_reg_access(struct cs4297a_state *s, u64 data)
                 /* Since a writer has the DSP open, we have to mux the
                    request in */
                 s->reg_request = data;
-                interruptible_sleep_on(&s->dma_dac.reg_wait);
+               oss_broken_sleep_on(&s->dma_dac.reg_wait, MAX_SCHEDULE_TIMEOUT);
                 /* XXXKW how can I deal with the starvation case where
                    the opener isn't writing? */
         } else {
@@ -790,7 +792,7 @@ static int cs4297a_read_ac97(struct cs4297a_state *s, u32 offset,
         if (serdma_reg_access(s, (0xCLL << 60) | (1LL << 47) | ((u64)(offset & 0x7F) << 40)))
                 return -1;
 
-        interruptible_sleep_on(&s->dma_adc.reg_wait);
+       oss_broken_sleep_on(&s->dma_adc.reg_wait, MAX_SCHEDULE_TIMEOUT);
         *value = s->read_value;
         CS_DBGOUT(CS_AC97, 2,
                   printk(KERN_INFO "cs4297a: rdr reg %x -> %x\n", s->read_reg, s->read_value));
@@ -1740,7 +1742,7 @@ static ssize_t cs4297a_read(struct file *file, char *buffer, size_t count,
                        start_adc(s);
                        if (file->f_flags & O_NONBLOCK)
                                return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
+                       oss_broken_sleep_on(&s->dma_adc.wait, MAX_SCHEDULE_TIMEOUT);
                        if (signal_pending(current))
                                return ret ? ret : -ERESTARTSYS;
                        continue;
@@ -1836,7 +1838,7 @@ static ssize_t cs4297a_write(struct file *file, const char *buffer,
                        start_dac(s);
                        if (file->f_flags & O_NONBLOCK)
                                return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&d->wait);
+                       oss_broken_sleep_on(&d->wait, MAX_SCHEDULE_TIMEOUT);
                        if (signal_pending(current))
                                return ret ? ret : -ERESTARTSYS;
                        continue;
@@ -2452,7 +2454,7 @@ static int cs4297a_locked_open(struct inode *inode, struct file *file)
                                return -EBUSY;
                        }
                        mutex_unlock(&s->open_sem_dac);
-                       interruptible_sleep_on(&s->open_wait_dac);
+                       oss_broken_sleep_on(&s->open_wait_dac, MAX_SCHEDULE_TIMEOUT);
 
                        if (signal_pending(current)) {
                                 printk("open - sig pending\n");
@@ -2469,7 +2471,7 @@ static int cs4297a_locked_open(struct inode *inode, struct file *file)
                                return -EBUSY;
                        }
                        mutex_unlock(&s->open_sem_adc);
-                       interruptible_sleep_on(&s->open_wait_adc);
+                       oss_broken_sleep_on(&s->open_wait_adc, MAX_SCHEDULE_TIMEOUT);
 
                        if (signal_pending(current)) {
                                 printk("open - sig pending\n");
index 4bbcc0fcd4eb0d7c988c06e21cc76afb1236969e..a077e9c69a5ea95610256345f73fb8c5ebdadaa4 100644 (file)
@@ -2921,6 +2921,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
        vwsnd_dev_t *devc;
        int minor = iminor(inode);
        int sw_samplefmt;
+       DEFINE_WAIT(wait);
 
        DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
 
@@ -2937,21 +2938,26 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
        }
 
        mutex_lock(&devc->open_mutex);
-       while (devc->open_mode & file->f_mode) {
+       while (1) {
+               prepare_to_wait(&devc->open_wait, &wait, TASK_INTERRUPTIBLE);
+               if (!(devc->open_mode & file->f_mode))
+                       break;
+
                mutex_unlock(&devc->open_mutex);
+               mutex_unlock(&vwsnd_mutex);
                if (file->f_flags & O_NONBLOCK) {
                        DEC_USE_COUNT;
-                       mutex_unlock(&vwsnd_mutex);
                        return -EBUSY;
                }
-               interruptible_sleep_on(&devc->open_wait);
+               schedule();
                if (signal_pending(current)) {
                        DEC_USE_COUNT;
-                       mutex_unlock(&vwsnd_mutex);
                        return -ERESTARTSYS;
                }
+               mutex_lock(&vwsnd_mutex);
                mutex_lock(&devc->open_mutex);
        }
+       finish_wait(&devc->open_wait, &wait);
        devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
        mutex_unlock(&devc->open_mutex);
 
index 46ed9e8ae0fde718525da786a5b79a27a043c372..8756c8e329224f1e2fb81862d6e60be4954a85cd 100644 (file)
@@ -25,6 +25,7 @@ config SND_ALS300
        select SND_PCM
        select SND_AC97_CODEC
        select SND_OPL3_LIB
+       select ZONE_DMA
        help
          Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
 
@@ -49,6 +50,7 @@ config SND_ALI5451
        tristate "ALi M5451 PCI Audio Controller"
        select SND_MPU401_UART
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for the integrated AC97 sound
          device on motherboards using the ALi M5451 Audio Controller
@@ -153,6 +155,7 @@ config SND_AZT3328
        select SND_PCM
        select SND_RAWMIDI
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for Aztech AZF3328 (PCI168)
          soundcards.
@@ -254,6 +257,7 @@ config SND_CS46XX
        tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
        select SND_RAWMIDI
        select SND_AC97_CODEC
+       select FW_LOADER
        help
          Say Y here to include support for Cirrus Logic CS4610/CS4612/
          CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips.
@@ -458,6 +462,7 @@ config SND_EMU10K1
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y to include support for Sound Blaster PCI 512, Live!,
          Audigy and E-mu APS (partially supported) soundcards.
@@ -473,6 +478,7 @@ config SND_EMU10K1X
        tristate "Emu10k1X (Dell OEM Version)"
        select SND_AC97_CODEC
        select SND_RAWMIDI
+       select ZONE_DMA
        help
          Say Y here to include support for the Dell OEM version of the
          Sound Blaster Live!.
@@ -506,6 +512,7 @@ config SND_ES1938
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for soundcards based on ESS Solo-1
          (ES1938, ES1946, ES1969) chips.
@@ -517,6 +524,7 @@ config SND_ES1968
        tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
        select SND_MPU401_UART
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for soundcards based on ESS Maestro
          1/2/2E chips.
@@ -605,6 +613,7 @@ config SND_ICE1712
        select SND_MPU401_UART
        select SND_AC97_CODEC
        select BITREVERSE
+       select ZONE_DMA
        help
          Say Y here to include support for soundcards based on the
          ICE1712 (Envy24) chip.
@@ -692,6 +701,7 @@ config SND_LX6464ES
 config SND_MAESTRO3
        tristate "ESS Allegro/Maestro3"
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for soundcards based on ESS Maestro 3
          (Allegro) chips.
@@ -788,6 +798,7 @@ config SND_SIS7019
        tristate "SiS 7019 Audio Accelerator"
        depends on X86 && !X86_64
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for the SiS 7019 Audio Accelerator.
 
@@ -799,6 +810,7 @@ config SND_SONICVIBES
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for soundcards based on the S3
          SonicVibes chip.
@@ -810,6 +822,7 @@ config SND_TRIDENT
        tristate "Trident 4D-Wave DX/NX; SiS 7018"
        select SND_MPU401_UART
        select SND_AC97_CODEC
+       select ZONE_DMA
        help
          Say Y here to include support for soundcards based on Trident
          4D-Wave DX/NX or SiS 7018 chips.
index fc339ef0a0ae439a87087753a4bfaf6e28de9742..c49a082c378b6c711e36d74187ef742318be56ce 100644 (file)
@@ -1716,9 +1716,14 @@ struct snd_cs46xx {
        struct snd_pcm *pcm_rear;
        struct snd_pcm *pcm_center_lfe;
        struct snd_pcm *pcm_iec958;
+
+#define CS46XX_DSP_MODULES     5
+       struct dsp_module_desc *modules[CS46XX_DSP_MODULES];
 #else /* for compatibility */
        struct snd_cs46xx_pcm *playback_pcm;
        unsigned int play_ctl;
+
+       struct ba1_struct *ba1;
 #endif
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/sound/pci/cs46xx/cs46xx_image.h b/sound/pci/cs46xx/cs46xx_image.h
deleted file mode 100644 (file)
index dc93f62..0000000
+++ /dev/null
@@ -1,3468 +0,0 @@
-struct BA1struct {
-       struct {
-               unsigned long offset;
-               unsigned long size;
-       } memory[BA1_MEMORY_COUNT];
-       u32 map[BA1_DWORD_SIZE];
-};
-
-
-static struct BA1struct BA1Struct = {
-{{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }},
-{0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00200040,0x00008010,0x00000000,
-0x00000000,0x80000001,0x00000001,0x00060000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00900080,0x00000173,0x00000000,
-0x00000000,0x00000010,0x00800000,0x00900000,
-0xf2c0000f,0x00000200,0x00000000,0x00010600,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x330300c2,
-0x06000000,0x00000000,0x80008000,0x80008000,
-0x3fc0000f,0x00000301,0x00010400,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-0x04800000,0x00000001,0x00800001,0x0000ffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x066a0600,0x06350070,0x0000929d,0x929d929d,
-0x00000000,0x0000735a,0x00000600,0x00000000,
-0x929d735a,0x8734abfe,0x00010000,0x735a735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000804f,0x000000c3,
-0x05000000,0x00a00010,0x00000000,0x80008000,
-0x00000000,0x00000000,0x00000700,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000080,0x00a00000,0x0000809a,0x000000c2,
-0x07400000,0x00000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x000107a0,
-0x00c80028,0x000000c2,0x06800000,0x00000000,
-0x06e00080,0x00300000,0x000080bb,0x000000c9,
-0x07a00000,0x04000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x00000780,
-0x00c80028,0x000000c5,0xff800000,0x00000000,
-0x00640080,0x00c00000,0x00008197,0x000000c9,
-0x07800000,0x04000000,0x80008000,0xffffffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000805e,0x000000c1,
-0x00000000,0x00800000,0x80008000,0x80008000,
-0x00020000,0x0000ffff,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x00100635,0x060b013f,0x00000004,
-0x00000001,0x007a0002,0x00000000,0x066e0610,
-0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-0x00000000,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x00000000,0x06400136,
-0x0000270f,0x00010000,0x007a0000,0x00000000,
-0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x735a0100,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00010004,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00001705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00009705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00011705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00019705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00021705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00029705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00031705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00039705,0x00001400,0x000a411e,0x00001003,
-0x000fe19e,0x00001003,0x0009c730,0x00001003,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00009705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00011705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00019705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00021705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00029705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00031705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00039705,0x00001400,0x000a211e,0x00001003,
-0x0000a730,0x00001008,0x000e2730,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x00000000,0x00000000,0x000f619c,0x00001003,
-0x0007f801,0x000c0000,0x00000037,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0000373c,0x00001000,0x00000000,0x00000000,
-0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000273c,0x00001000,
-0x00000033,0x00001000,0x000e679e,0x00001003,
-0x00007705,0x00001400,0x000ac71e,0x00001003,
-0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000a730,0x00001003,
-0x00000033,0x00001000,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x000c0000,
-0x00000032,0x00001000,0x0000273d,0x00001000,
-0x0004a730,0x00001003,0x00000f41,0x00097140,
-0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-0x00002725,0x000aa400,0x00013705,0x00093a00,
-0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-0x00031705,0x00092240,0x00039f05,0x000932c0,
-0x0003520a,0x00000000,0x00040731,0x0000100b,
-0x00010705,0x000b20c0,0x00000000,0x000eba44,
-0x00032108,0x000c60c4,0x00065208,0x000c2917,
-0x000406b0,0x00001007,0x00012f05,0x00036880,
-0x0002818e,0x000c0000,0x0004410a,0x00000000,
-0x00040630,0x00001007,0x00029705,0x000c0000,
-0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-0x000683ad,0x00095241,0x00020f05,0x000991c1,
-0x00000000,0x00000000,0x00086f88,0x00001000,
-0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-0x000a1681,0x000b97c0,0x00021601,0x00002500,
-0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-0x00021681,0x00002d00,0x00020f81,0x000bd800,
-0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-0x00021681,0x00020d00,0x00020f81,0x000bde80,
-0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-0x0007e48a,0x00000000,0x00011f05,0x00084080,
-0x00000000,0x00000000,0x00001705,0x000b3540,
-0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-0x00055488,0x00000000,0x0000d482,0x0003fc40,
-0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-0x000c86b0,0x00001007,0x00008281,0x000bb240,
-0x0000b801,0x000b7140,0x00007888,0x00000000,
-0x0000073c,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x00055288,0x000c555c,
-0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-0x0000fa88,0x00000000,0x00000032,0x00001000,
-0x0000073d,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x0008c01c,0x00001003,
-0x00002705,0x00001008,0x0008b201,0x000c1392,
-0x0000ba01,0x00000000,0x00008731,0x00001400,
-0x0004c108,0x000fe0c4,0x00057488,0x00000000,
-0x000a6388,0x00001001,0x0008b334,0x000bc141,
-0x0003020e,0x00000000,0x000886b0,0x00001008,
-0x00003625,0x000c5dfa,0x000a638a,0x00001001,
-0x0008020e,0x00001002,0x0008a6b0,0x00001008,
-0x0007f301,0x00000000,0x00000000,0x00000000,
-0x00002725,0x000a8c40,0x000000ae,0x00000000,
-0x000d8630,0x00001008,0x00000000,0x000c74e0,
-0x0007d182,0x0002d640,0x000a8630,0x00001008,
-0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
-0x0007420a,0x000c0000,0x00062208,0x000c4117,
-0x00070630,0x00001009,0x00000000,0x000c0000,
-0x0001022e,0x00000000,0x0003a630,0x00001009,
-0x00000000,0x000c0000,0x00000036,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x0002a730,0x00001008,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0002a730,0x00001008,
-0x00000033,0x00001000,0x0002a705,0x00001008,
-0x00007a01,0x000c0000,0x000e6288,0x000d550a,
-0x0006428a,0x00000000,0x00060730,0x0000100a,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-0x00057488,0x00000000,0x00033b94,0x00081140,
-0x000183ae,0x00000000,0x000786b0,0x0000100b,
-0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-0x00042731,0x00001003,0x0007aab0,0x00034880,
-0x00048fb0,0x0000100a,0x00057488,0x00000000,
-0x00033b94,0x00081140,0x000183ae,0x00000000,
-0x000806b0,0x0000100b,0x00022f05,0x00000000,
-0x00007401,0x00091140,0x00048f05,0x000951c0,
-0x00042731,0x00001003,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x000fe19e,0x00001003,0x00000000,0x00000000,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00000f41,0x00097140,0x0000a841,0x0009b240,
-0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
-0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
-0x00055208,0x00000000,0x00010705,0x000a2880,
-0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
-0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
-0x00065308,0x000c2997,0x000d86b0,0x0000100a,
-0x0004410a,0x000d40c7,0x00000000,0x00000000,
-0x00080730,0x00001004,0x00056f0a,0x000ea105,
-0x00000000,0x00000000,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x0000273d,0x00001000,0x00000000,0x000eba44,
-0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x00000000,0x000e5084,
-0x00000000,0x000eba44,0x00087401,0x000e4782,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
-0x0007e721,0x000bed40,0x00005f25,0x000badc0,
-0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
-0x00033217,0x00003ec0,0x00065590,0x000b8e40,
-0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
-0x000283a0,0x0000100c,0x000ee388,0x00042970,
-0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
-0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
-0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
-0x00078898,0x00001000,0x00038894,0x00000032,
-0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
-0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
-0x00041705,0x0009ed40,0x00058730,0x00001400,
-0x000d7488,0x000c3a00,0x00048f05,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000}
- };
index 1b66efd9b728e153506106cf3917b17c73ec87b3..f18e5878f58b42a195df536aedde6d80a3897700 100644 (file)
@@ -54,7 +54,9 @@
 #include <linux/gameport.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
-
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -330,13 +332,146 @@ int snd_cs46xx_download(struct snd_cs46xx *chip,
        return 0;
 }
 
+static inline void memcpy_le32(void *dst, const void *src, unsigned int len)
+{
+#ifdef __LITTLE_ENDIAN
+       memcpy(dst, src, len);
+#else
+       u32 *_dst = dst;
+       const __le32 *_src = src;
+       len /= 4;
+       while (len-- > 0)
+               *_dst++ = le32_to_cpu(*_src++);
+#endif
+}
+
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 
-#include "imgs/cwc4630.h"
-#include "imgs/cwcasync.h"
-#include "imgs/cwcsnoop.h"
-#include "imgs/cwcbinhack.h"
-#include "imgs/cwcdma.h"
+static const char *module_names[CS46XX_DSP_MODULES] = {
+       "cwc4630", "cwcasync", "cwcsnoop", "cwcbinhack", "cwcdma"
+};
+
+MODULE_FIRMWARE("cs46xx/cwc4630");
+MODULE_FIRMWARE("cs46xx/cwcasync");
+MODULE_FIRMWARE("cs46xx/cwcsnoop");
+MODULE_FIRMWARE("cs46xx/cwcbinhack");
+MODULE_FIRMWARE("cs46xx/cwcdma");
+
+static void free_module_desc(struct dsp_module_desc *module)
+{
+       if (!module)
+               return;
+       kfree(module->module_name);
+       kfree(module->symbol_table.symbols);
+       if (module->segments) {
+               int i;
+               for (i = 0; i < module->nsegments; i++)
+                       kfree(module->segments[i].data);
+               kfree(module->segments);
+       }
+}
+
+/* firmware binary format:
+ * le32 nsymbols;
+ * struct {
+ *     le32 address;
+ *     char symbol_name[DSP_MAX_SYMBOL_NAME];
+ *     le32 symbol_type;
+ * } symbols[nsymbols];
+ * le32 nsegments;
+ * struct {
+ *     le32 segment_type;
+ *     le32 offset;
+ *     le32 size;
+ *     le32 data[size];
+ * } segments[nsegments];
+ */
+
+static int load_firmware(struct snd_cs46xx *chip,
+                        struct dsp_module_desc **module_ret,
+                        const char *fw_name)
+{
+       int i, err;
+       unsigned int nums, fwlen, fwsize;
+       const __le32 *fwdat;
+       struct dsp_module_desc *module = NULL;
+       const struct firmware *fw;
+       char fw_path[32];
+
+       sprintf(fw_path, "cs46xx/%s", fw_name);
+       err = request_firmware(&fw, fw_path, &chip->pci->dev);
+       if (err < 0)
+               return err;
+       fwsize = fw->size / 4;
+       if (fwsize < 2) {
+               err = -EINVAL;
+               goto error;
+       }
+
+       err = -ENOMEM;
+       module = kzalloc(sizeof(*module), GFP_KERNEL);
+       if (!module)
+               goto error;
+       module->module_name = kstrdup(fw_name, GFP_KERNEL);
+       if (!module->module_name)
+               goto error;
+
+       fwlen = 0;
+       fwdat = (const __le32 *)fw->data;
+       nums = module->symbol_table.nsymbols = le32_to_cpu(fwdat[fwlen++]);
+       if (nums >= 40)
+               goto error_inval;
+       module->symbol_table.symbols =
+               kcalloc(nums, sizeof(struct dsp_symbol_entry), GFP_KERNEL);
+       if (!module->symbol_table.symbols)
+               goto error;
+       for (i = 0; i < nums; i++) {
+               struct dsp_symbol_entry *entry =
+                       &module->symbol_table.symbols[i];
+               if (fwlen + 2 + DSP_MAX_SYMBOL_NAME / 4 > fwsize)
+                       goto error_inval;
+               entry->address = le32_to_cpu(fwdat[fwlen++]);
+               memcpy(entry->symbol_name, &fwdat[fwlen], DSP_MAX_SYMBOL_NAME - 1);
+               fwlen += DSP_MAX_SYMBOL_NAME / 4;
+               entry->symbol_type = le32_to_cpu(fwdat[fwlen++]);
+       }
+
+       if (fwlen >= fwsize)
+               goto error_inval;
+       nums = module->nsegments = le32_to_cpu(fwdat[fwlen++]);
+       if (nums > 10)
+               goto error_inval;
+       module->segments =
+               kcalloc(nums, sizeof(struct dsp_segment_desc), GFP_KERNEL);
+       if (!module->segments)
+               goto error;
+       for (i = 0; i < nums; i++) {
+               struct dsp_segment_desc *entry = &module->segments[i];
+               if (fwlen + 3 > fwsize)
+                       goto error_inval;
+               entry->segment_type = le32_to_cpu(fwdat[fwlen++]);
+               entry->offset = le32_to_cpu(fwdat[fwlen++]);
+               entry->size = le32_to_cpu(fwdat[fwlen++]);
+               if (fwlen + entry->size > fwsize)
+                       goto error_inval;
+               entry->data = kmalloc(entry->size * 4, GFP_KERNEL);
+               if (!entry->data)
+                       goto error;
+               memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4);
+               fwlen += entry->size;
+       }
+
+       *module_ret = module;
+       release_firmware(fw);
+       return 0;
+
+ error_inval:
+       err = -EINVAL;
+ error:
+       free_module_desc(module);
+       release_firmware(fw);
+       return err;
+}
 
 int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
                          unsigned long offset,
@@ -361,20 +496,63 @@ int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
 
 #else /* old DSP image */
 
-#include "cs46xx_image.h"
+struct ba1_struct {
+       struct {
+               u32 offset;
+               u32 size;
+       } memory[BA1_MEMORY_COUNT];
+       u32 map[BA1_DWORD_SIZE];
+};
+
+MODULE_FIRMWARE("cs46xx/ba1");
+
+static int load_firmware(struct snd_cs46xx *chip)
+{
+       const struct firmware *fw;
+       int i, size, err;
+
+       err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
+       if (err < 0)
+               return err;
+       if (fw->size != sizeof(*chip->ba1)) {
+               err = -EINVAL;
+               goto error;
+       }
+
+       chip->ba1 = vmalloc(sizeof(*chip->ba1));
+       if (!chip->ba1) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));
+
+       /* sanity check */
+       size = 0;
+       for (i = 0; i < BA1_MEMORY_COUNT; i++)
+               size += chip->ba1->memory[i].size;
+       if (size > BA1_DWORD_SIZE * 4)
+               err = -EINVAL;
+
+ error:
+       release_firmware(fw);
+       return err;
+}
 
 int snd_cs46xx_download_image(struct snd_cs46xx *chip)
 {
        int idx, err;
-       unsigned long offset = 0;
+       unsigned int offset = 0;
+       struct ba1_struct *ba1 = chip->ba1;
 
        for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
-               if ((err = snd_cs46xx_download(chip,
-                                              &BA1Struct.map[offset],
-                                              BA1Struct.memory[idx].offset,
-                                              BA1Struct.memory[idx].size)) < 0)
+               err = snd_cs46xx_download(chip,
+                                         &ba1->map[offset],
+                                         ba1->memory[idx].offset,
+                                         ba1->memory[idx].size);
+               if (err < 0)
                        return err;
-               offset += BA1Struct.memory[idx].size >> 2;
+               offset += ba1->memory[idx].size >> 2;
        }       
        return 0;
 }
@@ -2798,6 +2976,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
                cs46xx_dsp_spos_destroy(chip);
                chip->dsp_spos_instance = NULL;
        }
+       for (idx = 0; idx < CS46XX_DSP_MODULES; idx++)
+               free_module_desc(chip->modules[idx]);
+#else
+       vfree(chip->ba1);
 #endif
        
 #ifdef CONFIG_PM_SLEEP
@@ -3067,6 +3249,11 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
 int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
 {      
        unsigned int tmp;
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+       int i;
+#endif
+       int err;
+
        /*
         *  Reset the processor.
         */
@@ -3075,45 +3262,33 @@ int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
         *  Download the image to the processor.
         */
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-#if 0
-       if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
-               snd_printk(KERN_ERR "image download error\n");
-               return -EIO;
-       }
-#endif
-
-       if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwc4630]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcasync]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcdma]\n");
-               return -EIO;
+       for (i = 0; i < CS46XX_DSP_MODULES; i++) {
+               err = load_firmware(chip, &chip->modules[i], module_names[i]);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "firmware load error [%s]\n",
+                                  module_names[i]);
+                       return err;
+               }
+               err = cs46xx_dsp_load_module(chip, chip->modules[i]);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "image download error [%s]\n",
+                                  module_names[i]);
+                       return err;
+               }
        }
 
        if (cs46xx_dsp_scb_and_task_init(chip) < 0)
                return -EIO;
 #else
+       err = load_firmware(chip);
+       if (err < 0)
+               return err;
+
        /* old image */
-       if (snd_cs46xx_download_image(chip) < 0) {
+       err = snd_cs46xx_download_image(chip);
+       if (err < 0) {
                snd_printk(KERN_ERR "image download error\n");
-               return -EIO;
+               return err;
        }
 
        /*
diff --git a/sound/pci/cs46xx/imgs/cwc4630.h b/sound/pci/cs46xx/imgs/cwc4630.h
deleted file mode 100644 (file)
index 37c4f13..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/* generated from cwc4630.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwc4630_H__
-#define __HEADER_cwc4630_H__
-
-static struct dsp_symbol_entry cwc4630_symbols[] = {
-  { 0x0000, "BEGINADDRESS",0x00 },
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0070, "SPOSCB",0x02 },
-  { 0x0107, "TASKTREETHREAD",0x03 },
-  { 0x013c, "TASKTREEHEADERCODE",0x03 },
-  { 0x0145, "FGTASKTREEHEADERCODE",0x03 },
-  { 0x0169, "NULLALGORITHM",0x03 },
-  { 0x016d, "HFGEXECCHILD",0x03 },
-  { 0x016e, "HFGEXECCHILD_98",0x03 },
-  { 0x0170, "HFGEXECCHILD_PUSH1IND",0x03 },
-  { 0x0173, "HFGEXECSIBLING",0x03 },
-  { 0x0175, "HFGEXECSIBLING_298",0x03 },
-  { 0x0176, "HFGEXECSIBLING_2IND1",0x03 },
-  { 0x0179, "S16_CODECOUTPUTTASK",0x03 },
-  { 0x0194, "#CODE_END",0x00 },
-}; /* cwc4630 symbols */
-
-static u32 cwc4630_code[] = {
-/* BEGINADDRESS */
-/* 0000 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0002 */ 0x00001705,0x00001400,0x000a411e,0x00001003,
-/* 0004 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0006 */ 0x00009705,0x00001400,0x000a411e,0x00001003,
-/* 0008 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 000A */ 0x00011705,0x00001400,0x000a411e,0x00001003,
-/* 000C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 000E */ 0x00019705,0x00001400,0x000a411e,0x00001003,
-/* 0010 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0012 */ 0x00021705,0x00001400,0x000a411e,0x00001003,
-/* 0014 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0016 */ 0x00029705,0x00001400,0x000a411e,0x00001003,
-/* 0018 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 001A */ 0x00031705,0x00001400,0x000a411e,0x00001003,
-/* 001C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 001E */ 0x00039705,0x00001400,0x000a411e,0x00001003,
-/* 0020 */ 0x000fe19e,0x00001003,0x0009c730,0x00001003,
-/* 0022 */ 0x0008e19c,0x00001003,0x000083c1,0x00093040,
-/* 0024 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0026 */ 0x00009705,0x00001400,0x000a211e,0x00001003,
-/* 0028 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 002A */ 0x00011705,0x00001400,0x000a211e,0x00001003,
-/* 002C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 002E */ 0x00019705,0x00001400,0x000a211e,0x00001003,
-/* 0030 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0032 */ 0x00021705,0x00001400,0x000a211e,0x00001003,
-/* 0034 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0036 */ 0x00029705,0x00001400,0x000a211e,0x00001003,
-/* 0038 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 003A */ 0x00031705,0x00001400,0x000a211e,0x00001003,
-/* 003C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 003E */ 0x00039705,0x00001400,0x000a211e,0x00001003,
-/* 0040 */ 0x0001a730,0x00001008,0x000e2730,0x00001002,
-/* 0042 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0044 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0046 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0048 */ 0x00000000,0x00000000,0x000f619c,0x00001003,
-/* 004A */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
-/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 004E */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0050 */ 0x00000000,0x000c0000,0x00000000,0x00000000,
-/* 0052 */ 0x0000373c,0x00001000,0x00000000,0x00000000,
-/* 0054 */ 0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-/* 0056 */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005A */ 0x00000000,0x00000000,0x0000273c,0x00001000,
-/* 005C */ 0x00000033,0x00001000,0x000e679e,0x00001003,
-/* 005E */ 0x00007705,0x00001400,0x000ac71e,0x00001003,
-/* 0060 */ 0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-/* 0062 */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0066 */ 0x00000000,0x00000000,0x0000a730,0x00001003,
-/* 0068 */ 0x00000033,0x00001000,0x0007f801,0x000c0000,
-/* 006A */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006E */ 0x00000000,0x00000000,0x00000000,0x000c0000,
-/* 0070 */ 0x00000032,0x00001000,0x0000273d,0x00001000,
-/* 0072 */ 0x0004a730,0x00001003,0x00000f41,0x00097140,
-/* 0074 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-/* 0076 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-/* 0078 */ 0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-/* 007A */ 0x00002725,0x000aa400,0x00013705,0x00093a00,
-/* 007C */ 0x0000002e,0x0009d6c0,0x0002ef8a,0x00000000,
-/* 007E */ 0x00040630,0x00001004,0x0004ef0a,0x000eb785,
-/* 0080 */ 0x0003fc8a,0x00000000,0x00000000,0x000c70e0,
-/* 0082 */ 0x0007d182,0x0002c640,0x00008630,0x00001004,
-/* 0084 */ 0x000799b8,0x0002c6c0,0x00031705,0x00092240,
-/* 0086 */ 0x00039f05,0x000932c0,0x0003520a,0x00000000,
-/* 0088 */ 0x00070731,0x0000100b,0x00010705,0x000b20c0,
-/* 008A */ 0x00000000,0x000eba44,0x00032108,0x000c60c4,
-/* 008C */ 0x00065208,0x000c2917,0x000486b0,0x00001007,
-/* 008E */ 0x00012f05,0x00036880,0x0002818e,0x000c0000,
-/* 0090 */ 0x0004410a,0x00000000,0x00048630,0x00001007,
-/* 0092 */ 0x00029705,0x000c0000,0x00000000,0x00000000,
-/* 0094 */ 0x00003fc1,0x0003fc40,0x000037c1,0x00091b40,
-/* 0096 */ 0x00003fc1,0x000911c0,0x000037c1,0x000957c0,
-/* 0098 */ 0x00003fc1,0x000951c0,0x000037c1,0x00000000,
-/* 009A */ 0x00003fc1,0x000991c0,0x000037c1,0x00000000,
-/* 009C */ 0x00003fc1,0x0009d1c0,0x000037c1,0x00000000,
-/* 009E */ 0x0001ccc1,0x000915c0,0x0001c441,0x0009d800,
-/* 00A0 */ 0x0009cdc1,0x00091240,0x0001c541,0x00091d00,
-/* 00A2 */ 0x0009cfc1,0x00095240,0x0001c741,0x00095c80,
-/* 00A4 */ 0x000e8ca9,0x00099240,0x000e85ad,0x00095640,
-/* 00A6 */ 0x00069ca9,0x00099d80,0x000e952d,0x00099640,
-/* 00A8 */ 0x000eaca9,0x0009d6c0,0x000ea5ad,0x00091a40,
-/* 00AA */ 0x0006bca9,0x0009de80,0x000eb52d,0x00095a40,
-/* 00AC */ 0x000ecca9,0x00099ac0,0x000ec5ad,0x0009da40,
-/* 00AE */ 0x000edca9,0x0009d300,0x000a6e0a,0x00001000,
-/* 00B0 */ 0x000ed52d,0x00091e40,0x000eeca9,0x00095ec0,
-/* 00B2 */ 0x000ee5ad,0x00099e40,0x0006fca9,0x00002500,
-/* 00B4 */ 0x000fb208,0x000c59a0,0x000ef52d,0x0009de40,
-/* 00B6 */ 0x00068ca9,0x000912c1,0x000683ad,0x00095241,
-/* 00B8 */ 0x00020f05,0x000991c1,0x00000000,0x00000000,
-/* 00BA */ 0x00086f88,0x00001000,0x0009cf81,0x000b5340,
-/* 00BC */ 0x0009c701,0x000b92c0,0x0009de81,0x000bd300,
-/* 00BE */ 0x0009d601,0x000b1700,0x0001fd81,0x000b9d80,
-/* 00C0 */ 0x0009f501,0x000b57c0,0x000a0f81,0x000bd740,
-/* 00C2 */ 0x00020701,0x000b5c80,0x000a1681,0x000b97c0,
-/* 00C4 */ 0x00021601,0x00002500,0x000a0701,0x000b9b40,
-/* 00C6 */ 0x000a0f81,0x000b1bc0,0x00021681,0x00002d00,
-/* 00C8 */ 0x00020f81,0x000bd800,0x000a0701,0x000b5bc0,
-/* 00CA */ 0x00021601,0x00003500,0x000a0f81,0x000b5f40,
-/* 00CC */ 0x000a0701,0x000bdbc0,0x00021681,0x00003d00,
-/* 00CE */ 0x00020f81,0x000b1d00,0x000a0701,0x000b1fc0,
-/* 00D0 */ 0x00021601,0x00020500,0x00020f81,0x000b1341,
-/* 00D2 */ 0x000a0701,0x000b9fc0,0x00021681,0x00020d00,
-/* 00D4 */ 0x00020f81,0x000bde80,0x000a0701,0x000bdfc0,
-/* 00D6 */ 0x00021601,0x00021500,0x00020f81,0x000b9341,
-/* 00D8 */ 0x00020701,0x000b53c1,0x00021681,0x00021d00,
-/* 00DA */ 0x000a0f81,0x000d0380,0x0000b601,0x000b15c0,
-/* 00DC */ 0x00007b01,0x00000000,0x00007b81,0x000bd1c0,
-/* 00DE */ 0x00007b01,0x00000000,0x00007b81,0x000b91c0,
-/* 00E0 */ 0x00007b01,0x000b57c0,0x00007b81,0x000b51c0,
-/* 00E2 */ 0x00007b01,0x000b1b40,0x00007b81,0x000b11c0,
-/* 00E4 */ 0x00087b01,0x000c3dc0,0x0007e488,0x000d7e45,
-/* 00E6 */ 0x00000000,0x000d7a44,0x0007e48a,0x00000000,
-/* 00E8 */ 0x00011f05,0x00084080,0x00000000,0x00000000,
-/* 00EA */ 0x00001705,0x000b3540,0x00008a01,0x000bf040,
-/* 00EC */ 0x00007081,0x000bb5c0,0x00055488,0x00000000,
-/* 00EE */ 0x0000d482,0x0003fc40,0x0003fc88,0x00000000,
-/* 00F0 */ 0x0001e401,0x000b3a00,0x0001ec81,0x000bd6c0,
-/* 00F2 */ 0x0002ef88,0x000e7784,0x00056f08,0x00000000,
-/* 00F4 */ 0x000d86b0,0x00001007,0x00008281,0x000bb240,
-/* 00F6 */ 0x0000b801,0x000b7140,0x00007888,0x00000000,
-/* 00F8 */ 0x0000073c,0x00001000,0x0007f188,0x000c0000,
-/* 00FA */ 0x00000000,0x00000000,0x00055288,0x000c555c,
-/* 00FC */ 0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-/* 00FE */ 0x0000fa88,0x00000000,0x00000032,0x00001000,
-/* 0100 */ 0x0000073d,0x00001000,0x0007f188,0x000c0000,
-/* 0102 */ 0x00000000,0x00000000,0x0008c01c,0x00001003,
-/* 0104 */ 0x00002705,0x00001008,0x0008b201,0x000c1392,
-/* 0106 */ 0x0000ba01,0x00000000,
-/* TASKTREETHREAD */
-/* 0107 */ 0x00008731,0x00001400,0x0004c108,0x000fe0c4,
-/* 0109 */ 0x00057488,0x00000000,0x000a6388,0x00001001,
-/* 010B */ 0x0008b334,0x000bc141,0x0003020e,0x00000000,
-/* 010D */ 0x000986b0,0x00001008,0x00003625,0x000c5dfa,
-/* 010F */ 0x000a638a,0x00001001,0x0008020e,0x00001002,
-/* 0111 */ 0x0009a6b0,0x00001008,0x0007f301,0x00000000,
-/* 0113 */ 0x00000000,0x00000000,0x00002725,0x000a8c40,
-/* 0115 */ 0x000000ae,0x00000000,0x000e8630,0x00001008,
-/* 0117 */ 0x00000000,0x000c74e0,0x0007d182,0x0002d640,
-/* 0119 */ 0x000b8630,0x00001008,0x000799b8,0x0002d6c0,
-/* 011B */ 0x0000748a,0x000c3ec5,0x0007420a,0x000c0000,
-/* 011D */ 0x00062208,0x000c4117,0x000a0630,0x00001009,
-/* 011F */ 0x00000000,0x000c0000,0x0001022e,0x00000000,
-/* 0121 */ 0x0006a630,0x00001009,0x00000032,0x00001000,
-/* 0123 */ 0x000ca21c,0x00001003,0x00005a02,0x00000000,
-/* 0125 */ 0x0001a630,0x00001009,0x00000000,0x000c0000,
-/* 0127 */ 0x00000036,0x00001000,0x00000000,0x00000000,
-/* 0129 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 012B */ 0x00000000,0x00000000,0x0003a730,0x00001008,
-/* 012D */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
-/* 012F */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0131 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0133 */ 0x0003a730,0x00001008,0x00000033,0x00001000,
-/* 0135 */ 0x0003a705,0x00001008,0x00007a01,0x000c0000,
-/* 0137 */ 0x000e6288,0x000d550a,0x0006428a,0x00000000,
-/* 0139 */ 0x00090730,0x0000100a,0x00000000,0x000c0000,
-/* 013B */ 0x00000000,0x00000000,
-/* TASKTREEHEADERCODE */
-/* 013C */ 0x0007aab0,0x00034880,0x000a8fb0,0x0000100b,
-/* 013E */ 0x00057488,0x00000000,0x00033b94,0x00081140,
-/* 0140 */ 0x000183ae,0x00000000,0x000a86b0,0x0000100b,
-/* 0142 */ 0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-/* 0144 */ 0x00042731,0x00001003,
-/* FGTASKTREEHEADERCODE */
-/* 0145 */ 0x0007aab0,0x00034880,0x00078fb0,0x0000100a,
-/* 0147 */ 0x00057488,0x00000000,0x00033b94,0x00081140,
-/* 0149 */ 0x000183ae,0x00000000,0x000b06b0,0x0000100b,
-/* 014B */ 0x00022f05,0x00000000,0x00007401,0x00091140,
-/* 014D */ 0x00048f05,0x000951c0,0x00042731,0x00001003,
-/* 014F */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
-/* 0151 */ 0x00080000,0x000bffc7,0x000fe19e,0x00001003,
-/* 0153 */ 0x00000000,0x00000000,0x0008e19c,0x00001003,
-/* 0155 */ 0x000083c1,0x00093040,0x00000f41,0x00097140,
-/* 0157 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-/* 0159 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-/* 015B */ 0x00000000,0x000fdc44,0x00055208,0x00000000,
-/* 015D */ 0x00010705,0x000a2880,0x0000a23a,0x00093a00,
-/* 015F */ 0x0003fc8a,0x000df6c5,0x0004ef0a,0x000c0000,
-/* 0161 */ 0x00012f05,0x00036880,0x00065308,0x000c2997,
-/* 0163 */ 0x000086b0,0x0000100b,0x0004410a,0x000d40c7,
-/* 0165 */ 0x00000000,0x00000000,0x00088730,0x00001004,
-/* 0167 */ 0x00056f0a,0x000ea105,0x00000000,0x00000000,
-/* NULLALGORITHM */
-/* 0169 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
-/* 016B */ 0x00080000,0x000bffc7,0x0000273d,0x00001000,
-/* HFGEXECCHILD */
-/* 016D */ 0x00000000,0x000eba44,
-/* HFGEXECCHILD_98 */
-/* 016E */ 0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-/* HFGEXECCHILD_PUSH1IND */
-/* 0170 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 0172 */ 0x00006a88,0x000c75c4,
-/* HFGEXECSIBLING */
-/* 0173 */ 0x00000000,0x000e5084,0x00000000,0x000eba44,
-/* HFGEXECSIBLING_298 */
-/* 0175 */ 0x00087401,0x000e4782,
-/* HFGEXECSIBLING_2IND1 */
-/* 0176 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 0178 */ 0x00006a88,0x000c75c4,
-/* S16_CODECOUTPUTTASK */
-/* 0179 */ 0x0007c108,0x000c0000,0x0007e721,0x000bed40,
-/* 017B */ 0x00005f25,0x000badc0,0x0003ba97,0x000beb80,
-/* 017D */ 0x00065590,0x000b2e00,0x00033217,0x00003ec0,
-/* 017F */ 0x00065590,0x000b8e40,0x0003ed80,0x000491c0,
-/* 0181 */ 0x00073fb0,0x00074c80,0x000583a0,0x0000100c,
-/* 0183 */ 0x000ee388,0x00042970,0x00008301,0x00021ef2,
-/* 0185 */ 0x000b8f14,0x0000000f,0x000c4d8d,0x0000001b,
-/* 0187 */ 0x000d6dc2,0x000e06c6,0x000032ac,0x000c3916,
-/* 0189 */ 0x0004edc2,0x00074c80,0x00078898,0x00001000,
-/* 018B */ 0x00038894,0x00000032,0x000c4d8d,0x00092e1b,
-/* 018D */ 0x000d6dc2,0x000e06c6,0x0004edc2,0x000c1956,
-/* 018F */ 0x0000722c,0x00034a00,0x00041705,0x0009ed40,
-/* 0191 */ 0x00058730,0x00001400,0x000d7488,0x000c3a00,
-/* 0193 */ 0x00048f05,0x00000000
-};
-/* #CODE_END */
-
-static u32 cwc4630_parameter[] = {
-/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0008 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0018 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 001C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0028 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 002C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0030 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0038 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 003C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0040 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0048 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0070 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0074 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0078 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 007C */ 0x00000000,0x00000000,0x00000000,0x00000000
-}; /* #PARAMETER_END */
-
-
-static struct dsp_segment_desc cwc4630_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code },
-  { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter },
-};
-
-static struct dsp_module_desc cwc4630_module = {
-  "cwc4630",
-  {
-    38,
-    cwc4630_symbols
-  },
-  2,
-  cwc4630_segments,
-};
-
-#endif /* __HEADER_cwc4630_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcasync.h b/sound/pci/cs46xx/imgs/cwcasync.h
deleted file mode 100644 (file)
index 70e63e1..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* generated from cwcasync.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcasync_H__
-#define __HEADER_cwcasync_H__
-
-static struct dsp_symbol_entry cwcasync_symbols[] = {
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0000, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x0000, "SPIOWRITE",0x03 },
-  { 0x000d, "S16_ASYNCCODECINPUTTASK",0x03 },
-  { 0x0043, "SPDIFITASK",0x03 },
-  { 0x007b, "SPDIFOTASK",0x03 },
-  { 0x0097, "ASYNCHFGTXCODE",0x03 },
-  { 0x00be, "ASYNCHFGRXCODE",0x03 },
-  { 0x00db, "#CODE_END",0x00 },
-}; /* cwcasync symbols */
-
-static u32 cwcasync_code[] = {
-/* OVERLAYBEGINADDRESS */
-/* 0000 */ 0x00002731,0x00001400,0x00003725,0x000a8440,
-/* 0002 */ 0x000000ae,0x00000000,0x00060630,0x00001000,
-/* 0004 */ 0x00000000,0x000c7560,0x00075282,0x0002d640,
-/* 0006 */ 0x00021705,0x00000000,0x00072ab8,0x0002d6c0,
-/* 0008 */ 0x00020630,0x00001000,0x000c74c2,0x000d4b82,
-/* 000A */ 0x000475c2,0x00000000,0x0003430a,0x000c0000,
-/* 000C */ 0x00042730,0x00001400,
-/* S16_ASYNCCODECINPUTTASK */
-/* 000D */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x00000000,
-/* 000F */ 0x000fa418,0x0000101f,0x0005d402,0x0001c500,
-/* 0011 */ 0x000f0630,0x00001000,0x00004418,0x00001380,
-/* 0013 */ 0x000e243d,0x000d394a,0x00049705,0x00000000,
-/* 0015 */ 0x0007d530,0x000b4240,0x000e00f2,0x00001000,
-/* 0017 */ 0x00009134,0x000ca20a,0x00004c90,0x00001000,
-/* 0019 */ 0x0005d705,0x00000000,0x00004f25,0x00098240,
-/* 001B */ 0x00004725,0x00000000,0x0000e48a,0x00000000,
-/* 001D */ 0x00027295,0x0009c2c0,0x0003df25,0x00000000,
-/* 001F */ 0x000e8030,0x00001001,0x0005f718,0x000ac600,
-/* 0021 */ 0x0007cf30,0x000c2a01,0x00082630,0x00001001,
-/* 0023 */ 0x000504a0,0x00001001,0x00029314,0x000bcb80,
-/* 0025 */ 0x0003cf25,0x000b0e00,0x0004f5c0,0x00000000,
-/* 0027 */ 0x00049118,0x000d888a,0x0007dd02,0x000c6efa,
-/* 0029 */ 0x00000000,0x00000000,0x0004f5c0,0x00069c80,
-/* 002B */ 0x0000d402,0x00000000,0x000e8630,0x00001001,
-/* 002D */ 0x00079130,0x00000000,0x00049118,0x00090e00,
-/* 002F */ 0x0006c10a,0x00000000,0x00000000,0x000c0000,
-/* 0031 */ 0x0007cf30,0x00030580,0x00005725,0x00000000,
-/* 0033 */ 0x000d84a0,0x00001001,0x00029314,0x000b4780,
-/* 0035 */ 0x0003cf25,0x000b8600,0x00000000,0x00000000,
-/* 0037 */ 0x00000000,0x000c0000,0x00000000,0x00042c80,
-/* 0039 */ 0x0001dec1,0x000e488c,0x00031114,0x00000000,
-/* 003B */ 0x0004f5c2,0x00000000,0x0003640a,0x00000000,
-/* 003D */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
-/* 003F */ 0x00007001,0x00000000,0x00000734,0x00001000,
-/* 0041 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
-/* SPDIFITASK */
-/* 0043 */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x000d5384,
-/* 0045 */ 0x0007e48a,0x00000000,0x00067718,0x00001000,
-/* 0047 */ 0x0007a418,0x00001000,0x0007221a,0x00000000,
-/* 0049 */ 0x0005d402,0x00014500,0x000b8630,0x00001002,
-/* 004B */ 0x00004418,0x00001780,0x000e243d,0x000d394a,
-/* 004D */ 0x00049705,0x00000000,0x0007d530,0x000b4240,
-/* 004F */ 0x000ac0f2,0x00001002,0x00014414,0x00000000,
-/* 0051 */ 0x00004c90,0x00001000,0x0005d705,0x00000000,
-/* 0053 */ 0x00004f25,0x00098240,0x00004725,0x00000000,
-/* 0055 */ 0x0000e48a,0x00000000,0x00027295,0x0009c2c0,
-/* 0057 */ 0x0007df25,0x00000000,0x000ac030,0x00001003,
-/* 0059 */ 0x0005f718,0x000fe798,0x00029314,0x000bcb80,
-/* 005B */ 0x00000930,0x000b0e00,0x0004f5c0,0x000de204,
-/* 005D */ 0x000884a0,0x00001003,0x0007cf25,0x000e3560,
-/* 005F */ 0x00049118,0x00000000,0x00049118,0x000d888a,
-/* 0061 */ 0x0007dd02,0x000c6efa,0x0000c434,0x00030040,
-/* 0063 */ 0x000fda82,0x000c2312,0x000fdc0e,0x00001001,
-/* 0065 */ 0x00083402,0x000c2b92,0x000706b0,0x00001003,
-/* 0067 */ 0x00075a82,0x00000000,0x0000d625,0x000b0940,
-/* 0069 */ 0x0000840e,0x00001002,0x0000aabc,0x000c511e,
-/* 006B */ 0x00078730,0x00001003,0x0000aaf4,0x000e910a,
-/* 006D */ 0x0004628a,0x00000000,0x00006aca,0x00000000,
-/* 006F */ 0x00000930,0x00000000,0x0004f5c0,0x00069c80,
-/* 0071 */ 0x00046ac0,0x00000000,0x0003c40a,0x000fc898,
-/* 0073 */ 0x00049118,0x00090e00,0x0006c10a,0x00000000,
-/* 0075 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
-/* 0077 */ 0x00007001,0x00000000,0x00000734,0x00001000,
-/* 0079 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
-/* SPDIFOTASK */
-/* 007B */ 0x0006a108,0x000c0000,0x0004f4c0,0x000c3245,
-/* 007D */ 0x0000a418,0x00001000,0x0003a20a,0x00000000,
-/* 007F */ 0x00004418,0x00001380,0x000e243d,0x000d394a,
-/* 0081 */ 0x000c9705,0x000def92,0x0008c030,0x00001004,
-/* 0083 */ 0x0005f718,0x000fe798,0x00000000,0x000c0000,
-/* 0085 */ 0x00005725,0x00000000,0x000704a0,0x00001004,
-/* 0087 */ 0x00029314,0x000b4780,0x0003cf25,0x000b8600,
-/* 0089 */ 0x00000000,0x00000000,0x00000000,0x000c0000,
-/* 008B */ 0x00000000,0x00042c80,0x0001dec1,0x000e488c,
-/* 008D */ 0x00031114,0x00000000,0x0004f5c2,0x00000000,
-/* 008F */ 0x0004a918,0x00098600,0x0006c28a,0x00000000,
-/* 0091 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
-/* 0093 */ 0x00007001,0x00000000,0x00000734,0x00001000,
-/* 0095 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
-/* ASYNCHFGTXCODE */
-/* 0097 */ 0x0002a880,0x000b4e40,0x00042214,0x000e5548,
-/* 0099 */ 0x000542bf,0x00000000,0x00000000,0x000481c0,
-/* 009B */ 0x00000000,0x00000000,0x00000000,0x00000030,
-/* 009D */ 0x0000072d,0x000fbf8a,0x00077f94,0x000ea7df,
-/* 009F */ 0x0002ac95,0x000d3145,0x00002731,0x00001400,
-/* 00A1 */ 0x00006288,0x000c71c4,0x00014108,0x000e6044,
-/* 00A3 */ 0x00035408,0x00000000,0x00025418,0x000a0ec0,
-/* 00A5 */ 0x0001443d,0x000ca21e,0x00046595,0x000d730c,
-/* 00A7 */ 0x0006538e,0x00000000,0x00064630,0x00001005,
-/* 00A9 */ 0x000e7b0e,0x000df782,0x000746b0,0x00001005,
-/* 00AB */ 0x00036f05,0x000c0000,0x00043695,0x000d598c,
-/* 00AD */ 0x0005331a,0x000f2185,0x00000000,0x00000000,
-/* 00AF */ 0x000007ae,0x000bdb00,0x00040630,0x00001400,
-/* 00B1 */ 0x0005e708,0x000c0000,0x0007ef30,0x000b1c00,
-/* 00B3 */ 0x000d86a0,0x00001005,0x00066408,0x000c0000,
-/* 00B5 */ 0x00000000,0x00000000,0x00021843,0x00000000,
-/* 00B7 */ 0x00000cac,0x00062c00,0x00001dac,0x00063400,
-/* 00B9 */ 0x00002cac,0x0006cc80,0x000db943,0x000e5ca1,
-/* 00BB */ 0x00000000,0x00000000,0x0006680a,0x000f3205,
-/* 00BD */ 0x00042730,0x00001400,
-/* ASYNCHFGRXCODE */
-/* 00BE */ 0x00014108,0x000f2204,0x00025418,0x000a2ec0,
-/* 00C0 */ 0x00015dbd,0x00038100,0x00015dbc,0x00000000,
-/* 00C2 */ 0x0005e415,0x00034880,0x0001258a,0x000d730c,
-/* 00C4 */ 0x0006538e,0x000baa40,0x00060630,0x00001006,
-/* 00C6 */ 0x00067b0e,0x000ac380,0x0003ef05,0x00000000,
-/* 00C8 */ 0x0000f734,0x0001c300,0x000586b0,0x00001400,
-/* 00CA */ 0x000b6f05,0x000c3a00,0x00048f05,0x00000000,
-/* 00CC */ 0x0005b695,0x0008c380,0x0002058e,0x00000000,
-/* 00CE */ 0x000500b0,0x00001400,0x0002b318,0x000e998d,
-/* 00D0 */ 0x0006430a,0x00000000,0x00000000,0x000ef384,
-/* 00D2 */ 0x00004725,0x000c0000,0x00000000,0x000f3204,
-/* 00D4 */ 0x00004f25,0x000c0000,0x00080000,0x000e5ca1,
-/* 00D6 */ 0x000cb943,0x000e5ca1,0x0004b943,0x00000000,
-/* 00D8 */ 0x00040730,0x00001400,0x000cb943,0x000e5ca1,
-/* 00DA */ 0x0004b943,0x00000000
-};
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcasync_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code },
-};
-
-static struct dsp_module_desc cwcasync_module = {
-  "cwcasync",
-  {
-    32,
-    cwcasync_symbols
-  },
-  1,
-  cwcasync_segments,
-};
-
-#endif /* __HEADER_cwcasync_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcbinhack.h b/sound/pci/cs46xx/imgs/cwcbinhack.h
deleted file mode 100644 (file)
index f4d9368..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* generated by Benny 
-   MODIFY ON YOUR OWN RISK */
-
-#ifndef __HEADER_cwcbinhack_H__
-#define __HEADER_cwcbinhack_H__
-
-static struct dsp_symbol_entry cwcbinhack_symbols[] = {
-  { 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x02c8, "MAGICSNOOPTASK",0x03 },
-  { 0x0308, "#CODE_END",0x00 },
-}; /* cwcbinhack symbols */
-
-static u32 cwcbinhack_code[] = {
-  /* 0x02c8 */
-  0x0007bfb0,0x000bc240,0x00000c2e,0x000c6084, /* 1 */
-  0x000b8630,0x00001016,0x00006408,0x000efb84, /* 2 */
-  0x00016008,0x00000000,0x0001c088,0x000c0000, /* 3 */
-  0x000fc908,0x000e3392,0x0005f488,0x000efb84, /* 4 */
-  0x0001d402,0x000b2e00,0x0003d418,0x00001000, /* 5 */
-  0x0008d574,0x000c4293,0x00065625,0x000ea30e, /* 6 */
-  0x00096c01,0x000c6f92,0x0001a58a,0x000c6085, /* 7 */
-  0x00002f43,0x00000000,0x000e03a0,0x00001016, /* 8 */
-  0x0005e608,0x000c0000,0x00000000,0x00000000, /* 9 */
-  0x000ca108,0x000dcca1,0x00003bac,0x000c3205, /* 10 */
-  0x00073843,0x00000000,0x00010730,0x00001017, /* 11 */
-  0x0001600a,0x000c0000,0x00057488,0x00000000, /* 12 */
-  0x00000000,0x000e5084,0x00000000,0x000eba44, /* 13 */
-  0x00087401,0x000e4782,0x00000734,0x00001000, /* 14 */
-  0x00010705,0x000a6880,0x00006a88,0x000c75c4, /* 15 */
-  0x00000000,0x00000000,0x00000000,0x00000000, /* 16 */
-};
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcbinhack_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
-};
-
-static struct dsp_module_desc cwcbinhack_module = {
-  "cwcbinhack",
-  {
-    3,
-    cwcbinhack_symbols
-  },
-  1,
-  cwcbinhack_segments,
-};
-
-#endif /* __HEADER_cwcbinhack_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcdma.asp b/sound/pci/cs46xx/imgs/cwcdma.asp
deleted file mode 100644 (file)
index a65e119..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-// 
-//  Copyright(c) by Benny Sjostrand (benny@hostmobility.com)
-//
-//  This program is free software; you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation; either version 2 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-
-
-//
-// This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
-// to compile it you need a tool named SPASM 3.0 and DSP code owned by 
-// Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
-// the "ospparser"  tool will genereate the cwcdma.h file it's included from
-// the cs46xx_lib.c file.
-//
-//
-// The purpose of this code is very simple: make it possible to tranfser
-// the samples 'as they are' with no alteration from a PCMreader
-// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
-// SRC (source rate converters) task always alters the samples in somehow,
-// however it's from 48khz -> 48khz.
-// The alterations are not audible, but AC3 wont work. 
-//
-//        ...
-//         |
-// +---------------+
-// | AsynchFGTxSCB |
-// +---------------+
-//        |
-//    subListPtr
-//        |
-// +--------------+
-// |   DMAReader  |
-// +--------------+
-//        |
-//    subListPtr
-//        |
-// +-------------+
-// | PCMReader   |
-// +-------------+
-// (DMA from host)
-//
-
-struct dmaSCB
-  {
-    long  dma_reserved1[3];
-
-    short dma_reserved2:dma_outBufPtr;
-
-    short dma_unused1:dma_unused2;
-
-    long  dma_reserved3[4];
-
-    short dma_subListPtr:dma_nextSCB;
-    short dma_SPBptr:dma_entryPoint;
-
-    long  dma_strmRsConfig;
-    long  dma_strmBufPtr;
-
-    long  dma_reserved4;
-
-    VolumeControl s2m_volume;
-  };
-
-#export DMAReader
-void DMAReader()
-{
-  execChild();
-  r2 = r0->dma_subListPtr;
-  r1 = r0->nextSCB;
-       
-  rsConfig01 = r2->strmRsConfig;
-  // Load rsConfig for input buffer
-
-  rsDMA01 = r2->basicReq.daw,       ,                   tb = Z(0 - rf);
-  // Load rsDMA in case input buffer is a DMA buffer    Test to see if there is any data to transfer
-
-  if (tb) goto execSibling_2ind1 after {
-      r5 = rf + (-1);
-      r6 = r1->dma_entryPoint;           // r6 = entry point of sibling task
-      r1 = r1->dma_SPBptr,               // r1 = pointer to sibling task's SPB
-          ,   ind = r6;                  // Load entry point of sibling task
-  }
-
-  rsConfig23 = r0->dma_strmRsConfig;
-  // Load rsConfig for output buffer (never a DMA buffer)
-
-  r4 = r0->dma_outBufPtr;
-
-  rsa0 = r2->strmBufPtr;
-  // rsa0 = input buffer pointer                        
-
-  for (i = r5; i >= 0; --i)
-    after {
-      rsa2 = r4;
-      // rsa2 = output buffer pointer
-
-      nop;
-      nop;
-    }
-  //*****************************
-  // TODO: cycles to this point *
-  //*****************************
-    {
-      acc0 =  (rsd0 = *rsa0++1);
-      // get sample
-
-      nop;  // Those "nop"'s are really uggly, but there's
-      nop;  // something with DSP's pipelines which I don't
-      nop;  // understand, resulting this code to fail without
-            // having those "nop"'s (Benny)
-
-      rsa0?reqDMA = r2;
-      // Trigger DMA transfer on input stream, 
-      // if needed to replenish input buffer
-
-      nop;
-      // Yet another magic "nop" to make stuff work
-
-      ,,r98 = acc0 $+>> 0;
-      // store sample in ALU
-
-      nop;
-      // latency on load register.
-      // (this one is understandable)
-
-      *rsa2++1 = r98;
-      // store sample in output buffer
-
-      nop; // The same story
-      nop; // as above again ...
-      nop;
-    }
-  // TODO: cycles per loop iteration
-
-  r2->strmBufPtr = rsa0,,   ;
-  // Update the modified buffer pointers
-
-  r4 = rsa2;
-  // Load output pointer position into r4
-
-  r2 = r0->nextSCB;
-  // Sibling task
-
-  goto execSibling_2ind1 // takes 6 cycles
-    after {
-      r98 = r2->thisSPB:entryPoint;
-      // Load child routine entry and data address 
-
-      r1 = r9;
-      // r9 is r2->thisSPB
-
-      r0->dma_outBufPtr = r4,,
-      // Store updated output buffer pointer
-
-      ind = r8;
-      // r8 is r2->entryPoint
-    }
-}
diff --git a/sound/pci/cs46xx/imgs/cwcdma.h b/sound/pci/cs46xx/imgs/cwcdma.h
deleted file mode 100644 (file)
index 7ff0d45..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* generated from cwcdma.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcdma_H__
-#define __HEADER_cwcdma_H__
-
-static struct dsp_symbol_entry cwcdma_symbols[] = {
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0000, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x0000, "DMAREADER",0x03 },
-  { 0x0018, "#CODE_END",0x00 },
-}; /* cwcdma symbols */
-
-static u32 cwcdma_code[] = {
-/* OVERLAYBEGINADDRESS */
-/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044,
-/* 0002 */ 0x0005f608,0x00000000,0x000007ae,0x000be300,
-/* 0004 */ 0x00058630,0x00001400,0x0007afb0,0x000e9584,
-/* 0006 */ 0x00007301,0x000a9840,0x0005e708,0x000cd104,
-/* 0008 */ 0x00067008,0x00000000,0x000902a0,0x00001000,
-/* 000A */ 0x00012a01,0x000c0000,0x00000000,0x00000000,
-/* 000C */ 0x00021843,0x000c0000,0x00000000,0x000c0000,
-/* 000E */ 0x0000e101,0x000c0000,0x00000cac,0x00000000,
-/* 0010 */ 0x00080000,0x000e5ca1,0x00000000,0x000c0000,
-/* 0012 */ 0x00000000,0x00000000,0x00000000,0x00092c00,
-/* 0014 */ 0x000122c1,0x000e5084,0x00058730,0x00001400,
-/* 0016 */ 0x000d7488,0x000e4782,0x00007401,0x0001c100
-};
-
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcdma_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
-};
-
-static struct dsp_module_desc cwcdma_module = {
-  "cwcdma",
-  {
-    27,
-    cwcdma_symbols
-  },
-  1,
-  cwcdma_segments,
-};
-
-#endif /* __HEADER_cwcdma_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcsnoop.h b/sound/pci/cs46xx/imgs/cwcsnoop.h
deleted file mode 100644 (file)
index 6929d0a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* generated from cwcsnoop.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcsnoop_H__
-#define __HEADER_cwcsnoop_H__
-
-static struct dsp_symbol_entry cwcsnoop_symbols[] = {
-  { 0x0500, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x0500, "OUTPUTSNOOP",0x03 },
-  { 0x051f, "#CODE_END",0x00 },
-}; /* cwcsnoop symbols */
-
-static u32 cwcsnoop_code[] = {
-/* 0000 */ 0x0007bfb0,0x000b4e40,0x0007c088,0x000c0617,
-/* 0002 */ 0x00049705,0x00000000,0x00080630,0x00001028,
-/* 0004 */ 0x00076408,0x000efb84,0x00066008,0x00000000,
-/* 0006 */ 0x0007c908,0x000c0000,0x00046725,0x000efa44,
-/* 0008 */ 0x0005f708,0x00000000,0x0001d402,0x000b2e00,
-/* 000A */ 0x0003d418,0x00001000,0x0008d574,0x000c4293,
-/* 000C */ 0x00065625,0x000ea30e,0x00096c01,0x000c6f92,
-/* 000E */ 0x0006a58a,0x000f6085,0x00002f43,0x00000000,
-/* 0010 */ 0x000a83a0,0x00001028,0x0005e608,0x000c0000,
-/* 0012 */ 0x00000000,0x00000000,0x000ca108,0x000dcca1,
-/* 0014 */ 0x00003bac,0x000fb205,0x00073843,0x00000000,
-/* 0016 */ 0x000d8730,0x00001028,0x0006600a,0x000c0000,
-/* 0018 */ 0x00057488,0x00000000,0x00000000,0x000e5084,
-/* 001A */ 0x00000000,0x000eba44,0x00087401,0x000e4782,
-/* 001C */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 001E */ 0x00006a88,0x000c75c4
-};
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcsnoop_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
-};
-
-static struct dsp_module_desc cwcsnoop_module = {
-  "cwcsnoop",
-  {
-    3,
-    cwcsnoop_symbols
-  },
-  1,
-  cwcsnoop_segments,
-};
-
-#endif /* __HEADER_cwcsnoop_H__ */
index 902bebd3b3fb6d660a9d5f00ddca921c149a7009..c0d2835344dab60a8f2fef5f934a103d6fdd933f 100644 (file)
@@ -253,7 +253,7 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
 static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
 {
        synchronize_irq(cs5535au->irq);
-       pci_set_power_state(cs5535au->pci, 3);
+       pci_set_power_state(cs5535au->pci, PCI_D3hot);
 
        if (cs5535au->irq >= 0)
                free_irq(cs5535au->irq, cs5535au);
index b5fa583a239a5c978a1af60defe47a61886aeab0..eb86829529eb3e7f56da61324f8f16a87f3a44c6 100644 (file)
@@ -435,6 +435,11 @@ atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                return 0;
        position = src->ops->get_ca(src);
 
+       if (position < apcm->vm_block->addr) {
+               snd_printdd("ctxfi: bad ca - ca=0x%08x, vba=0x%08x, vbs=0x%08x\n", position, apcm->vm_block->addr, apcm->vm_block->size);
+               position = apcm->vm_block->addr;
+       }
+
        size = apcm->vm_block->size;
        max_cisz = src->multi * src->rsc.msr;
        max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8);
index b0e3d92c465673ddb34baf85cb251eb512652acb..772cc36f951de1929d9ef69962688cd51f502537 100644 (file)
@@ -1422,7 +1422,7 @@ static void snd_es1968_free_dmabuf(struct es1968 *chip)
 
        if (! chip->dma.area)
                return;
-       snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci));
+       snd_dma_free_pages(&chip->dma);
        while ((p = chip->buf_list.next) != &chip->buf_list) {
                struct esm_memory *chunk = list_entry(p, struct esm_memory, list);
                list_del(p);
@@ -1438,20 +1438,18 @@ snd_es1968_init_dmabuf(struct es1968 *chip)
 
        chip->dma.dev.type = SNDRV_DMA_TYPE_DEV;
        chip->dma.dev.dev = snd_dma_pci_data(chip->pci);
-       if (! snd_dma_get_reserved_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci))) {
-               err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
-                                                  snd_dma_pci_data(chip->pci),
-                                                  chip->total_bufsize, &chip->dma);
-               if (err < 0 || ! chip->dma.area) {
-                       snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n",
-                                  chip->total_bufsize);
-                       return -ENOMEM;
-               }
-               if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
-                       snd_dma_free_pages(&chip->dma);
-                       snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n");
-                       return -ENOMEM;
-               }
+       err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
+                                          snd_dma_pci_data(chip->pci),
+                                          chip->total_bufsize, &chip->dma);
+       if (err < 0 || ! chip->dma.area) {
+               snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n",
+                          chip->total_bufsize);
+               return -ENOMEM;
+       }
+       if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
+               snd_dma_free_pages(&chip->dma);
+               snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n");
+               return -ENOMEM;
        }
 
        INIT_LIST_HEAD(&chip->buf_list);
index 4cdd9ded4563247318795b3b5f259dd828ed54b3..0e53634dbbd85825249f68a7e4460b6a543d3361 100644 (file)
@@ -87,69 +87,54 @@ config SND_HDA_PATCH_LOADER
          This option turns on hwdep and reconfig features automatically.
 
 config SND_HDA_CODEC_REALTEK
-       bool "Build Realtek HD-audio codec support"
-       default y
+       tristate "Build Realtek HD-audio codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include Realtek HD-audio codec support in
+         Say Y or M here to include Realtek HD-audio codec support in
          snd-hda-intel driver, such as ALC880.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-realtek.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_REALTEK=m
 
 config SND_HDA_CODEC_ANALOG
-       bool "Build Analog Device HD-audio codec support"
-       default y
+       tristate "Build Analog Device HD-audio codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include Analog Device HD-audio codec support in
+         Say Y or M here to include Analog Device HD-audio codec support in
          snd-hda-intel driver, such as AD1986A.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-analog.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_ANALOG=m
 
 config SND_HDA_CODEC_SIGMATEL
-       bool "Build IDT/Sigmatel HD-audio codec support"
-       default y
+       tristate "Build IDT/Sigmatel HD-audio codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include IDT (Sigmatel) HD-audio codec support in
+         Say Y or M here to include IDT (Sigmatel) HD-audio codec support in
          snd-hda-intel driver, such as STAC9200.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-idt.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_SIGMATEL=m
 
 config SND_HDA_CODEC_VIA
-       bool "Build VIA HD-audio codec support"
-       default y
+       tristate "Build VIA HD-audio codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include VIA HD-audio codec support in
+         Say Y or M here to include VIA HD-audio codec support in
          snd-hda-intel driver, such as VT1708.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-via.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_VIA=m
 
 config SND_HDA_CODEC_HDMI
-       bool "Build HDMI/DisplayPort HD-audio codec support"
-       default y
+       tristate "Build HDMI/DisplayPort HD-audio codec support"
        help
-         Say Y here to include HDMI and DisplayPort HD-audio codec
+         Say Y or M here to include HDMI and DisplayPort HD-audio codec
          support in snd-hda-intel driver.  This includes all AMD/ATI,
          Intel and Nvidia HDMI/DisplayPort codecs.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-hdmi.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_HDMI=m
 
 config SND_HDA_I915
        bool
@@ -157,55 +142,43 @@ config SND_HDA_I915
        depends on DRM_I915
 
 config SND_HDA_CODEC_CIRRUS
-       bool "Build Cirrus Logic codec support"
-       default y
+       tristate "Build Cirrus Logic codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include Cirrus Logic codec support in
+         Say Y or M here to include Cirrus Logic codec support in
          snd-hda-intel driver, such as CS4206.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-cirrus.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CIRRUS=m
 
 config SND_HDA_CODEC_CONEXANT
-       bool "Build Conexant HD-audio codec support"
-       default y
+       tristate "Build Conexant HD-audio codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include Conexant HD-audio codec support in
+         Say Y or M here to include Conexant HD-audio codec support in
          snd-hda-intel driver, such as CX20549.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-conexant.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CONEXANT=m
 
 config SND_HDA_CODEC_CA0110
-       bool "Build Creative CA0110-IBG codec support"
-       default y
+       tristate "Build Creative CA0110-IBG codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include Creative CA0110-IBG codec support in
+         Say Y or M here to include Creative CA0110-IBG codec support in
          snd-hda-intel driver, found on some Creative X-Fi cards.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-ca0110.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CA0110=m
 
 config SND_HDA_CODEC_CA0132
-       bool "Build Creative CA0132 codec support"
-       default y
+       tristate "Build Creative CA0132 codec support"
        help
-         Say Y here to include Creative CA0132 codec support in
+         Say Y or M here to include Creative CA0132 codec support in
          snd-hda-intel driver.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-ca0132.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CA0132=m
 
 config SND_HDA_CODEC_CA0132_DSP
        bool "Support new DSP code for CA0132 codec"
@@ -220,37 +193,33 @@ config SND_HDA_CODEC_CA0132_DSP
          (ctefx.bin).
 
 config SND_HDA_CODEC_CMEDIA
-       bool "Build C-Media HD-audio codec support"
-       default y
+       tristate "Build C-Media HD-audio codec support"
        select SND_HDA_GENERIC
        help
-         Say Y here to include C-Media HD-audio codec support in
+         Say Y or M here to include C-Media HD-audio codec support in
          snd-hda-intel driver, such as CMI9880.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-cmedia.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_CMEDIA=m
 
 config SND_HDA_CODEC_SI3054
-       bool "Build Silicon Labs 3054 HD-modem codec support"
-       default y
+       tristate "Build Silicon Labs 3054 HD-modem codec support"
        help
-         Say Y here to include Silicon Labs 3054 HD-modem codec
+         Say Y or M here to include Silicon Labs 3054 HD-modem codec
          (and compatibles) support in snd-hda-intel driver.
 
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-si3054.
-         This module is automatically loaded at probing.
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_CODEC_SI3054=m
 
 config SND_HDA_GENERIC
-       bool "Enable generic HD-audio codec parser"
-       default y
+       tristate "Enable generic HD-audio codec parser"
        help
-         Say Y here to enable the generic HD-audio codec parser
+         Say Y or M here to enable the generic HD-audio codec parser
          in snd-hda-intel driver.
 
+comment "Set to Y if you want auto-loading the codec driver"
+       depends on SND_HDA_INTEL=y && SND_HDA_GENERIC=m
+
 config SND_HDA_POWER_SAVE_DEFAULT
        int "Default time-out for HD-audio power-save mode"
        depends on PM
index c091438286a39c3fc5d6fdf1c79fb653ea2cdf31..1fcb118e480afc77617c01c6c681f0e24891a27d 100644 (file)
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
 snd-hda-intel-$(CONFIG_SND_HDA_I915) +=        hda_i915.o
 
 snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o
-snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
 snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
 snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
 snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
@@ -12,6 +11,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
 CFLAGS_hda_codec.o := -I$(src)
 CFLAGS_hda_intel.o := -I$(src)
 
+snd-hda-codec-generic-objs :=  hda_generic.o
 snd-hda-codec-realtek-objs :=  patch_realtek.o
 snd-hda-codec-cmedia-objs :=   patch_cmedia.o
 snd-hda-codec-analog-objs :=   patch_analog.o
@@ -27,40 +27,19 @@ snd-hda-codec-hdmi-objs :=  patch_hdmi.o hda_eld.o
 # common driver
 obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
 
-# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
-ifdef CONFIG_SND_HDA_CODEC_REALTEK
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CMEDIA
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cmedia.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_ANALOG
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-analog.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-idt.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_SI3054
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CIRRUS
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CA0110
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0110.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CA0132
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0132.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CONEXANT
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_VIA
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_HDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o
-endif
+# codec drivers
+obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o
+obj-$(CONFIG_SND_HDA_CODEC_REALTEK) += snd-hda-codec-realtek.o
+obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
+obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
+obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
+obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
+obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
+obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
+obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
+obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
+obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
+obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
 
 # this must be the last entry after codec drivers;
 # otherwise the codec patches won't be hooked before the PCI probe
index 853c6a69e29e81c04c9fda91ce3500cf6a60fcbc..47ad31c6aa702c1e0783b75f7b5f9ac8ed5bc5dc 100644 (file)
@@ -414,7 +414,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);
+EXPORT_SYMBOL_GPL(snd_hda_parse_pin_defcfg);
 
 int snd_hda_get_input_pin_attr(unsigned int def_conf)
 {
@@ -435,7 +435,7 @@ int snd_hda_get_input_pin_attr(unsigned int def_conf)
                return INPUT_PIN_ATTR_FRONT;
        return INPUT_PIN_ATTR_NORMAL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
+EXPORT_SYMBOL_GPL(snd_hda_get_input_pin_attr);
 
 /**
  * hda_get_input_pin_label - Give a label for the given input pin
@@ -547,7 +547,7 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
                                       cfg->inputs[input].pin,
                                       has_multiple_pins);
 }
-EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
+EXPORT_SYMBOL_GPL(hda_get_autocfg_input_label);
 
 /* return the position of NID in the list, or -1 if not found */
 static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
@@ -721,7 +721,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
        strlcpy(label, name, maxlen);
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);
+EXPORT_SYMBOL_GPL(snd_hda_get_pin_label);
 
 int snd_hda_add_verbs(struct hda_codec *codec,
                      const struct hda_verb *list)
@@ -733,7 +733,7 @@ int snd_hda_add_verbs(struct hda_codec *codec,
        *v = list;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_verbs);
+EXPORT_SYMBOL_GPL(snd_hda_add_verbs);
 
 void snd_hda_apply_verbs(struct hda_codec *codec)
 {
@@ -743,7 +743,7 @@ void snd_hda_apply_verbs(struct hda_codec *codec)
                snd_hda_sequence_write(codec, *v);
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_apply_verbs);
+EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);
 
 void snd_hda_apply_pincfgs(struct hda_codec *codec,
                           const struct hda_pintbl *cfg)
@@ -751,7 +751,7 @@ void snd_hda_apply_pincfgs(struct hda_codec *codec,
        for (; cfg->nid; cfg++)
                snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
 }
-EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);
+EXPORT_SYMBOL_GPL(snd_hda_apply_pincfgs);
 
 static void set_pin_targets(struct hda_codec *codec,
                            const struct hda_pintbl *cfg)
@@ -822,7 +822,7 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
        if (codec->fixup_list)
                apply_fixup(codec, codec->fixup_id, action, 0);
 }
-EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);
+EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
 
 void snd_hda_pick_fixup(struct hda_codec *codec,
                        const struct hda_model_fixup *models,
@@ -880,4 +880,4 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
                codec->fixup_name = name;
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);
+EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);
index 98bce9830be0d345a7dec92f0916bd927bb48ab8..0589b39cda6e413a5ef76025638cf80a6bc025b5 100644 (file)
@@ -194,7 +194,7 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device);
+EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
 
 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
 {
@@ -231,7 +231,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
+EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
 
 void snd_hda_detach_beep_device(struct hda_codec *codec)
 {
@@ -243,7 +243,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
                kfree(beep);
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
+EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
 
 static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
 {
@@ -265,7 +265,7 @@ int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
        }
        return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get_beep);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep);
 
 int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_value *ucontrol)
@@ -288,4 +288,4 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
                return 0;
        return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep);
index 69178c4f4113fad7fb3111b57d49247c8f2ebe5c..ec4536c8d8d43c0987d43fd0ef9d07fe9a417ef4 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/async.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include <sound/asoundef.h>
@@ -83,7 +84,7 @@ int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
        mutex_unlock(&preset_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
+EXPORT_SYMBOL_GPL(snd_hda_add_codec_preset);
 
 int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
 {
@@ -92,23 +93,31 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
        mutex_unlock(&preset_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
+EXPORT_SYMBOL_GPL(snd_hda_delete_codec_preset);
 
 #ifdef CONFIG_PM
 #define codec_in_pm(codec)     ((codec)->in_pm)
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
-static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
+
+static void hda_call_pm_notify(struct hda_codec *codec, bool power_up)
 {
+       struct hda_bus *bus = codec->bus;
+
+       if ((power_up && codec->pm_up_notified) ||
+           (!power_up && !codec->pm_up_notified))
+               return;
        if (bus->ops.pm_notify)
                bus->ops.pm_notify(bus, power_up);
+       codec->pm_up_notified = power_up;
 }
+
 #else
 #define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
-#define hda_call_pm_notify(bus, state) {}
+#define hda_call_pm_notify(codec, state) {}
 #endif
 
 /**
@@ -143,7 +152,7 @@ const char *snd_hda_get_jack_location(u32 cfg)
        }
        return "UNKNOWN";
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_location);
 
 /**
  * snd_hda_get_jack_connectivity - Give a connectivity string of the jack
@@ -158,7 +167,7 @@ const char *snd_hda_get_jack_connectivity(u32 cfg)
 
        return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_connectivity);
 
 /**
  * snd_hda_get_jack_type - Give a type string of the jack
@@ -179,7 +188,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
        return jack_types[(cfg & AC_DEFCFG_DEVICE)
                                >> AC_DEFCFG_DEVICE_SHIFT];
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_type);
 
 /*
  * Compose a 32bit command word to be sent to the HD-audio controller
@@ -275,7 +284,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
                return -1;
        return res;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_read);
+EXPORT_SYMBOL_GPL(snd_hda_codec_read);
 
 /**
  * snd_hda_codec_write - send a single command without waiting for response
@@ -297,7 +306,7 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
        return codec_exec_verb(codec, cmd, flags,
                               codec->bus->sync_write ? &res : NULL);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_write);
+EXPORT_SYMBOL_GPL(snd_hda_codec_write);
 
 /**
  * snd_hda_sequence_write - sequence writes
@@ -312,7 +321,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
        for (; seq->nid; seq++)
                snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
 }
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
+EXPORT_SYMBOL_GPL(snd_hda_sequence_write);
 
 /**
  * snd_hda_get_sub_nodes - get the range of sub nodes
@@ -334,7 +343,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
        *start_id = (parm >> 16) & 0x7fff;
        return (int)(parm & 0x7fff);
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
+EXPORT_SYMBOL_GPL(snd_hda_get_sub_nodes);
 
 /* connection list element */
 struct hda_conn_list {
@@ -444,7 +453,7 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
                added = true;
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);
+EXPORT_SYMBOL_GPL(snd_hda_get_conn_list);
 
 /**
  * snd_hda_get_connections - copy connection list
@@ -476,7 +485,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
 
        return len;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+EXPORT_SYMBOL_GPL(snd_hda_get_connections);
 
 /* return CONNLIST_LEN parameter of the given widget */
 static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
@@ -625,7 +634,7 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
 
        return add_conn_list(codec, nid, len, list);
 }
-EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);
+EXPORT_SYMBOL_GPL(snd_hda_override_conn_list);
 
 /**
  * snd_hda_get_conn_index - get the connection index of the given NID
@@ -664,7 +673,7 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
        }
        return -1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
+EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
 
 
 /* return DEVLIST_LEN parameter of the given widget */
@@ -760,7 +769,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
+EXPORT_SYMBOL_GPL(snd_hda_queue_unsol_event);
 
 /*
  * process queued unsolicited events
@@ -831,6 +840,7 @@ static int snd_hda_bus_free(struct hda_bus *bus)
                bus->ops.private_free(bus);
        if (bus->workq)
                destroy_workqueue(bus->workq);
+
        kfree(bus);
        return 0;
 }
@@ -920,7 +930,7 @@ int snd_hda_bus_new(struct snd_card *card,
                *busp = bus;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_bus_new);
+EXPORT_SYMBOL_GPL(snd_hda_bus_new);
 
 #ifdef CONFIG_SND_HDA_GENERIC
 #define is_generic_config(codec) \
@@ -945,9 +955,6 @@ find_codec_preset(struct hda_codec *codec)
        const struct hda_codec_preset *preset;
        unsigned int mod_requested = 0;
 
-       if (is_generic_config(codec))
-               return NULL; /* use the generic parser */
-
  again:
        mutex_lock(&preset_mutex);
        list_for_each_entry(tbl, &hda_preset_tables, list) {
@@ -1163,7 +1170,7 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec,
 {
        return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_pincfg);
 
 /**
  * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
@@ -1198,7 +1205,7 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
                return pin->cfg;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
+EXPORT_SYMBOL_GPL(snd_hda_codec_get_pincfg);
 
 /* remember the current pinctl target value */
 int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
@@ -1212,7 +1219,7 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
        pin->target = val;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_pin_target);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_pin_target);
 
 /* return the current pinctl target value */
 int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
@@ -1224,7 +1231,7 @@ int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
                return 0;
        return pin->target;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_get_pin_target);
+EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);
 
 /**
  * snd_hda_shutup_pins - Shut up all pins
@@ -1249,7 +1256,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
        }
        codec->pins_shutup = 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
+EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);
 
 #ifdef CONFIG_PM
 /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
@@ -1329,6 +1336,28 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
        return p;
 }
 
+/*
+ * Dynamic symbol binding for the codec parsers
+ */
+#ifdef MODULE
+#define load_parser_sym(sym)           ((int (*)(struct hda_codec *))symbol_request(sym))
+#define unload_parser_addr(addr)       symbol_put_addr(addr)
+#else
+#define load_parser_sym(sym)           (sym)
+#define unload_parser_addr(addr)       do {} while (0)
+#endif
+
+#define load_parser(codec, sym) \
+       ((codec)->parser = load_parser_sym(sym))
+
+static void unload_parser(struct hda_codec *codec)
+{
+       if (codec->parser) {
+               unload_parser_addr(codec->parser);
+               codec->parser = NULL;
+       }
+}
+
 /*
  * codec destructor
  */
@@ -1352,10 +1381,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        codec->bus->caddr_tbl[codec->addr] = NULL;
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
-#ifdef CONFIG_PM
-       if (!codec->pm_down_notified) /* cancel leftover refcounts */
-               hda_call_pm_notify(codec->bus, false);
-#endif
+       hda_call_pm_notify(codec, false); /* cancel leftover refcounts */
+       unload_parser(codec);
        module_put(codec->owner);
        free_hda_cache(&codec->amp_cache);
        free_hda_cache(&codec->cmd_cache);
@@ -1363,6 +1390,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        kfree(codec->chip_name);
        kfree(codec->modelname);
        kfree(codec->wcaps);
+       codec->bus->num_codecs--;
        kfree(codec);
 }
 
@@ -1424,6 +1452,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
        INIT_LIST_HEAD(&codec->conn_list);
 
        INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
+       codec->depop_delay = -1;
 
 #ifdef CONFIG_PM
        spin_lock_init(&codec->power_lock);
@@ -1433,7 +1462,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
         * phase.
         */
        hda_keep_power_on(codec);
-       hda_call_pm_notify(bus, true);
 #endif
 
        if (codec->bus->modelname) {
@@ -1445,6 +1473,8 @@ int snd_hda_codec_new(struct hda_bus *bus,
        }
 
        list_add_tail(&codec->list, &bus->codec_list);
+       bus->num_codecs++;
+
        bus->caddr_tbl[codec_addr] = codec;
 
        codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
@@ -1486,11 +1516,14 @@ int snd_hda_codec_new(struct hda_bus *bus,
 #ifdef CONFIG_PM
        codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg,
                                        AC_PWRST_CLKSTOP);
-       if (!codec->d3_stop_clk)
-               bus->power_keep_link_on = 1;
 #endif
        codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
                                        AC_PWRST_EPSS);
+#ifdef CONFIG_PM
+       if (!codec->d3_stop_clk || !codec->epss)
+               bus->power_keep_link_on = 1;
+#endif
+
 
        /* power-up all before initialization */
        hda_set_power_state(codec, AC_PWRST_D0);
@@ -1511,7 +1544,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
        snd_hda_codec_free(codec);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_new);
+EXPORT_SYMBOL_GPL(snd_hda_codec_new);
 
 int snd_hda_codec_update_widgets(struct hda_codec *codec)
 {
@@ -1534,8 +1567,33 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
 
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
+EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets);
+
 
+#ifdef CONFIG_SND_HDA_CODEC_HDMI
+/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
+static bool is_likely_hdmi_codec(struct hda_codec *codec)
+{
+       hda_nid_t nid = codec->start_nid;
+       int i;
+
+       for (i = 0; i < codec->num_nodes; i++, nid++) {
+               unsigned int wcaps = get_wcaps(codec, nid);
+               switch (get_wcaps_type(wcaps)) {
+               case AC_WID_AUD_IN:
+                       return false; /* HDMI parser supports only HDMI out */
+               case AC_WID_AUD_OUT:
+                       if (!(wcaps & AC_WCAP_DIGITAL))
+                               return false;
+                       break;
+               }
+       }
+       return true;
+}
+#else
+/* no HDMI codec parser support */
+#define is_likely_hdmi_codec(codec)    false
+#endif /* CONFIG_SND_HDA_CODEC_HDMI */
 
 /**
  * snd_hda_codec_configure - (Re-)configure the HD-audio codec
@@ -1548,6 +1606,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
  */
 int snd_hda_codec_configure(struct hda_codec *codec)
 {
+       int (*patch)(struct hda_codec *) = NULL;
        int err;
 
        codec->preset = find_codec_preset(codec);
@@ -1557,31 +1616,42 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                        return err;
        }
 
-       if (is_generic_config(codec)) {
-               err = snd_hda_parse_generic_codec(codec);
-               goto patched;
-       }
-       if (codec->preset && codec->preset->patch) {
-               err = codec->preset->patch(codec);
-               goto patched;
+       if (!is_generic_config(codec) && codec->preset)
+               patch = codec->preset->patch;
+       if (!patch) {
+               unload_parser(codec); /* to be sure */
+               if (is_likely_hdmi_codec(codec))
+                       patch = load_parser(codec, snd_hda_parse_hdmi_codec);
+#ifdef CONFIG_SND_HDA_GENERIC
+               if (!patch)
+                       patch = load_parser(codec, snd_hda_parse_generic_codec);
+#endif
+               if (!patch) {
+                       printk(KERN_ERR "hda-codec: No codec parser is available\n");
+                       return -ENODEV;
+               }
        }
 
-       /* call the default parser */
-       err = snd_hda_parse_generic_codec(codec);
-       if (err < 0)
-               printk(KERN_ERR "hda-codec: No codec parser is available\n");
+       err = patch(codec);
+       if (err < 0) {
+               unload_parser(codec);
+               return err;
+       }
 
- patched:
-       if (!err && codec->patch_ops.unsol_event)
+       if (codec->patch_ops.unsol_event) {
                err = init_unsol_queue(codec->bus);
+               if (err < 0)
+                       return err;
+       }
+
        /* audio codec should override the mixer name */
-       if (!err && (codec->afg || !*codec->bus->card->mixername))
+       if (codec->afg || !*codec->bus->card->mixername)
                snprintf(codec->bus->card->mixername,
                         sizeof(codec->bus->card->mixername),
                         "%s %s", codec->vendor_name, codec->chip_name);
-       return err;
+       return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
+EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
 
 /* update the stream-id if changed */
 static void update_pcm_stream_id(struct hda_codec *codec,
@@ -1668,7 +1738,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
                }
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
+EXPORT_SYMBOL_GPL(snd_hda_codec_setup_stream);
 
 static void really_cleanup_stream(struct hda_codec *codec,
                                  struct hda_cvt_setup *q);
@@ -1703,7 +1773,7 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
                        p->active = 0;
        }
 }
-EXPORT_SYMBOL_HDA(__snd_hda_codec_cleanup_stream);
+EXPORT_SYMBOL_GPL(__snd_hda_codec_cleanup_stream);
 
 static void really_cleanup_stream(struct hda_codec *codec,
                                  struct hda_cvt_setup *q)
@@ -1891,7 +1961,7 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
                               HDA_HASH_KEY(nid, direction, 0),
                               read_amp_cap);
 }
-EXPORT_SYMBOL_HDA(query_amp_caps);
+EXPORT_SYMBOL_GPL(query_amp_caps);
 
 /**
  * snd_hda_override_amp_caps - Override the AMP capabilities
@@ -1911,7 +1981,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
 {
        return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps);
 }
-EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
+EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
 
 static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid,
                                 int dir)
@@ -1935,7 +2005,7 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
        return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid),
                               read_pin_cap);
 }
-EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
+EXPORT_SYMBOL_GPL(snd_hda_query_pin_caps);
 
 /**
  * snd_hda_override_pin_caps - Override the pin capabilities
@@ -1952,7 +2022,7 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
 {
        return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps);
 }
-EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
+EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps);
 
 /* read or sync the hash value with the current value;
  * call within hash_mutex
@@ -2033,7 +2103,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
        mutex_unlock(&codec->hash_mutex);
        return val;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read);
 
 static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
                            int direction, int idx, int mask, int val,
@@ -2085,7 +2155,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
 {
        return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
 
 /**
  * snd_hda_codec_amp_stereo - update the AMP stereo values
@@ -2111,7 +2181,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
                                                idx, mask, val);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
 
 /* Works like snd_hda_codec_amp_update() but it writes the value only at
  * the first access.  If the amp was already initialized / updated beforehand,
@@ -2122,7 +2192,7 @@ int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
 {
        return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
 
 int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
                                  int dir, int idx, int mask, int val)
@@ -2136,7 +2206,7 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
                                              idx, mask, val);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
 
 /**
  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
@@ -2179,7 +2249,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
        }
        mutex_unlock(&codec->hash_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
+EXPORT_SYMBOL_GPL(snd_hda_codec_resume_amp);
 
 static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
                             unsigned int ofs)
@@ -2219,7 +2289,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_info);
 
 
 static inline unsigned int
@@ -2276,7 +2346,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
                *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_get);
 
 /**
  * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
@@ -2306,7 +2376,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
        snd_hda_power_down(codec);
        return change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
 
 /**
  * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
@@ -2344,7 +2414,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
                return -EFAULT;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_tlv);
 
 /**
  * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
@@ -2372,7 +2442,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
        tlv[2] = -nums * step;
        tlv[3] = step;
 }
-EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);
 
 /* find a mixer control element with the given name */
 static struct snd_kcontrol *
@@ -2401,7 +2471,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
 {
        return find_mixer_ctl(codec, name, 0, 0);
 }
-EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
+EXPORT_SYMBOL_GPL(snd_hda_find_mixer_ctl);
 
 static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
                                    int start_idx)
@@ -2461,7 +2531,7 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
        item->flags = flags;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
+EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
 
 /**
  * snd_hda_add_nid - Assign a NID to a control element
@@ -2492,7 +2562,7 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
               kctl->id.name, kctl->id.index, index);
        return -EINVAL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_nid);
+EXPORT_SYMBOL_GPL(snd_hda_add_nid);
 
 /**
  * snd_hda_ctls_clear - Clear all controls assigned to the given codec
@@ -2543,7 +2613,7 @@ int snd_hda_lock_devices(struct hda_bus *bus)
        spin_unlock(&card->files_lock);
        return -EINVAL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_lock_devices);
+EXPORT_SYMBOL_GPL(snd_hda_lock_devices);
 
 void snd_hda_unlock_devices(struct hda_bus *bus)
 {
@@ -2554,7 +2624,7 @@ void snd_hda_unlock_devices(struct hda_bus *bus)
        card->shutdown = 0;
        spin_unlock(&card->files_lock);
 }
-EXPORT_SYMBOL_HDA(snd_hda_unlock_devices);
+EXPORT_SYMBOL_GPL(snd_hda_unlock_devices);
 
 /**
  * snd_hda_codec_reset - Clear all objects assigned to the codec
@@ -2610,6 +2680,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        codec->preset = NULL;
        codec->slave_dig_outs = NULL;
        codec->spdif_status_reset = 0;
+       unload_parser(codec);
        module_put(codec->owner);
        codec->owner = NULL;
 
@@ -2777,7 +2848,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
                *ctl_ret = kctl;
        return 0;
 }
-EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
+EXPORT_SYMBOL_GPL(__snd_hda_add_vmaster);
 
 /*
  * mute-LED control using vmaster
@@ -2854,7 +2925,7 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec,
                return -ENOMEM;
        return snd_hda_ctl_add(codec, 0, kctl);
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
+EXPORT_SYMBOL_GPL(snd_hda_add_vmaster_hook);
 
 /*
  * Call the hook with the current value for synchronization
@@ -2878,7 +2949,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
                break;
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
+EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
 
 
 /**
@@ -2898,7 +2969,7 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
        uinfo->value.integer.max = 1;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_info);
 
 /**
  * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
@@ -2924,7 +2995,7 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
                         HDA_AMP_MUTE) ? 0 : 1;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get);
 
 /**
  * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
@@ -2958,7 +3029,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
        snd_hda_power_down(codec);
        return change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
 
 /*
  * bound volume controls
@@ -2990,7 +3061,7 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get);
 
 /**
  * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
@@ -3020,7 +3091,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err < 0 ? err : change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put);
 
 /**
  * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
@@ -3043,7 +3114,7 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info);
 
 /**
  * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
@@ -3066,7 +3137,7 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get);
 
 /**
  * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
@@ -3095,7 +3166,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        return err < 0 ? err : change;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put);
 
 /**
  * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
@@ -3118,7 +3189,7 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        mutex_unlock(&codec->control_mutex);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv);
 
 struct hda_ctl_ops snd_hda_bind_vol = {
        .info = snd_hda_mixer_amp_volume_info,
@@ -3126,7 +3197,7 @@ struct hda_ctl_ops snd_hda_bind_vol = {
        .put = snd_hda_mixer_amp_volume_put,
        .tlv = snd_hda_mixer_amp_tlv
 };
-EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
+EXPORT_SYMBOL_GPL(snd_hda_bind_vol);
 
 struct hda_ctl_ops snd_hda_bind_sw = {
        .info = snd_hda_mixer_amp_switch_info,
@@ -3134,7 +3205,7 @@ struct hda_ctl_ops snd_hda_bind_sw = {
        .put = snd_hda_mixer_amp_switch_put,
        .tlv = snd_hda_mixer_amp_tlv
 };
-EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
+EXPORT_SYMBOL_GPL(snd_hda_bind_sw);
 
 /*
  * SPDIF out controls
@@ -3438,7 +3509,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
        spdif->status = convert_to_spdif_status(spdif->ctls);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);
 
 /* get the hda_spdif_out entry from the given NID
  * call within spdif_mutex lock
@@ -3455,7 +3526,7 @@ struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
        }
        return NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_out_of_nid);
 
 void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
 {
@@ -3466,7 +3537,7 @@ void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
        spdif->nid = (u16)-1;
        mutex_unlock(&codec->spdif_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_unassign);
 
 void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
 {
@@ -3482,7 +3553,7 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
        }
        mutex_unlock(&codec->spdif_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign);
 
 /*
  * SPDIF sharing with analog output
@@ -3530,7 +3601,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
        /* ATTENTION: here mout is passed as private_data, instead of codec */
        return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl);
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
+EXPORT_SYMBOL_GPL(snd_hda_create_spdif_share_sw);
 
 /*
  * SPDIF input
@@ -3638,7 +3709,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
                AC_DIG1_ENABLE;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls);
 
 /*
  * command cache
@@ -3689,7 +3760,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
        mutex_unlock(&codec->bus->cmd_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_write_cache);
 
 /**
  * snd_hda_codec_update_cache - check cache and write the cmd only when needed
@@ -3724,7 +3795,7 @@ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
        mutex_unlock(&codec->bus->cmd_mutex);
        return snd_hda_codec_write_cache(codec, nid, flags, verb, parm);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_update_cache);
 
 /**
  * snd_hda_codec_resume_cache - Resume the all commands from the cache
@@ -3756,7 +3827,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
        }
        mutex_unlock(&codec->hash_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_resume_cache);
 
 /**
  * snd_hda_sequence_write_cache - sequence writes with caching
@@ -3774,7 +3845,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
                snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
                                          seq->param);
 }
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
+EXPORT_SYMBOL_GPL(snd_hda_sequence_write_cache);
 
 /**
  * snd_hda_codec_flush_cache - Execute all pending (cached) amps / verbs
@@ -3785,7 +3856,7 @@ void snd_hda_codec_flush_cache(struct hda_codec *codec)
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache);
 
 void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
                                    unsigned int power_state)
@@ -3807,7 +3878,7 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
                                    state);
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
 
 /*
  *  supported power states check
@@ -3856,6 +3927,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
                                             hda_nid_t nid,
                                             unsigned int power_state)
 {
+       if (nid == codec->afg || nid == codec->mfg)
+               return power_state;
        if (power_state == AC_PWRST_D3 &&
            get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
            (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
@@ -3866,7 +3939,7 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
        }
        return power_state;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
+EXPORT_SYMBOL_GPL(snd_hda_codec_eapd_power_filter);
 
 /*
  * set power state of the codec, and return the power state
@@ -3881,8 +3954,10 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
 
        /* this delay seems necessary to avoid click noise at power-down */
        if (power_state == AC_PWRST_D3) {
-               /* transition time less than 10ms for power down */
-               msleep(codec->epss ? 10 : 100);
+               if (codec->depop_delay < 0)
+                       msleep(codec->epss ? 10 : 100);
+               else if (codec->depop_delay > 0)
+                       msleep(codec->depop_delay);
                flags = HDA_RW_NO_RESPONSE_FALLBACK;
        }
 
@@ -3892,9 +3967,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
                        codec->patch_ops.set_power_state(codec, fg,
                                                         power_state);
                else {
-                       snd_hda_codec_read(codec, fg, flags,
-                                          AC_VERB_SET_POWER_STATE,
-                                          power_state);
+                       state = power_state;
+                       if (codec->power_filter)
+                               state = codec->power_filter(codec, fg, state);
+                       if (state == power_state || power_state != AC_PWRST_D3)
+                               snd_hda_codec_read(codec, fg, flags,
+                                                  AC_VERB_SET_POWER_STATE,
+                                                  state);
                        snd_hda_codec_set_power_to_all(codec, fg, power_state);
                }
                state = hda_sync_power_state(codec, fg, power_state);
@@ -4000,10 +4079,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
         * in the resume / power-save sequence
         */
        hda_keep_power_on(codec);
-       if (codec->pm_down_notified) {
-               codec->pm_down_notified = 0;
-               hda_call_pm_notify(codec->bus, true);
-       }
        hda_set_power_state(codec, AC_PWRST_D0);
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
@@ -4055,7 +4130,7 @@ int snd_hda_build_controls(struct hda_bus *bus)
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_build_controls);
+EXPORT_SYMBOL_GPL(snd_hda_build_controls);
 
 /*
  * add standard channel maps if not specified
@@ -4228,7 +4303,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 
        return val;
 }
-EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
+EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format);
 
 static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,
                                  int dir)
@@ -4374,7 +4449,7 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm);
+EXPORT_SYMBOL_GPL(snd_hda_query_supported_pcm);
 
 /**
  * snd_hda_is_supported_format - Check the validity of the format
@@ -4441,7 +4516,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
 
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
+EXPORT_SYMBOL_GPL(snd_hda_is_supported_format);
 
 /*
  * PCM stuff
@@ -4519,7 +4594,7 @@ int snd_hda_codec_prepare(struct hda_codec *codec,
        mutex_unlock(&codec->bus->prepare_mutex);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_codec_prepare);
 
 void snd_hda_codec_cleanup(struct hda_codec *codec,
                           struct hda_pcm_stream *hinfo,
@@ -4529,7 +4604,7 @@ void snd_hda_codec_cleanup(struct hda_codec *codec,
        hinfo->ops.cleanup(hinfo, codec, substream);
        mutex_unlock(&codec->bus->prepare_mutex);
 }
-EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup);
 
 /* global */
 const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
@@ -4687,7 +4762,7 @@ int snd_hda_build_pcms(struct hda_bus *bus)
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
+EXPORT_SYMBOL_GPL(snd_hda_build_pcms);
 
 /**
  * snd_hda_check_board_config - compare the current codec with the config table
@@ -4743,7 +4818,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
        }
        return -1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
+EXPORT_SYMBOL_GPL(snd_hda_check_board_config);
 
 /**
  * snd_hda_check_board_codec_sid_config - compare the current codec
@@ -4804,7 +4879,7 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
        }
        return -1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
+EXPORT_SYMBOL_GPL(snd_hda_check_board_codec_sid_config);
 
 /**
  * snd_hda_add_new_ctls - create controls from the array
@@ -4854,7 +4929,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
 
 #ifdef CONFIG_PM
 static void hda_power_work(struct work_struct *work)
@@ -4877,11 +4952,8 @@ static void hda_power_work(struct work_struct *work)
        spin_unlock(&codec->power_lock);
 
        state = hda_call_codec_suspend(codec, true);
-       if (!codec->pm_down_notified &&
-           !bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
-               codec->pm_down_notified = 1;
-               hda_call_pm_notify(bus, false);
-       }
+       if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK))
+               hda_call_pm_notify(codec, false);
 }
 
 static void hda_keep_power_on(struct hda_codec *codec)
@@ -4891,6 +4963,7 @@ static void hda_keep_power_on(struct hda_codec *codec)
        codec->power_on = 1;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       hda_call_pm_notify(codec, true);
 }
 
 /* update the power on/off account with the current jiffies */
@@ -4910,8 +4983,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
 /* call this with codec->power_lock held! */
 static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
 {
-       struct hda_bus *bus = codec->bus;
-
        /* Return if power_on or transitioning to power_on, unless currently
         * powering down. */
        if ((codec->power_on || codec->power_transition > 0) &&
@@ -4938,11 +5009,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
        codec->power_transition = 1; /* avoid reentrance */
        spin_unlock(&codec->power_lock);
 
-       if (codec->pm_down_notified) {
-               codec->pm_down_notified = 0;
-               hda_call_pm_notify(bus, true);
-       }
-
        hda_call_codec_resume(codec);
 
        spin_lock(&codec->power_lock);
@@ -4985,7 +5051,7 @@ void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
                __snd_hda_power_down(codec);
        spin_unlock(&codec->power_lock);
 }
-EXPORT_SYMBOL_HDA(snd_hda_power_save);
+EXPORT_SYMBOL_GPL(snd_hda_power_save);
 
 /**
  * snd_hda_check_amp_list_power - Check the amp list and update the power
@@ -5035,7 +5101,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
+EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power);
 #endif
 
 /*
@@ -5059,7 +5125,7 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
                chmode[uinfo->value.enumerated.item].channels);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_info);
 
 /**
  * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
@@ -5080,7 +5146,7 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_get);
 
 /**
  * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
@@ -5104,7 +5170,7 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
                snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_put);
 
 /*
  * input MUX helper
@@ -5129,7 +5195,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
        strcpy(uinfo->value.enumerated.name, imux->items[index].label);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
+EXPORT_SYMBOL_GPL(snd_hda_input_mux_info);
 
 /**
  * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
@@ -5154,7 +5220,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
        *cur_val = idx;
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
+EXPORT_SYMBOL_GPL(snd_hda_input_mux_put);
 
 
 /*
@@ -5183,7 +5249,7 @@ int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
               texts[uinfo->value.enumerated.item]);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info);
+EXPORT_SYMBOL_GPL(snd_hda_enum_helper_info);
 
 /*
  * Multi-channel / digital-out PCM helper functions
@@ -5249,7 +5315,7 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus)
                        codec->patch_ops.reboot_notify(codec);
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
+EXPORT_SYMBOL_GPL(snd_hda_bus_reboot_notify);
 
 /**
  * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
@@ -5265,7 +5331,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_open);
 
 /**
  * snd_hda_multi_out_dig_prepare - prepare the digital out stream
@@ -5281,7 +5347,7 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare);
 
 /**
  * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
@@ -5294,7 +5360,7 @@ int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup);
 
 /**
  * snd_hda_multi_out_dig_close - release the digital out stream
@@ -5307,7 +5373,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close);
 
 /**
  * snd_hda_multi_out_analog_open - open analog outputs
@@ -5357,7 +5423,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
        return snd_pcm_hw_constraint_step(substream->runtime, 0,
                                          SNDRV_PCM_HW_PARAM_CHANNELS, 2);
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_open);
 
 /**
  * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
@@ -5434,7 +5500,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_prepare);
 
 /**
  * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
@@ -5465,7 +5531,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
        mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_cleanup);
 
 /**
  * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
@@ -5492,7 +5558,7 @@ unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
                return AC_PINCTL_VREF_GRD;
        return AC_PINCTL_VREF_HIZ;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);
+EXPORT_SYMBOL_GPL(snd_hda_get_default_vref);
 
 /* correct the pin ctl value for matching with the pin cap */
 unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
@@ -5543,7 +5609,7 @@ unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
 
        return val;
 }
-EXPORT_SYMBOL_HDA(snd_hda_correct_pin_ctl);
+EXPORT_SYMBOL_GPL(snd_hda_correct_pin_ctl);
 
 int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int val, bool cached)
@@ -5557,7 +5623,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
                return snd_hda_codec_write(codec, pin, 0,
                                           AC_VERB_SET_PIN_WIDGET_CONTROL, val);
 }
-EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);
+EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
 
 /**
  * snd_hda_add_imux_item - Add an item to input_mux
@@ -5591,7 +5657,7 @@ int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
        imux->num_items++;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
+EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
 
 
 #ifdef CONFIG_PM
@@ -5599,6 +5665,17 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
  * power management
  */
 
+
+static void hda_async_suspend(void *data, async_cookie_t cookie)
+{
+       hda_call_codec_suspend(data, false);
+}
+
+static void hda_async_resume(void *data, async_cookie_t cookie)
+{
+       hda_call_codec_resume(data);
+}
+
 /**
  * snd_hda_suspend - suspend the codecs
  * @bus: the HDA bus
@@ -5608,15 +5685,25 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
 int snd_hda_suspend(struct hda_bus *bus)
 {
        struct hda_codec *codec;
+       ASYNC_DOMAIN_EXCLUSIVE(domain);
 
        list_for_each_entry(codec, &bus->codec_list, list) {
                cancel_delayed_work_sync(&codec->jackpoll_work);
-               if (hda_codec_is_power_on(codec))
-                       hda_call_codec_suspend(codec, false);
+               if (hda_codec_is_power_on(codec)) {
+                       if (bus->num_codecs > 1)
+                               async_schedule_domain(hda_async_suspend, codec,
+                                                     &domain);
+                       else
+                               hda_call_codec_suspend(codec, false);
+               }
        }
+
+       if (bus->num_codecs > 1)
+               async_synchronize_full_domain(&domain);
+
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_suspend);
+EXPORT_SYMBOL_GPL(snd_hda_suspend);
 
 /**
  * snd_hda_resume - resume the codecs
@@ -5627,13 +5714,21 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend);
 int snd_hda_resume(struct hda_bus *bus)
 {
        struct hda_codec *codec;
+       ASYNC_DOMAIN_EXCLUSIVE(domain);
 
        list_for_each_entry(codec, &bus->codec_list, list) {
-               hda_call_codec_resume(codec);
+               if (bus->num_codecs > 1)
+                       async_schedule_domain(hda_async_resume, codec, &domain);
+               else
+                       hda_call_codec_resume(codec);
        }
+
+       if (bus->num_codecs > 1)
+               async_synchronize_full_domain(&domain);
+
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_resume);
+EXPORT_SYMBOL_GPL(snd_hda_resume);
 #endif /* CONFIG_PM */
 
 /*
@@ -5667,7 +5762,7 @@ void *snd_array_new(struct snd_array *array)
        }
        return snd_array_elem(array, array->used++);
 }
-EXPORT_SYMBOL_HDA(snd_array_new);
+EXPORT_SYMBOL_GPL(snd_array_new);
 
 /**
  * snd_array_free - free the given array elements
@@ -5680,7 +5775,7 @@ void snd_array_free(struct snd_array *array)
        array->alloced = 0;
        array->list = NULL;
 }
-EXPORT_SYMBOL_HDA(snd_array_free);
+EXPORT_SYMBOL_GPL(snd_array_free);
 
 /**
  * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
@@ -5701,7 +5796,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
 
        buf[j] = '\0'; /* necessary when j == 0 */
 }
-EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
+EXPORT_SYMBOL_GPL(snd_print_pcm_bits);
 
 MODULE_DESCRIPTION("HDA codec core");
 MODULE_LICENSE("GPL");
index 77db69480c195cde15ee64dd13bb18b2f81aa2de..2b5d19e48a27320d71cb0516a779af125e494a6d 100644 (file)
 #include <sound/control.h>
 #include <sound/pcm.h>
 #include <sound/hwdep.h>
-
-/*
- * nodes
- */
-#define        AC_NODE_ROOT            0x00
-
-/*
- * function group types
- */
-enum {
-       AC_GRP_AUDIO_FUNCTION = 0x01,
-       AC_GRP_MODEM_FUNCTION = 0x02,
-};
-       
-/*
- * widget types
- */
-enum {
-       AC_WID_AUD_OUT,         /* Audio Out */
-       AC_WID_AUD_IN,          /* Audio In */
-       AC_WID_AUD_MIX,         /* Audio Mixer */
-       AC_WID_AUD_SEL,         /* Audio Selector */
-       AC_WID_PIN,             /* Pin Complex */
-       AC_WID_POWER,           /* Power */
-       AC_WID_VOL_KNB,         /* Volume Knob */
-       AC_WID_BEEP,            /* Beep Generator */
-       AC_WID_VENDOR = 0x0f    /* Vendor specific */
-};
-
-/*
- * GET verbs
- */
-#define AC_VERB_GET_STREAM_FORMAT              0x0a00
-#define AC_VERB_GET_AMP_GAIN_MUTE              0x0b00
-#define AC_VERB_GET_PROC_COEF                  0x0c00
-#define AC_VERB_GET_COEF_INDEX                 0x0d00
-#define AC_VERB_PARAMETERS                     0x0f00
-#define AC_VERB_GET_CONNECT_SEL                        0x0f01
-#define AC_VERB_GET_CONNECT_LIST               0x0f02
-#define AC_VERB_GET_PROC_STATE                 0x0f03
-#define AC_VERB_GET_SDI_SELECT                 0x0f04
-#define AC_VERB_GET_POWER_STATE                        0x0f05
-#define AC_VERB_GET_CONV                       0x0f06
-#define AC_VERB_GET_PIN_WIDGET_CONTROL         0x0f07
-#define AC_VERB_GET_UNSOLICITED_RESPONSE       0x0f08
-#define AC_VERB_GET_PIN_SENSE                  0x0f09
-#define AC_VERB_GET_BEEP_CONTROL               0x0f0a
-#define AC_VERB_GET_EAPD_BTLENABLE             0x0f0c
-#define AC_VERB_GET_DIGI_CONVERT_1             0x0f0d
-#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e /* unused */
-#define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
-/* f10-f1a: GPIO */
-#define AC_VERB_GET_GPIO_DATA                  0x0f15
-#define AC_VERB_GET_GPIO_MASK                  0x0f16
-#define AC_VERB_GET_GPIO_DIRECTION             0x0f17
-#define AC_VERB_GET_GPIO_WAKE_MASK             0x0f18
-#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK  0x0f19
-#define AC_VERB_GET_GPIO_STICKY_MASK           0x0f1a
-#define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
-/* f20: AFG/MFG */
-#define AC_VERB_GET_SUBSYSTEM_ID               0x0f20
-#define AC_VERB_GET_CVT_CHAN_COUNT             0x0f2d
-#define AC_VERB_GET_HDMI_DIP_SIZE              0x0f2e
-#define AC_VERB_GET_HDMI_ELDD                  0x0f2f
-#define AC_VERB_GET_HDMI_DIP_INDEX             0x0f30
-#define AC_VERB_GET_HDMI_DIP_DATA              0x0f31
-#define AC_VERB_GET_HDMI_DIP_XMIT              0x0f32
-#define AC_VERB_GET_HDMI_CP_CTRL               0x0f33
-#define AC_VERB_GET_HDMI_CHAN_SLOT             0x0f34
-#define AC_VERB_GET_DEVICE_SEL                 0xf35
-#define AC_VERB_GET_DEVICE_LIST                        0xf36
-
-/*
- * SET verbs
- */
-#define AC_VERB_SET_STREAM_FORMAT              0x200
-#define AC_VERB_SET_AMP_GAIN_MUTE              0x300
-#define AC_VERB_SET_PROC_COEF                  0x400
-#define AC_VERB_SET_COEF_INDEX                 0x500
-#define AC_VERB_SET_CONNECT_SEL                        0x701
-#define AC_VERB_SET_PROC_STATE                 0x703
-#define AC_VERB_SET_SDI_SELECT                 0x704
-#define AC_VERB_SET_POWER_STATE                        0x705
-#define AC_VERB_SET_CHANNEL_STREAMID           0x706
-#define AC_VERB_SET_PIN_WIDGET_CONTROL         0x707
-#define AC_VERB_SET_UNSOLICITED_ENABLE         0x708
-#define AC_VERB_SET_PIN_SENSE                  0x709
-#define AC_VERB_SET_BEEP_CONTROL               0x70a
-#define AC_VERB_SET_EAPD_BTLENABLE             0x70c
-#define AC_VERB_SET_DIGI_CONVERT_1             0x70d
-#define AC_VERB_SET_DIGI_CONVERT_2             0x70e
-#define AC_VERB_SET_VOLUME_KNOB_CONTROL                0x70f
-#define AC_VERB_SET_GPIO_DATA                  0x715
-#define AC_VERB_SET_GPIO_MASK                  0x716
-#define AC_VERB_SET_GPIO_DIRECTION             0x717
-#define AC_VERB_SET_GPIO_WAKE_MASK             0x718
-#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK  0x719
-#define AC_VERB_SET_GPIO_STICKY_MASK           0x71a
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0     0x71c
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1     0x71d
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2     0x71e
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3     0x71f
-#define AC_VERB_SET_EAPD                               0x788
-#define AC_VERB_SET_CODEC_RESET                        0x7ff
-#define AC_VERB_SET_CVT_CHAN_COUNT             0x72d
-#define AC_VERB_SET_HDMI_DIP_INDEX             0x730
-#define AC_VERB_SET_HDMI_DIP_DATA              0x731
-#define AC_VERB_SET_HDMI_DIP_XMIT              0x732
-#define AC_VERB_SET_HDMI_CP_CTRL               0x733
-#define AC_VERB_SET_HDMI_CHAN_SLOT             0x734
-#define AC_VERB_SET_DEVICE_SEL                 0x735
-
-/*
- * Parameter IDs
- */
-#define AC_PAR_VENDOR_ID               0x00
-#define AC_PAR_SUBSYSTEM_ID            0x01
-#define AC_PAR_REV_ID                  0x02
-#define AC_PAR_NODE_COUNT              0x04
-#define AC_PAR_FUNCTION_TYPE           0x05
-#define AC_PAR_AUDIO_FG_CAP            0x08
-#define AC_PAR_AUDIO_WIDGET_CAP                0x09
-#define AC_PAR_PCM                     0x0a
-#define AC_PAR_STREAM                  0x0b
-#define AC_PAR_PIN_CAP                 0x0c
-#define AC_PAR_AMP_IN_CAP              0x0d
-#define AC_PAR_CONNLIST_LEN            0x0e
-#define AC_PAR_POWER_STATE             0x0f
-#define AC_PAR_PROC_CAP                        0x10
-#define AC_PAR_GPIO_CAP                        0x11
-#define AC_PAR_AMP_OUT_CAP             0x12
-#define AC_PAR_VOL_KNB_CAP             0x13
-#define AC_PAR_DEVLIST_LEN             0x15
-#define AC_PAR_HDMI_LPCM_CAP           0x20
-
-/*
- * AC_VERB_PARAMETERS results (32bit)
- */
-
-/* Function Group Type */
-#define AC_FGT_TYPE                    (0xff<<0)
-#define AC_FGT_TYPE_SHIFT              0
-#define AC_FGT_UNSOL_CAP               (1<<8)
-
-/* Audio Function Group Capabilities */
-#define AC_AFG_OUT_DELAY               (0xf<<0)
-#define AC_AFG_IN_DELAY                        (0xf<<8)
-#define AC_AFG_BEEP_GEN                        (1<<16)
-
-/* Audio Widget Capabilities */
-#define AC_WCAP_STEREO                 (1<<0)  /* stereo I/O */
-#define AC_WCAP_IN_AMP                 (1<<1)  /* AMP-in present */
-#define AC_WCAP_OUT_AMP                        (1<<2)  /* AMP-out present */
-#define AC_WCAP_AMP_OVRD               (1<<3)  /* AMP-parameter override */
-#define AC_WCAP_FORMAT_OVRD            (1<<4)  /* format override */
-#define AC_WCAP_STRIPE                 (1<<5)  /* stripe */
-#define AC_WCAP_PROC_WID               (1<<6)  /* Proc Widget */
-#define AC_WCAP_UNSOL_CAP              (1<<7)  /* Unsol capable */
-#define AC_WCAP_CONN_LIST              (1<<8)  /* connection list */
-#define AC_WCAP_DIGITAL                        (1<<9)  /* digital I/O */
-#define AC_WCAP_POWER                  (1<<10) /* power control */
-#define AC_WCAP_LR_SWAP                        (1<<11) /* L/R swap */
-#define AC_WCAP_CP_CAPS                        (1<<12) /* content protection */
-#define AC_WCAP_CHAN_CNT_EXT           (7<<13) /* channel count ext */
-#define AC_WCAP_DELAY                  (0xf<<16)
-#define AC_WCAP_DELAY_SHIFT            16
-#define AC_WCAP_TYPE                   (0xf<<20)
-#define AC_WCAP_TYPE_SHIFT             20
-
-/* supported PCM rates and bits */
-#define AC_SUPPCM_RATES                        (0xfff << 0)
-#define AC_SUPPCM_BITS_8               (1<<16)
-#define AC_SUPPCM_BITS_16              (1<<17)
-#define AC_SUPPCM_BITS_20              (1<<18)
-#define AC_SUPPCM_BITS_24              (1<<19)
-#define AC_SUPPCM_BITS_32              (1<<20)
-
-/* supported PCM stream format */
-#define AC_SUPFMT_PCM                  (1<<0)
-#define AC_SUPFMT_FLOAT32              (1<<1)
-#define AC_SUPFMT_AC3                  (1<<2)
-
-/* GP I/O count */
-#define AC_GPIO_IO_COUNT               (0xff<<0)
-#define AC_GPIO_O_COUNT                        (0xff<<8)
-#define AC_GPIO_O_COUNT_SHIFT          8
-#define AC_GPIO_I_COUNT                        (0xff<<16)
-#define AC_GPIO_I_COUNT_SHIFT          16
-#define AC_GPIO_UNSOLICITED            (1<<30)
-#define AC_GPIO_WAKE                   (1<<31)
-
-/* Converter stream, channel */
-#define AC_CONV_CHANNEL                        (0xf<<0)
-#define AC_CONV_STREAM                 (0xf<<4)
-#define AC_CONV_STREAM_SHIFT           4
-
-/* Input converter SDI select */
-#define AC_SDI_SELECT                  (0xf<<0)
-
-/* stream format id */
-#define AC_FMT_CHAN_SHIFT              0
-#define AC_FMT_CHAN_MASK               (0x0f << 0)
-#define AC_FMT_BITS_SHIFT              4
-#define AC_FMT_BITS_MASK               (7 << 4)
-#define AC_FMT_BITS_8                  (0 << 4)
-#define AC_FMT_BITS_16                 (1 << 4)
-#define AC_FMT_BITS_20                 (2 << 4)
-#define AC_FMT_BITS_24                 (3 << 4)
-#define AC_FMT_BITS_32                 (4 << 4)
-#define AC_FMT_DIV_SHIFT               8
-#define AC_FMT_DIV_MASK                        (7 << 8)
-#define AC_FMT_MULT_SHIFT              11
-#define AC_FMT_MULT_MASK               (7 << 11)
-#define AC_FMT_BASE_SHIFT              14
-#define AC_FMT_BASE_48K                        (0 << 14)
-#define AC_FMT_BASE_44K                        (1 << 14)
-#define AC_FMT_TYPE_SHIFT              15
-#define AC_FMT_TYPE_PCM                        (0 << 15)
-#define AC_FMT_TYPE_NON_PCM            (1 << 15)
-
-/* Unsolicited response control */
-#define AC_UNSOL_TAG                   (0x3f<<0)
-#define AC_UNSOL_ENABLED               (1<<7)
-#define AC_USRSP_EN                    AC_UNSOL_ENABLED
-
-/* Unsolicited responses */
-#define AC_UNSOL_RES_TAG               (0x3f<<26)
-#define AC_UNSOL_RES_TAG_SHIFT         26
-#define AC_UNSOL_RES_SUBTAG            (0x1f<<21)
-#define AC_UNSOL_RES_SUBTAG_SHIFT      21
-#define AC_UNSOL_RES_DE                        (0x3f<<15)  /* Device Entry
-                                                    * (for DP1.2 MST)
-                                                    */
-#define AC_UNSOL_RES_DE_SHIFT          15
-#define AC_UNSOL_RES_IA                        (1<<2)  /* Inactive (for DP1.2 MST) */
-#define AC_UNSOL_RES_ELDV              (1<<1)  /* ELD Data valid (for HDMI) */
-#define AC_UNSOL_RES_PD                        (1<<0)  /* pinsense detect */
-#define AC_UNSOL_RES_CP_STATE          (1<<1)  /* content protection */
-#define AC_UNSOL_RES_CP_READY          (1<<0)  /* content protection */
-
-/* Pin widget capabilies */
-#define AC_PINCAP_IMP_SENSE            (1<<0)  /* impedance sense capable */
-#define AC_PINCAP_TRIG_REQ             (1<<1)  /* trigger required */
-#define AC_PINCAP_PRES_DETECT          (1<<2)  /* presence detect capable */
-#define AC_PINCAP_HP_DRV               (1<<3)  /* headphone drive capable */
-#define AC_PINCAP_OUT                  (1<<4)  /* output capable */
-#define AC_PINCAP_IN                   (1<<5)  /* input capable */
-#define AC_PINCAP_BALANCE              (1<<6)  /* balanced I/O capable */
-/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
- *       but is marked reserved in the Intel HDA specification.
- */
-#define AC_PINCAP_LR_SWAP              (1<<7)  /* L/R swap */
-/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
- *       in HD-audio specification
- */
-#define AC_PINCAP_HDMI                 (1<<7)  /* HDMI pin */
-#define AC_PINCAP_DP                   (1<<24) /* DisplayPort pin, can
-                                                * coexist with AC_PINCAP_HDMI
-                                                */
-#define AC_PINCAP_VREF                 (0x37<<8)
-#define AC_PINCAP_VREF_SHIFT           8
-#define AC_PINCAP_EAPD                 (1<<16) /* EAPD capable */
-#define AC_PINCAP_HBR                  (1<<27) /* High Bit Rate */
-/* Vref status (used in pin cap) */
-#define AC_PINCAP_VREF_HIZ             (1<<0)  /* Hi-Z */
-#define AC_PINCAP_VREF_50              (1<<1)  /* 50% */
-#define AC_PINCAP_VREF_GRD             (1<<2)  /* ground */
-#define AC_PINCAP_VREF_80              (1<<4)  /* 80% */
-#define AC_PINCAP_VREF_100             (1<<5)  /* 100% */
-
-/* Amplifier capabilities */
-#define AC_AMPCAP_OFFSET               (0x7f<<0)  /* 0dB offset */
-#define AC_AMPCAP_OFFSET_SHIFT         0
-#define AC_AMPCAP_NUM_STEPS            (0x7f<<8)  /* number of steps */
-#define AC_AMPCAP_NUM_STEPS_SHIFT      8
-#define AC_AMPCAP_STEP_SIZE            (0x7f<<16) /* step size 0-32dB
-                                                   * in 0.25dB
-                                                   */
-#define AC_AMPCAP_STEP_SIZE_SHIFT      16
-#define AC_AMPCAP_MUTE                 (1<<31)    /* mute capable */
-#define AC_AMPCAP_MUTE_SHIFT           31
-
-/* driver-specific amp-caps: using bits 24-30 */
-#define AC_AMPCAP_MIN_MUTE             (1 << 30) /* min-volume = mute */
-
-/* Connection list */
-#define AC_CLIST_LENGTH                        (0x7f<<0)
-#define AC_CLIST_LONG                  (1<<7)
-
-/* Supported power status */
-#define AC_PWRST_D0SUP                 (1<<0)
-#define AC_PWRST_D1SUP                 (1<<1)
-#define AC_PWRST_D2SUP                 (1<<2)
-#define AC_PWRST_D3SUP                 (1<<3)
-#define AC_PWRST_D3COLDSUP             (1<<4)
-#define AC_PWRST_S3D3COLDSUP           (1<<29)
-#define AC_PWRST_CLKSTOP               (1<<30)
-#define AC_PWRST_EPSS                  (1U<<31)
-
-/* Power state values */
-#define AC_PWRST_SETTING               (0xf<<0)
-#define AC_PWRST_ACTUAL                        (0xf<<4)
-#define AC_PWRST_ACTUAL_SHIFT          4
-#define AC_PWRST_D0                    0x00
-#define AC_PWRST_D1                    0x01
-#define AC_PWRST_D2                    0x02
-#define AC_PWRST_D3                    0x03
-#define AC_PWRST_ERROR                  (1<<8)
-#define AC_PWRST_CLK_STOP_OK            (1<<9)
-#define AC_PWRST_SETTING_RESET          (1<<10)
-
-/* Processing capabilies */
-#define AC_PCAP_BENIGN                 (1<<0)
-#define AC_PCAP_NUM_COEF               (0xff<<8)
-#define AC_PCAP_NUM_COEF_SHIFT         8
-
-/* Volume knobs capabilities */
-#define AC_KNBCAP_NUM_STEPS            (0x7f<<0)
-#define AC_KNBCAP_DELTA                        (1<<7)
-
-/* HDMI LPCM capabilities */
-#define AC_LPCMCAP_48K_CP_CHNS         (0x0f<<0) /* max channels w/ CP-on */   
-#define AC_LPCMCAP_48K_NO_CHNS         (0x0f<<4) /* max channels w/o CP-on */
-#define AC_LPCMCAP_48K_20BIT           (1<<8)  /* 20b bitrate supported */
-#define AC_LPCMCAP_48K_24BIT           (1<<9)  /* 24b bitrate supported */
-#define AC_LPCMCAP_96K_CP_CHNS         (0x0f<<10) /* max channels w/ CP-on */  
-#define AC_LPCMCAP_96K_NO_CHNS         (0x0f<<14) /* max channels w/o CP-on */
-#define AC_LPCMCAP_96K_20BIT           (1<<18) /* 20b bitrate supported */
-#define AC_LPCMCAP_96K_24BIT           (1<<19) /* 24b bitrate supported */
-#define AC_LPCMCAP_192K_CP_CHNS                (0x0f<<20) /* max channels w/ CP-on */  
-#define AC_LPCMCAP_192K_NO_CHNS                (0x0f<<24) /* max channels w/o CP-on */
-#define AC_LPCMCAP_192K_20BIT          (1<<28) /* 20b bitrate supported */
-#define AC_LPCMCAP_192K_24BIT          (1<<29) /* 24b bitrate supported */
-#define AC_LPCMCAP_44K                 (1<<30) /* 44.1kHz support */
-#define AC_LPCMCAP_44K_MS              (1<<31) /* 44.1kHz-multiplies support */
-
-/* Display pin's device list length */
-#define AC_DEV_LIST_LEN_MASK           0x3f
-#define AC_MAX_DEV_LIST_LEN            64
-
-/*
- * Control Parameters
- */
-
-/* Amp gain/mute */
-#define AC_AMP_MUTE                    (1<<7)
-#define AC_AMP_GAIN                    (0x7f)
-#define AC_AMP_GET_INDEX               (0xf<<0)
-
-#define AC_AMP_GET_LEFT                        (1<<13)
-#define AC_AMP_GET_RIGHT               (0<<13)
-#define AC_AMP_GET_OUTPUT              (1<<15)
-#define AC_AMP_GET_INPUT               (0<<15)
-
-#define AC_AMP_SET_INDEX               (0xf<<8)
-#define AC_AMP_SET_INDEX_SHIFT         8
-#define AC_AMP_SET_RIGHT               (1<<12)
-#define AC_AMP_SET_LEFT                        (1<<13)
-#define AC_AMP_SET_INPUT               (1<<14)
-#define AC_AMP_SET_OUTPUT              (1<<15)
-
-/* DIGITAL1 bits */
-#define AC_DIG1_ENABLE                 (1<<0)
-#define AC_DIG1_V                      (1<<1)
-#define AC_DIG1_VCFG                   (1<<2)
-#define AC_DIG1_EMPHASIS               (1<<3)
-#define AC_DIG1_COPYRIGHT              (1<<4)
-#define AC_DIG1_NONAUDIO               (1<<5)
-#define AC_DIG1_PROFESSIONAL           (1<<6)
-#define AC_DIG1_LEVEL                  (1<<7)
-
-/* DIGITAL2 bits */
-#define AC_DIG2_CC                     (0x7f<<0)
-
-/* DIGITAL3 bits */
-#define AC_DIG3_ICT                    (0xf<<0)
-#define AC_DIG3_KAE                    (1<<7)
-
-/* Pin widget control - 8bit */
-#define AC_PINCTL_EPT                  (0x3<<0)
-#define AC_PINCTL_EPT_NATIVE           0
-#define AC_PINCTL_EPT_HBR              3
-#define AC_PINCTL_VREFEN               (0x7<<0)
-#define AC_PINCTL_VREF_HIZ             0       /* Hi-Z */
-#define AC_PINCTL_VREF_50              1       /* 50% */
-#define AC_PINCTL_VREF_GRD             2       /* ground */
-#define AC_PINCTL_VREF_80              4       /* 80% */
-#define AC_PINCTL_VREF_100             5       /* 100% */
-#define AC_PINCTL_IN_EN                        (1<<5)
-#define AC_PINCTL_OUT_EN               (1<<6)
-#define AC_PINCTL_HP_EN                        (1<<7)
-
-/* Pin sense - 32bit */
-#define AC_PINSENSE_IMPEDANCE_MASK     (0x7fffffff)
-#define AC_PINSENSE_PRESENCE           (1<<31)
-#define AC_PINSENSE_ELDV               (1<<30) /* ELD valid (HDMI) */
-
-/* EAPD/BTL enable - 32bit */
-#define AC_EAPDBTL_BALANCED            (1<<0)
-#define AC_EAPDBTL_EAPD                        (1<<1)
-#define AC_EAPDBTL_LR_SWAP             (1<<2)
-
-/* HDMI ELD data */
-#define AC_ELDD_ELD_VALID              (1<<31)
-#define AC_ELDD_ELD_DATA               0xff
-
-/* HDMI DIP size */
-#define AC_DIPSIZE_ELD_BUF             (1<<3) /* ELD buf size of packet size */
-#define AC_DIPSIZE_PACK_IDX            (0x07<<0) /* packet index */
-
-/* HDMI DIP index */
-#define AC_DIPIDX_PACK_IDX             (0x07<<5) /* packet idnex */
-#define AC_DIPIDX_BYTE_IDX             (0x1f<<0) /* byte index */
-
-/* HDMI DIP xmit (transmit) control */
-#define AC_DIPXMIT_MASK                        (0x3<<6)
-#define AC_DIPXMIT_DISABLE             (0x0<<6) /* disable xmit */
-#define AC_DIPXMIT_ONCE                        (0x2<<6) /* xmit once then disable */
-#define AC_DIPXMIT_BEST                        (0x3<<6) /* best effort */
-
-/* HDMI content protection (CP) control */
-#define AC_CPCTRL_CES                  (1<<9) /* current encryption state */
-#define AC_CPCTRL_READY                        (1<<8) /* ready bit */
-#define AC_CPCTRL_SUBTAG               (0x1f<<3) /* subtag for unsol-resp */
-#define AC_CPCTRL_STATE                        (3<<0) /* current CP request state */
-
-/* Converter channel <-> HDMI slot mapping */
-#define AC_CVTMAP_HDMI_SLOT            (0xf<<0) /* HDMI slot number */
-#define AC_CVTMAP_CHAN                 (0xf<<4) /* converter channel number */
-
-/* configuration default - 32bit */
-#define AC_DEFCFG_SEQUENCE             (0xf<<0)
-#define AC_DEFCFG_DEF_ASSOC            (0xf<<4)
-#define AC_DEFCFG_ASSOC_SHIFT          4
-#define AC_DEFCFG_MISC                 (0xf<<8)
-#define AC_DEFCFG_MISC_SHIFT           8
-#define AC_DEFCFG_MISC_NO_PRESENCE     (1<<0)
-#define AC_DEFCFG_COLOR                        (0xf<<12)
-#define AC_DEFCFG_COLOR_SHIFT          12
-#define AC_DEFCFG_CONN_TYPE            (0xf<<16)
-#define AC_DEFCFG_CONN_TYPE_SHIFT      16
-#define AC_DEFCFG_DEVICE               (0xf<<20)
-#define AC_DEFCFG_DEVICE_SHIFT         20
-#define AC_DEFCFG_LOCATION             (0x3f<<24)
-#define AC_DEFCFG_LOCATION_SHIFT       24
-#define AC_DEFCFG_PORT_CONN            (0x3<<30)
-#define AC_DEFCFG_PORT_CONN_SHIFT      30
-
-/* Display pin's device list entry */
-#define AC_DE_PD                       (1<<0)
-#define AC_DE_ELDV                     (1<<1)
-#define AC_DE_IA                       (1<<2)
-
-/* device device types (0x0-0xf) */
-enum {
-       AC_JACK_LINE_OUT,
-       AC_JACK_SPEAKER,
-       AC_JACK_HP_OUT,
-       AC_JACK_CD,
-       AC_JACK_SPDIF_OUT,
-       AC_JACK_DIG_OTHER_OUT,
-       AC_JACK_MODEM_LINE_SIDE,
-       AC_JACK_MODEM_HAND_SIDE,
-       AC_JACK_LINE_IN,
-       AC_JACK_AUX,
-       AC_JACK_MIC_IN,
-       AC_JACK_TELEPHONY,
-       AC_JACK_SPDIF_IN,
-       AC_JACK_DIG_OTHER_IN,
-       AC_JACK_OTHER = 0xf,
-};
-
-/* jack connection types (0x0-0xf) */
-enum {
-       AC_JACK_CONN_UNKNOWN,
-       AC_JACK_CONN_1_8,
-       AC_JACK_CONN_1_4,
-       AC_JACK_CONN_ATAPI,
-       AC_JACK_CONN_RCA,
-       AC_JACK_CONN_OPTICAL,
-       AC_JACK_CONN_OTHER_DIGITAL,
-       AC_JACK_CONN_OTHER_ANALOG,
-       AC_JACK_CONN_DIN,
-       AC_JACK_CONN_XLR,
-       AC_JACK_CONN_RJ11,
-       AC_JACK_CONN_COMB,
-       AC_JACK_CONN_OTHER = 0xf,
-};
-
-/* jack colors (0x0-0xf) */
-enum {
-       AC_JACK_COLOR_UNKNOWN,
-       AC_JACK_COLOR_BLACK,
-       AC_JACK_COLOR_GREY,
-       AC_JACK_COLOR_BLUE,
-       AC_JACK_COLOR_GREEN,
-       AC_JACK_COLOR_RED,
-       AC_JACK_COLOR_ORANGE,
-       AC_JACK_COLOR_YELLOW,
-       AC_JACK_COLOR_PURPLE,
-       AC_JACK_COLOR_PINK,
-       AC_JACK_COLOR_WHITE = 0xe,
-       AC_JACK_COLOR_OTHER,
-};
-
-/* Jack location (0x0-0x3f) */
-/* common case */
-enum {
-       AC_JACK_LOC_NONE,
-       AC_JACK_LOC_REAR,
-       AC_JACK_LOC_FRONT,
-       AC_JACK_LOC_LEFT,
-       AC_JACK_LOC_RIGHT,
-       AC_JACK_LOC_TOP,
-       AC_JACK_LOC_BOTTOM,
-};
-/* bits 4-5 */
-enum {
-       AC_JACK_LOC_EXTERNAL = 0x00,
-       AC_JACK_LOC_INTERNAL = 0x10,
-       AC_JACK_LOC_SEPARATE = 0x20,
-       AC_JACK_LOC_OTHER    = 0x30,
-};
-enum {
-       /* external on primary chasis */
-       AC_JACK_LOC_REAR_PANEL = 0x07,
-       AC_JACK_LOC_DRIVE_BAY,
-       /* internal */
-       AC_JACK_LOC_RISER = 0x17,
-       AC_JACK_LOC_HDMI,
-       AC_JACK_LOC_ATAPI,
-       /* others */
-       AC_JACK_LOC_MOBILE_IN = 0x37,
-       AC_JACK_LOC_MOBILE_OUT,
-};
-
-/* Port connectivity (0-3) */
-enum {
-       AC_JACK_PORT_COMPLEX,
-       AC_JACK_PORT_NONE,
-       AC_JACK_PORT_FIXED,
-       AC_JACK_PORT_BOTH,
-};
-
-/* max. codec address */
-#define HDA_MAX_CODEC_ADDRESS  0x0f
+#include <sound/hda_verbs.h>
 
 /*
  * generic arrays
@@ -673,6 +128,7 @@ struct hda_bus {
 
        /* codec linked list */
        struct list_head codec_list;
+       unsigned int num_codecs;
        /* link caddr -> codec */
        struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
 
@@ -698,7 +154,6 @@ struct hda_bus {
        unsigned int in_reset:1;        /* during reset operation */
        unsigned int power_keep_link_on:1; /* don't power off HDA link */
        unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
-       unsigned int avoid_link_reset:1; /* don't reset link at runtime PM */
 
        int primary_dig_out_type;       /* primary digital out PCM type */
 };
@@ -835,6 +290,7 @@ struct hda_codec {
        /* detected preset */
        const struct hda_codec_preset *preset;
        struct module *owner;
+       int (*parser)(struct hda_codec *codec);
        const char *vendor_name;        /* codec vendor name */
        const char *chip_name;          /* codec chip name */
        const char *modelname;  /* model name for preset */
@@ -908,7 +364,7 @@ struct hda_codec {
 #ifdef CONFIG_PM
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int d3_stop_clk:1;     /* support D3 operation without BCLK */
-       unsigned int pm_down_notified:1; /* PM notified to controller */
+       unsigned int pm_up_notified:1;  /* PM notified to controller */
        unsigned int in_pm:1;           /* suspend/resume being performed */
        int power_transition;   /* power-state in transition */
        int power_count;        /* current (global) power refcount */
@@ -937,6 +393,8 @@ struct hda_codec {
        struct snd_array jacks;
 #endif
 
+       int depop_delay; /* depop delay in ms, -1 for default delay time */
+
        /* fix-up list */
        int fixup_id;
        const struct hda_fixup *fixup_list;
@@ -1223,19 +681,6 @@ snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
                                struct snd_dma_buffer *dmab) {}
 #endif
 
-/*
- * Codec modularization
- */
-
-/* Export symbols only for communication with codec drivers;
- * When built in kernel, all HD-audio drivers are supposed to be statically
- * linked to the kernel.  Thus, the symbols don't have to (or shouldn't) be
- * exported unless it's built as a module.
- */
-#ifdef MODULE
 #define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym)
-#else
-#define EXPORT_SYMBOL_HDA(sym)
-#endif
 
 #endif /* __SOUND_HDA_CODEC_H */
index 3067ed4fe3b2f7fdb7edfca13e2b14575b9707a1..8321a97d5c05047ab2312f8c62603826041a1897 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
+#include <linux/module.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include "hda_codec.h"
@@ -47,7 +48,7 @@ int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
        mutex_init(&spec->pcm_mutex);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
+EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
 
 struct snd_kcontrol_new *
 snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
@@ -65,7 +66,7 @@ snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
                return NULL;
        return knew;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
+EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
 
 static void free_kctls(struct hda_gen_spec *spec)
 {
@@ -86,7 +87,7 @@ void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
        snd_array_free(&spec->paths);
        snd_array_free(&spec->loopback_list);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
+EXPORT_SYMBOL_GPL(snd_hda_gen_spec_free);
 
 /*
  * store user hints
@@ -266,7 +267,7 @@ struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
 {
        return get_nid_path(codec, from_nid, to_nid, 0);
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
+EXPORT_SYMBOL_GPL(snd_hda_get_nid_path);
 
 /* get the index number corresponding to the path instance;
  * the index starts from 1, for easier checking the invalid value
@@ -284,7 +285,7 @@ int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
                return 0;
        return idx + 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_path_idx);
+EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
 
 /* get the path instance corresponding to the given index number */
 struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
@@ -295,7 +296,7 @@ struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
                return NULL;
        return snd_array_elem(&spec->paths, idx - 1);
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_path_from_idx);
+EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
 
 /* check whether the given DAC is already found in any existing paths */
 static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
@@ -432,7 +433,7 @@ bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
        }
        return false;
 }
-EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
+EXPORT_SYMBOL_GPL(snd_hda_parse_nid_path);
 
 /*
  * parse the path between the given NIDs and add to the path list.
@@ -463,7 +464,7 @@ snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
        spec->paths.used--;
        return NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
+EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
 
 /* clear the given path as invalid so that it won't be picked up later */
 static void invalidate_nid_path(struct hda_codec *codec, int idx)
@@ -474,6 +475,20 @@ static void invalidate_nid_path(struct hda_codec *codec, int idx)
        memset(path, 0, sizeof(*path));
 }
 
+/* return a DAC if paired to the given pin by codec driver */
+static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
+{
+       struct hda_gen_spec *spec = codec->spec;
+       const hda_nid_t *list = spec->preferred_dacs;
+
+       if (!list)
+               return 0;
+       for (; *list; list += 2)
+               if (*list == pin)
+                       return list[1];
+       return 0;
+}
+
 /* look for an empty DAC slot */
 static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
                              bool is_digital)
@@ -759,7 +774,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
        if (enable)
                path->active = true;
 }
-EXPORT_SYMBOL_HDA(snd_hda_activate_path);
+EXPORT_SYMBOL_GPL(snd_hda_activate_path);
 
 /* if the given path is inactive, put widgets into D3 (only if suitable) */
 static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
@@ -1135,7 +1150,7 @@ const struct badness_table hda_main_out_badness = {
        .shared_clfe = BAD_SHARED_CLFE,
        .shared_surr_main = BAD_SHARED_SURROUND,
 };
-EXPORT_SYMBOL_HDA(hda_main_out_badness);
+EXPORT_SYMBOL_GPL(hda_main_out_badness);
 
 const struct badness_table hda_extra_out_badness = {
        .no_primary_dac = BAD_NO_DAC,
@@ -1145,7 +1160,7 @@ const struct badness_table hda_extra_out_badness = {
        .shared_clfe = BAD_SHARED_EXTRA_SURROUND,
        .shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
 };
-EXPORT_SYMBOL_HDA(hda_extra_out_badness);
+EXPORT_SYMBOL_GPL(hda_extra_out_badness);
 
 /* get the DAC of the primary output corresponding to the given array index */
 static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
@@ -1192,7 +1207,14 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
                        continue;
                }
 
-               dacs[i] = look_for_dac(codec, pin, false);
+               dacs[i] = get_preferred_dac(codec, pin);
+               if (dacs[i]) {
+                       if (is_dac_already_used(codec, dacs[i]))
+                               badness += bad->shared_primary;
+               }
+
+               if (!dacs[i])
+                       dacs[i] = look_for_dac(codec, pin, false);
                if (!dacs[i] && !i) {
                        /* try to steal the DAC of surrounds for the front */
                        for (j = 1; j < num_outs; j++) {
@@ -2506,12 +2528,8 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
 
        for (i = 0; i < num_pins; i++) {
                hda_nid_t pin = pins[i];
-               if (pin == spec->hp_mic_pin) {
-                       int ret = create_hp_mic_jack_mode(codec, pin);
-                       if (ret < 0)
-                               return ret;
+               if (pin == spec->hp_mic_pin)
                        continue;
-               }
                if (get_out_jack_num_items(codec, pin) > 1) {
                        struct snd_kcontrol_new *knew;
                        char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
@@ -2764,7 +2782,7 @@ static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
                        val &= ~(AC_PINCTL_VREFEN | PIN_HP);
                        val |= get_vref_idx(vref_caps, idx) | PIN_IN;
                } else
-                       val = snd_hda_get_default_vref(codec, nid);
+                       val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
        }
        snd_hda_set_pin_ctl_cache(codec, nid, val);
        call_hp_automute(codec, NULL);
@@ -2784,9 +2802,6 @@ static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
        struct hda_gen_spec *spec = codec->spec;
        struct snd_kcontrol_new *knew;
 
-       if (get_out_jack_num_items(codec, pin) <= 1 &&
-           get_in_jack_num_items(codec, pin) <= 1)
-               return 0; /* no need */
        knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
                                    &hp_mic_jack_mode_enum);
        if (!knew)
@@ -2815,6 +2830,44 @@ static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
        return 0;
 }
 
+/* return true if either a volume or a mute amp is found for the given
+ * aamix path; the amp has to be either in the mixer node or its direct leaf
+ */
+static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
+                                  hda_nid_t pin, unsigned int *mix_val,
+                                  unsigned int *mute_val)
+{
+       int idx, num_conns;
+       const hda_nid_t *list;
+       hda_nid_t nid;
+
+       idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
+       if (idx < 0)
+               return false;
+
+       *mix_val = *mute_val = 0;
+       if (nid_has_volume(codec, mix_nid, HDA_INPUT))
+               *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
+       if (nid_has_mute(codec, mix_nid, HDA_INPUT))
+               *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
+       if (*mix_val && *mute_val)
+               return true;
+
+       /* check leaf node */
+       num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
+       if (num_conns < idx)
+               return false;
+       nid = list[idx];
+       if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
+           !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
+               *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+       if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
+           !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
+               *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+
+       return *mix_val || *mute_val;
+}
+
 /* create input playback/capture controls for the given pin */
 static int new_analog_input(struct hda_codec *codec, int input_idx,
                            hda_nid_t pin, const char *ctlname, int ctlidx,
@@ -2822,12 +2875,11 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
 {
        struct hda_gen_spec *spec = codec->spec;
        struct nid_path *path;
-       unsigned int val;
+       unsigned int mix_val, mute_val;
        int err, idx;
 
-       if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
-           !nid_has_mute(codec, mix_nid, HDA_INPUT))
-               return 0; /* no need for analog loopback */
+       if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
+               return 0;
 
        path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
        if (!path)
@@ -2836,20 +2888,18 @@ static int new_analog_input(struct hda_codec *codec, int input_idx,
        spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
 
        idx = path->idx[path->depth - 1];
-       if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
-               val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
-               err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
+       if (mix_val) {
+               err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
                if (err < 0)
                        return err;
-               path->ctls[NID_PATH_VOL_CTL] = val;
+               path->ctls[NID_PATH_VOL_CTL] = mix_val;
        }
 
-       if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
-               val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
-               err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
+       if (mute_val) {
+               err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
                if (err < 0)
                        return err;
-               path->ctls[NID_PATH_MUTE_CTL] = val;
+               path->ctls[NID_PATH_MUTE_CTL] = mute_val;
        }
 
        path->active = true;
@@ -3006,6 +3056,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
                        spec->imux_pins[imux->num_items] = pin;
                        snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
                        imux_added = true;
+                       if (spec->dyn_adc_switch)
+                               spec->dyn_adc_idx[imux_idx] = c;
                }
        }
 
@@ -3103,7 +3155,9 @@ static int create_input_ctls(struct hda_codec *codec)
                }
        }
 
-       if (mixer && spec->add_stereo_mix_input) {
+       /* add stereo mix when explicitly enabled via hint */
+       if (mixer && spec->add_stereo_mix_input &&
+           snd_hda_get_bool_hint(codec, "add_stereo_mix_input") > 0) {
                err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
                                           "Stereo Mix", 0);
                if (err < 0)
@@ -3869,7 +3923,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
        do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                    spec->autocfg.line_out_pins, paths, on);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
+EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
 
 static void call_update_outputs(struct hda_codec *codec)
 {
@@ -3902,7 +3956,7 @@ void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
                return;
        call_update_outputs(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
+EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
 
 /* standard line-out-automute helper */
 void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
@@ -3922,7 +3976,7 @@ void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jac
                return;
        call_update_outputs(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
+EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
 
 /* standard mic auto-switch helper */
 void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
@@ -3945,7 +3999,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja
        }
        mux_select(codec, 0, spec->am_entry[0].idx);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
+EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
 
 /* call appropriate hooks */
 static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
@@ -4258,11 +4312,11 @@ static int check_auto_mic_availability(struct hda_codec *codec)
 }
 
 /* power_filter hook; make inactive widgets into power down */
-static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
+unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
                                                  hda_nid_t nid,
                                                  unsigned int power_state)
 {
-       if (power_state != AC_PWRST_D0)
+       if (power_state != AC_PWRST_D0 || nid == codec->afg)
                return power_state;
        if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
                return power_state;
@@ -4270,7 +4324,28 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
                return power_state;
        return AC_PWRST_D3;
 }
+EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
+
+/* mute all aamix inputs initially; parse up to the first leaves */
+static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
+{
+       int i, nums;
+       const hda_nid_t *conn;
+       bool has_amp;
 
+       nums = snd_hda_get_conn_list(codec, mix, &conn);
+       has_amp = nid_has_mute(codec, mix, HDA_INPUT);
+       for (i = 0; i < nums; i++) {
+               if (has_amp)
+                       snd_hda_codec_amp_stereo(codec, mix,
+                                                HDA_INPUT, i,
+                                                0xff, HDA_AMP_MUTE);
+               else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
+                       snd_hda_codec_amp_stereo(codec, conn[i],
+                                                HDA_OUTPUT, 0,
+                                                0xff, HDA_AMP_MUTE);
+       }
+}
 
 /*
  * Parse the given BIOS configuration and set up the hda_gen_spec
@@ -4307,7 +4382,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                        spec->no_analog = 1;
                        goto dig_only;
                }
-               return 0; /* can't find valid BIOS pin config */
+               if (!cfg->num_inputs && !cfg->dig_in_pin)
+                       return 0; /* can't find valid BIOS pin config */
        }
 
        if (!spec->no_primary_hp &&
@@ -4375,6 +4451,19 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
        if (err < 0)
                return err;
 
+       /* add stereo mix if available and not enabled yet */
+       if (!spec->auto_mic && spec->mixer_nid &&
+           spec->add_stereo_mix_input &&
+           spec->input_mux.num_items > 1 &&
+           snd_hda_get_bool_hint(codec, "add_stereo_mix_input") < 0) {
+               err = parse_capture_source(codec, spec->mixer_nid,
+                                          CFG_IDX_MIX, spec->num_all_adcs,
+                                          "Stereo Mix", 0);
+               if (err < 0)
+                       return err;
+       }
+
+
        err = create_capture_mixers(codec);
        if (err < 0)
                return err;
@@ -4383,6 +4472,17 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
        if (err < 0)
                return err;
 
+       /* create "Headphone Mic Jack Mode" if no input selection is
+        * available (or user specifies add_jack_modes hint)
+        */
+       if (spec->hp_mic_pin &&
+           (spec->auto_mic || spec->input_mux.num_items == 1 ||
+            spec->add_jack_modes)) {
+               err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
+               if (err < 0)
+                       return err;
+       }
+
        if (spec->add_jack_modes) {
                if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
                        err = create_out_jack_modes(codec, cfg->line_outs,
@@ -4398,6 +4498,10 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                }
        }
 
+       /* mute all aamix input initially */
+       if (spec->mixer_nid)
+               mute_all_mixer_nid(codec, spec->mixer_nid);
+
  dig_only:
        parse_digital(codec);
 
@@ -4412,7 +4516,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 
        return 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
+EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
 
 
 /*
@@ -4494,7 +4598,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
+EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
 
 
 /*
@@ -5027,7 +5131,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
+EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
 
 
 /*
@@ -5101,6 +5205,23 @@ static void init_multi_io(struct hda_codec *codec)
        }
 }
 
+static void init_aamix_paths(struct hda_codec *codec)
+{
+       struct hda_gen_spec *spec = codec->spec;
+
+       if (!spec->have_aamix_ctl)
+               return;
+       update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
+                          spec->aamix_out_paths[0],
+                          spec->autocfg.line_out_type);
+       update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
+                          spec->aamix_out_paths[1],
+                          AUTO_PIN_HP_OUT);
+       update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
+                          spec->aamix_out_paths[2],
+                          AUTO_PIN_SPEAKER_OUT);
+}
+
 /* set up input pins and loopback paths */
 static void init_analog_input(struct hda_codec *codec)
 {
@@ -5203,6 +5324,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        init_multi_out(codec);
        init_extra_out(codec);
        init_multi_io(codec);
+       init_aamix_paths(codec);
        init_analog_input(codec);
        init_input_src(codec);
        init_digital(codec);
@@ -5220,7 +5342,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        hda_call_check_power_status(codec, 0x01);
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_init);
+EXPORT_SYMBOL_GPL(snd_hda_gen_init);
 
 /*
  * free the generic spec;
@@ -5233,7 +5355,7 @@ void snd_hda_gen_free(struct hda_codec *codec)
        kfree(codec->spec);
        codec->spec = NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_free);
+EXPORT_SYMBOL_GPL(snd_hda_gen_free);
 
 #ifdef CONFIG_PM
 /*
@@ -5245,7 +5367,7 @@ int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
        struct hda_gen_spec *spec = codec->spec;
        return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
 }
-EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
+EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
 #endif
 
 
@@ -5290,4 +5412,7 @@ error:
        snd_hda_gen_free(codec);
        return err;
 }
-EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
+EXPORT_SYMBOL_GPL(snd_hda_parse_generic_codec);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic HD-audio codec parser");
index 7e45cb44d1514497385f2f6bc2b63251391cdaba..07f767231c9f439bef66a950f6a5cab3ce957156 100644 (file)
@@ -249,6 +249,9 @@ struct hda_gen_spec {
        const struct badness_table *main_out_badness;
        const struct badness_table *extra_out_badness;
 
+       /* preferred pin/DAC pairs; an array of paired NIDs */
+       const hda_nid_t *preferred_dacs;
+
        /* loopback mixing mode */
        bool aamix_mode;
 
@@ -332,5 +335,8 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec);
 #ifdef CONFIG_PM
 int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
 #endif
+unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
+                                          hda_nid_t nid,
+                                          unsigned int power_state);
 
 #endif /* __SOUND_HDA_GENERIC_H */
index fe0bda19de153f78da5da0c4add17e5fb3d95d65..72d8389fb399c1802d645686ae0dbc2ee379a2b4 100644 (file)
@@ -616,7 +616,7 @@ const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
        struct hda_hint *hint = get_hint(codec, key);
        return hint ? hint->val : NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_hint);
+EXPORT_SYMBOL_GPL(snd_hda_get_hint);
 
 int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
 {
@@ -642,7 +642,7 @@ int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
        mutex_unlock(&codec->user_mutex);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
+EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint);
 
 int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
 {
@@ -663,7 +663,7 @@ int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
        mutex_unlock(&codec->user_mutex);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hda_get_int_hint);
+EXPORT_SYMBOL_GPL(snd_hda_get_int_hint);
 #endif /* CONFIG_SND_HDA_RECONFIG */
 
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
@@ -762,20 +762,50 @@ DEFINE_PARSE_ID_MODE(revision_id);
 
 struct hda_patch_item {
        const char *tag;
+       const char *alias;
        void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
-       int need_codec;
 };
 
 static struct hda_patch_item patch_items[NUM_LINE_MODES] = {
-       [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 },
-       [LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 },
-       [LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 },
-       [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 },
-       [LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 },
-       [LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 },
-       [LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 },
-       [LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 },
-       [LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 },
+       [LINE_MODE_CODEC] = {
+               .tag = "[codec]",
+               .parser = parse_codec_mode,
+       },
+       [LINE_MODE_MODEL] = {
+               .tag = "[model]",
+               .parser = parse_model_mode,
+       },
+       [LINE_MODE_VERB] = {
+               .tag = "[verb]",
+               .alias = "[init_verbs]",
+               .parser = parse_verb_mode,
+       },
+       [LINE_MODE_PINCFG] = {
+               .tag = "[pincfg]",
+               .alias = "[user_pin_configs]",
+               .parser = parse_pincfg_mode,
+       },
+       [LINE_MODE_HINT] = {
+               .tag = "[hint]",
+               .alias = "[hints]",
+               .parser = parse_hint_mode
+       },
+       [LINE_MODE_VENDOR_ID] = {
+               .tag = "[vendor_id]",
+               .parser = parse_vendor_id_mode,
+       },
+       [LINE_MODE_SUBSYSTEM_ID] = {
+               .tag = "[subsystem_id]",
+               .parser = parse_subsystem_id_mode,
+       },
+       [LINE_MODE_REVISION_ID] = {
+               .tag = "[revision_id]",
+               .parser = parse_revision_id_mode,
+       },
+       [LINE_MODE_CHIP_NAME] = {
+               .tag = "[chip_name]",
+               .parser = parse_chip_name_mode,
+       },
 };
 
 /* check the line starting with '[' -- change the parser mode accodingly */
@@ -787,6 +817,8 @@ static int parse_line_mode(char *buf, struct hda_bus *bus)
                        continue;
                if (strmatch(buf, patch_items[i].tag))
                        return i;
+               if (patch_items[i].alias && strmatch(buf, patch_items[i].alias))
+                       return i;
        }
        return LINE_MODE_NONE;
 }
@@ -846,10 +878,10 @@ int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf)
                if (*buf == '[')
                        line_mode = parse_line_mode(buf, bus);
                else if (patch_items[line_mode].parser &&
-                        (codec || !patch_items[line_mode].need_codec))
+                        (codec || line_mode <= LINE_MODE_CODEC))
                        patch_items[line_mode].parser(buf, bus, &codec);
        }
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_load_patch);
+EXPORT_SYMBOL_GPL(snd_hda_load_patch);
 #endif /* CONFIG_SND_HDA_PATCH_LOADER */
index 7a09404579a73ac729ad437c358f38ac3b2b807b..fa2879a21a50a51beed9fdc1bcc77ea607b00b27 100644 (file)
@@ -297,9 +297,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define ULI_NUM_CAPTURE                5
 #define ULI_NUM_PLAYBACK       6
 
-/* ATI HDMI has 1 playback and 0 capture */
+/* ATI HDMI may have up to 8 playbacks and 0 capture */
 #define ATIHDMI_NUM_CAPTURE    0
-#define ATIHDMI_NUM_PLAYBACK   1
+#define ATIHDMI_NUM_PLAYBACK   8
 
 /* TERA has 4 playback and 3 capture */
 #define TERA_NUM_CAPTURE       3
@@ -431,6 +431,8 @@ struct azx_dev {
        struct timecounter  azx_tc;
        struct cyclecounter azx_cc;
 
+       int delay_negative_threshold;
+
 #ifdef CONFIG_SND_HDA_DSP_LOADER
        struct mutex dsp_mutex;
 #endif
@@ -543,9 +545,7 @@ struct azx {
        /* for pending irqs */
        struct work_struct irq_pending_work;
 
-#ifdef CONFIG_SND_HDA_I915
        struct work_struct probe_work;
-#endif
 
        /* reboot notifier (for mysterious hangup problem at power-down) */
        struct notifier_block reboot_notifier;
@@ -2197,6 +2197,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                        goto unlock;
        }
 
+       /* when LPIB delay correction gives a small negative value,
+        * we ignore it; currently set the threshold statically to
+        * 64 frames
+        */
+       if (runtime->period_size > 64)
+               azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64);
+       else
+               azx_dev->delay_negative_threshold = 0;
+
        /* wallclk has 24Mhz clock source */
        azx_dev->period_wallclk = (((runtime->period_size * 24000) /
                                                runtime->rate) * 1000);
@@ -2449,8 +2458,12 @@ static unsigned int azx_get_position(struct azx *chip,
                        delay = pos - lpib_pos;
                else
                        delay = lpib_pos - pos;
-               if (delay < 0)
-                       delay += azx_dev->bufsize;
+               if (delay < 0) {
+                       if (delay >= azx_dev->delay_negative_threshold)
+                               delay = 0;
+                       else
+                               delay += azx_dev->bufsize;
+               }
                if (delay >= azx_dev->period_bytes) {
                        snd_printk(KERN_WARNING SFX
                                   "%s: Unstable LPIB (%d >= %d); "
@@ -2994,8 +3007,7 @@ static int azx_runtime_suspend(struct device *dev)
                  STATESTS_INT_MASK);
 
        azx_stop_chip(chip);
-       if (!chip->bus->avoid_link_reset)
-               azx_enter_link_reset(chip);
+       azx_enter_link_reset(chip);
        azx_clear_irq_pending(chip);
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                hda_display_power(false);
@@ -3434,6 +3446,10 @@ static void check_probe_mask(struct azx *chip, int dev)
  * white/black-list for enable_msi
  */
 static struct snd_pci_quirk msi_black_list[] = {
+       SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
@@ -3501,12 +3517,10 @@ static void azx_check_snoop_available(struct azx *chip)
        }
 }
 
-#ifdef CONFIG_SND_HDA_I915
 static void azx_probe_work(struct work_struct *work)
 {
        azx_probe_continue(container_of(work, struct azx, probe_work));
 }
-#endif
 
 /*
  * constructor
@@ -3583,10 +3597,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
                return err;
        }
 
-#ifdef CONFIG_SND_HDA_I915
        /* continue probing in work context as may trigger request module */
        INIT_WORK(&chip->probe_work, azx_probe_work);
-#endif
 
        *rchip = chip;
 
@@ -3806,7 +3818,7 @@ static int azx_probe(struct pci_dev *pci,
        static int dev;
        struct snd_card *card;
        struct azx *chip;
-       bool probe_now;
+       bool schedule_probe;
        int err;
 
        if (dev >= SNDRV_CARDS)
@@ -3845,7 +3857,7 @@ static int azx_probe(struct pci_dev *pci,
                chip->disabled = true;
        }
 
-       probe_now = !chip->disabled;
+       schedule_probe = !chip->disabled;
 
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
        if (patch[dev] && *patch[dev]) {
@@ -3856,28 +3868,21 @@ static int azx_probe(struct pci_dev *pci,
                                              azx_firmware_cb);
                if (err < 0)
                        goto out_free;
-               probe_now = false; /* continued in azx_firmware_cb() */
+               schedule_probe = false; /* continued in azx_firmware_cb() */
        }
 #endif /* CONFIG_SND_HDA_PATCH_LOADER */
 
-       /* continue probing in work context, avoid request_module deadlock */
-       if (probe_now && (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)) {
-#ifdef CONFIG_SND_HDA_I915
-               probe_now = false;
-               schedule_work(&chip->probe_work);
-#else
+#ifndef CONFIG_SND_HDA_I915
+       if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                snd_printk(KERN_ERR SFX "Haswell must build in CONFIG_SND_HDA_I915\n");
 #endif
-       }
 
-       if (probe_now) {
-               err = azx_probe_continue(chip);
-               if (err < 0)
-                       goto out_free;
-       }
+       if (schedule_probe)
+               schedule_work(&chip->probe_work);
 
        dev++;
-       complete_all(&chip->probe_wait);
+       if (chip->disabled)
+               complete_all(&chip->probe_wait);
        return 0;
 
 out_free:
@@ -3954,10 +3959,10 @@ static int azx_probe_continue(struct azx *chip)
        if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo)
                pm_runtime_put_noidle(&pci->dev);
 
-       return 0;
-
 out_free:
-       chip->init_failed = 1;
+       if (err < 0)
+               chip->init_failed = 1;
+       complete_all(&chip->probe_wait);
        return err;
 }
 
@@ -3979,7 +3984,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
@@ -4004,6 +4009,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
          .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
        { PCI_DEVICE(0x8086, 0x0d0c),
          .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
+       /* Broadwell */
+       { PCI_DEVICE(0x8086, 0x160c),
+         .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
index afe594411a565d855297fe5cecd4561b10022967..9746d73cec52b113b83e7e694f854cdac719e574 100644 (file)
@@ -34,7 +34,7 @@ bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
                return false;
        return true;
 }
-EXPORT_SYMBOL_HDA(is_jack_detectable);
+EXPORT_SYMBOL_GPL(is_jack_detectable);
 
 /* execute pin sense measurement */
 static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
@@ -71,7 +71,7 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
                        return jack;
        return NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
+EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get);
 
 /**
  * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
@@ -89,7 +89,7 @@ snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
                        return jack;
        return NULL;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
+EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
 
 /**
  * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
@@ -108,7 +108,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
        jack->tag = codec->jacktbl.used;
        return jack;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new);
+EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_new);
 
 void snd_hda_jack_tbl_clear(struct hda_codec *codec)
 {
@@ -172,7 +172,7 @@ void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
                if (jack->nid)
                        jack->jack_dirty = 1;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);
+EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all);
 
 /**
  * snd_hda_pin_sense - execute pin sense measurement
@@ -191,7 +191,7 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
        }
        return read_pin_sense(codec, nid);
 }
-EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
+EXPORT_SYMBOL_GPL(snd_hda_pin_sense);
 
 /**
  * snd_hda_jack_detect_state - query pin Presence Detect status
@@ -211,7 +211,7 @@ int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
        else
                return HDA_JACK_NOT_PRESENT;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_detect_state);
+EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state);
 
 /**
  * snd_hda_jack_detect_enable - enable the jack-detection
@@ -236,14 +236,14 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
                                         AC_VERB_SET_UNSOLICITED_ENABLE,
                                         AC_USRSP_EN | jack->tag);
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable_callback);
+EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
 
 int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
                               unsigned char action)
 {
        return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL);
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
+EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
 
 /**
  * snd_hda_jack_set_gating_jack - Set gating jack.
@@ -264,7 +264,7 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_set_gating_jack);
+EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
 
 /**
  * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
@@ -297,7 +297,7 @@ void snd_hda_jack_report_sync(struct hda_codec *codec)
 #endif
                }
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
+EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
 
 #ifdef CONFIG_SND_HDA_INPUT_JACK
 /* guess the jack type from the pin-config */
@@ -377,7 +377,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 {
        return __snd_hda_jack_add_kctl(codec, nid, name, idx, false);
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
+EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl);
 
 /* get the unique index number for the given kctl name */
 static int get_unique_index(struct hda_codec *codec, const char *name, int idx)
@@ -493,7 +493,7 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
                return err;
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
+EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls);
 
 static void call_jack_callback(struct hda_codec *codec,
                               struct hda_jack_tbl *jack)
@@ -521,7 +521,7 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
        call_jack_callback(codec, event);
        snd_hda_jack_report_sync(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event);
+EXPORT_SYMBOL_GPL(snd_hda_jack_unsol_event);
 
 void snd_hda_jack_poll_all(struct hda_codec *codec)
 {
@@ -542,5 +542,5 @@ void snd_hda_jack_poll_all(struct hda_codec *codec)
        if (changes)
                snd_hda_jack_report_sync(codec);
 }
-EXPORT_SYMBOL_HDA(snd_hda_jack_poll_all);
+EXPORT_SYMBOL_GPL(snd_hda_jack_poll_all);
 
index d398b648bb5d1478d63e8d430d333eedda45beb3..da80c5bd7fd42ecacaa99e17befd8bef5c40099f 100644 (file)
@@ -352,14 +352,8 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
 /*
  * generic codec parser
  */
-#ifdef CONFIG_SND_HDA_GENERIC
 int snd_hda_parse_generic_codec(struct hda_codec *codec);
-#else
-static inline int snd_hda_parse_generic_codec(struct hda_codec *codec)
-{
-       return -ENODEV;
-}
-#endif
+int snd_hda_parse_hdmi_codec(struct hda_codec *codec);
 
 /*
  * generic proc interface
index 1a83559f4cbd27e455a941adaddc6d0513d9dd81..7a426ed491f2bea356f6a2610329f5ed84e17ebf 100644 (file)
@@ -147,6 +147,8 @@ static void ad_vmaster_eapd_hook(void *private_data, int enabled)
 
        if (!spec->eapd_nid)
                return;
+       if (codec->inv_eapd)
+               enabled = !enabled;
        snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
                                   AC_VERB_SET_EAPD_BTLENABLE,
                                   enabled ? 0x02 : 0x00);
@@ -183,7 +185,7 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = {
 };
 
 
-static int ad198x_parse_auto_config(struct hda_codec *codec)
+static int ad198x_parse_auto_config(struct hda_codec *codec, bool indep_hp)
 {
        struct ad198x_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->gen.autocfg;
@@ -193,7 +195,8 @@ static int ad198x_parse_auto_config(struct hda_codec *codec)
        codec->no_trigger_sense = 1;
        codec->no_sticky_stream = 1;
 
-       spec->gen.indep_hp = 1;
+       spec->gen.indep_hp = indep_hp;
+       spec->gen.add_stereo_mix_input = 1;
 
        err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
        if (err < 0)
@@ -278,11 +281,11 @@ static const struct hda_fixup ad1986a_fixups[] = {
                .v.pins = (const struct hda_pintbl[]) {
                        { 0x1a, 0x02214021 }, /* headphone */
                        { 0x1b, 0x01014011 }, /* front */
-                       { 0x1c, 0x01013012 }, /* surround */
-                       { 0x1d, 0x01019015 }, /* clfe */
+                       { 0x1c, 0x01813030 }, /* line-in */
+                       { 0x1d, 0x01a19020 }, /* rear mic */
                        { 0x1e, 0x411111f0 }, /* N/A */
                        { 0x1f, 0x02a190f0 }, /* mic */
-                       { 0x20, 0x018130f0 }, /* line-in */
+                       { 0x20, 0x411111f0 }, /* N/A */
                        {}
                },
        },
@@ -338,6 +341,14 @@ static int patch_ad1986a(struct hda_codec *codec)
 {
        int err;
        struct ad198x_spec *spec;
+       static hda_nid_t preferred_pairs[] = {
+               0x1a, 0x03,
+               0x1b, 0x03,
+               0x1c, 0x04,
+               0x1d, 0x05,
+               0x1e, 0x03,
+               0
+       };
 
        err = alloc_ad_spec(codec);
        if (err < 0)
@@ -358,12 +369,17 @@ static int patch_ad1986a(struct hda_codec *codec)
         * So, let's disable the shared stream.
         */
        spec->gen.multiout.no_share_stream = 1;
+       /* give fixed DAC/pin pairs */
+       spec->gen.preferred_dacs = preferred_pairs;
+
+       /* AD1986A can't manage the dynamic pin on/off smoothly */
+       spec->gen.auto_mute_via_amp = 1;
 
        snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
                           ad1986a_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
-       err = ad198x_parse_auto_config(codec);
+       err = ad198x_parse_auto_config(codec, false);
        if (err < 0) {
                snd_hda_gen_free(codec);
                return err;
@@ -465,7 +481,7 @@ static int patch_ad1983(struct hda_codec *codec)
 
        spec->gen.beep_nid = 0x10;
        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
-       err = ad198x_parse_auto_config(codec);
+       err = ad198x_parse_auto_config(codec, false);
        if (err < 0)
                goto error;
        err = ad1983_add_spdif_mux_ctl(codec);
@@ -552,7 +568,7 @@ static int patch_ad1981(struct hda_codec *codec)
        snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
-       err = ad198x_parse_auto_config(codec);
+       err = ad198x_parse_auto_config(codec, false);
        if (err < 0)
                goto error;
        err = ad1983_add_spdif_mux_ctl(codec);
@@ -878,7 +894,7 @@ static int patch_ad1988(struct hda_codec *codec)
        snd_hda_pick_fixup(codec, ad1988_fixup_models, NULL, ad1988_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
-       err = ad198x_parse_auto_config(codec);
+       err = ad198x_parse_auto_config(codec, true);
        if (err < 0)
                goto error;
        err = ad1988_add_spdif_mux_ctl(codec);
@@ -962,6 +978,7 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
                spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
+               spec->gen.own_eapd_ctl = 1;
                snd_hda_sequence_write_cache(codec, gpio_init_verbs);
                break;
        case HDA_FIXUP_ACT_PROBE:
@@ -1054,7 +1071,7 @@ static int patch_ad1884(struct hda_codec *codec)
        snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
-       err = ad198x_parse_auto_config(codec);
+       err = ad198x_parse_auto_config(codec, true);
        if (err < 0)
                goto error;
        err = ad1983_add_spdif_mux_ctl(codec);
@@ -1096,7 +1113,7 @@ static int patch_ad1882(struct hda_codec *codec)
        spec->gen.mixer_merge_nid = 0x21;
        spec->gen.beep_nid = 0x10;
        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
-       err = ad198x_parse_auto_config(codec);
+       err = ad198x_parse_auto_config(codec, true);
        if (err < 0)
                goto error;
        err = ad1988_add_spdif_mux_ctl(codec);
index c205bb1747fdf6a7d367d6ef54d718331d671c0b..4e0ec146553dadebda31c7ea996a4583dc296764 100644 (file)
@@ -2936,7 +2936,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
-       SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
        SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
        SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
@@ -3241,80 +3240,8 @@ enum {
        CXT_FIXUP_THINKPAD_ACPI,
 };
 
-#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
-
-#include <linux/thinkpad_acpi.h>
-
-static int (*led_set_func)(int, bool);
-
-static void update_tpacpi_mute_led(void *private_data, int enabled)
-{
-       struct hda_codec *codec = private_data;
-       struct conexant_spec *spec = codec->spec;
-
-       if (spec->dynamic_eapd)
-               cx_auto_vmaster_hook(private_data, enabled);
-
-       if (led_set_func)
-               led_set_func(TPACPI_LED_MUTE, !enabled);
-}
-
-static void update_tpacpi_micmute_led(struct hda_codec *codec,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       if (!ucontrol || !led_set_func)
-               return;
-       if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
-               /* TODO: How do I verify if it's a mono or stereo here? */
-               bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
-               led_set_func(TPACPI_LED_MICMUTE, !val);
-       }
-}
-
-static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
-                                 const struct hda_fixup *fix, int action)
-{
-       struct conexant_spec *spec = codec->spec;
-
-       bool removefunc = false;
-
-       if (action == HDA_FIXUP_ACT_PROBE) {
-               if (!led_set_func)
-                       led_set_func = symbol_request(tpacpi_led_set);
-               if (!led_set_func) {
-                       snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
-                       return;
-               }
-
-               removefunc = true;
-               if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
-                       spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
-                       removefunc = false;
-               }
-               if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
-                       if (spec->gen.num_adc_nids > 1)
-                               snd_printdd("Skipping micmute LED control due to several ADCs");
-                       else {
-                               spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
-                               removefunc = false;
-                       }
-               }
-       }
-
-       if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
-               symbol_put(tpacpi_led_set);
-               led_set_func = NULL;
-       }
-}
-
-#else
-
-static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
-                                 const struct hda_fixup *fix, int action)
-{
-}
-
-#endif
+/* for hda_fixup_thinkpad_acpi() */
+#include "thinkpad_helper.c"
 
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
                                  const struct hda_fixup *fix, int action)
@@ -3471,7 +3398,7 @@ static const struct hda_fixup cxt_fixups[] = {
        },
        [CXT_FIXUP_THINKPAD_ACPI] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = cxt_fixup_thinkpad_acpi,
+               .v.func = hda_fixup_thinkpad_acpi,
        },
 };
 
@@ -3494,6 +3421,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
        SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
        {}
index 08407bed093e5a64d4b659f90bf236dead9ec002..64f0a5e73a259b00fe43f89672f369ea9b751b8d 100644 (file)
@@ -46,6 +46,9 @@ module_param(static_hdmi_pcm, bool, 0644);
 MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 
 #define is_haswell(codec)  ((codec)->vendor_id == 0x80862807)
+#define is_broadwell(codec)    ((codec)->vendor_id == 0x80862808)
+#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec))
+
 #define is_valleyview(codec) ((codec)->vendor_id == 0x80862882)
 
 struct hdmi_spec_per_cvt {
@@ -1101,7 +1104,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
        if (!channels)
                return;
 
-       if (is_haswell(codec))
+       if (is_haswell_plus(codec))
                snd_hda_codec_write(codec, pin_nid, 0,
                                            AC_VERB_SET_AMP_GAIN_MUTE,
                                            AMP_OUT_UNMUTE);
@@ -1142,32 +1145,34 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
 
 static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
 
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+static void jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack)
 {
        struct hdmi_spec *spec = codec->spec;
+       int pin_idx = pin_nid_to_pin_index(spec, jack->nid);
+       if (pin_idx < 0)
+               return;
+
+       if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
+               snd_hda_jack_report_sync(codec);
+}
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
        int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int pin_nid;
-       int pin_idx;
        struct hda_jack_tbl *jack;
        int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
 
        jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
        if (!jack)
                return;
-       pin_nid = jack->nid;
        jack->jack_dirty = 1;
 
        _snd_printd(SND_PR_VERBOSE,
                "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n",
-               codec->addr, pin_nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
+               codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
                !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
 
-       pin_idx = pin_nid_to_pin_index(spec, pin_nid);
-       if (pin_idx < 0)
-               return;
-
-       if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
-               snd_hda_jack_report_sync(codec);
+       jack_callback(codec, jack);
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -1278,7 +1283,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
        struct hdmi_spec *spec = codec->spec;
        int err;
 
-       if (is_haswell(codec))
+       if (is_haswell_plus(codec))
                haswell_verify_D0(codec, cvt_nid, pin_nid);
 
        err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format));
@@ -1419,7 +1424,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
                            mux_idx);
 
        /* configure unused pins to choose other converters */
-       if (is_haswell(codec) || is_valleyview(codec))
+       if (is_haswell_plus(codec) || is_valleyview(codec))
                intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx);
 
        snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
@@ -1494,11 +1499,14 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
         * specification worked this way. Hence, we just ignore the data in
         * the unsolicited response to avoid custom WARs.
         */
-       int present = snd_hda_pin_sense(codec, pin_nid);
+       int present;
        bool update_eld = false;
        bool eld_changed = false;
        bool ret;
 
+       snd_hda_power_up(codec);
+       present = snd_hda_pin_sense(codec, pin_nid);
+
        mutex_lock(&per_pin->lock);
        pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
        if (pin_eld->monitor_present)
@@ -1571,6 +1579,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
                jack->block_report = !ret;
 
        mutex_unlock(&per_pin->lock);
+       snd_hda_power_down(codec);
        return ret;
 }
 
@@ -1605,7 +1614,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
        if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
                return 0;
 
-       if (is_haswell(codec))
+       if (is_haswell_plus(codec))
                intel_haswell_fixup_connect_list(codec, pin_nid);
 
        pin_idx = spec->num_pins;
@@ -1692,21 +1701,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
                }
        }
 
-#ifdef CONFIG_PM
-       /* We're seeing some problems with unsolicited hot plug events on
-        * PantherPoint after S3, if this is not enabled */
-       if (codec->vendor_id == 0x80862806)
-               codec->bus->power_keep_link_on = 1;
-       /*
-        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-        * can be lost and presence sense verb will become inaccurate if the
-        * HDA link is powered off at hot plug or hw initialization time.
-        */
-       else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-             AC_PWRST_EPSS))
-               codec->bus->power_keep_link_on = 1;
-#endif
-
        return 0;
 }
 
@@ -2095,7 +2089,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
                hda_nid_t pin_nid = per_pin->pin_nid;
 
                hdmi_init_pin(codec, pin_nid);
-               snd_hda_jack_detect_enable(codec, pin_nid, pin_nid);
+               snd_hda_jack_detect_enable_callback(codec, pin_nid, pin_nid,
+                       codec->jackpoll_interval > 0 ? jack_callback : NULL);
        }
        return 0;
 }
@@ -2257,18 +2252,22 @@ static int patch_generic_hdmi(struct hda_codec *codec)
        codec->spec = spec;
        hdmi_array_init(spec, 4);
 
-       if (is_haswell(codec)) {
+       if (is_haswell_plus(codec)) {
                intel_haswell_enable_all_pins(codec, true);
                intel_haswell_fixup_enable_dp12(codec);
        }
 
+       if (is_haswell(codec) || is_valleyview(codec)) {
+               codec->depop_delay = 0;
+       }
+
        if (hdmi_parse_codec(codec) < 0) {
                codec->spec = NULL;
                kfree(spec);
                return -EINVAL;
        }
        codec->patch_ops = generic_hdmi_patch_ops;
-       if (is_haswell(codec)) {
+       if (is_haswell_plus(codec)) {
                codec->patch_ops.set_power_state = haswell_set_power_state;
                codec->dp_mst = true;
        }
@@ -2334,8 +2333,9 @@ static int simple_playback_build_controls(struct hda_codec *codec)
        int err;
 
        per_cvt = get_cvt(spec, 0);
-       err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
-                                           per_cvt->cvt_nid);
+       err = snd_hda_create_dig_out_ctls(codec, per_cvt->cvt_nid,
+                                         per_cvt->cvt_nid,
+                                         HDA_PCM_TYPE_HDMI);
        if (err < 0)
                return err;
        return simple_hdmi_build_jack(codec, 0);
@@ -3213,6 +3213,15 @@ static int patch_via_hdmi(struct hda_codec *codec)
        return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);
 }
 
+/*
+ * called from hda_codec.c for generic HDMI support
+ */
+int snd_hda_parse_hdmi_codec(struct hda_codec *codec)
+{
+       return patch_generic_hdmi(codec);
+}
+EXPORT_SYMBOL_GPL(snd_hda_parse_hdmi_codec);
+
 /*
  * patch entries
  */
@@ -3267,6 +3276,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x80862805, .name = "CougarPoint HDMI",        .patch = patch_generic_hdmi },
 { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
 { .id = 0x80862807, .name = "Haswell HDMI",    .patch = patch_generic_hdmi },
+{ .id = 0x80862808, .name = "Broadwell HDMI",  .patch = patch_generic_hdmi },
 { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi },
 { .id = 0x80862882, .name = "Valleyview2 HDMI",        .patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",  .patch = patch_generic_hdmi },
@@ -3322,6 +3332,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862804");
 MODULE_ALIAS("snd-hda-codec-id:80862805");
 MODULE_ALIAS("snd-hda-codec-id:80862806");
 MODULE_ALIAS("snd-hda-codec-id:80862807");
+MODULE_ALIAS("snd-hda-codec-id:80862808");
 MODULE_ALIAS("snd-hda-codec-id:80862880");
 MODULE_ALIAS("snd-hda-codec-id:80862882");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
index 5e42059f10a1fc4e5e6f127a6c6b536ae0dd537f..a1c16457880ea6d51e0381a0477f34fde0dbc521 100644 (file)
@@ -118,7 +118,8 @@ struct alc_spec {
 
        int init_amp;
        int codec_variant;      /* flag for other variants */
-       bool has_alc5505_dsp;
+       unsigned int has_alc5505_dsp:1;
+       unsigned int no_depop_delay:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -280,8 +281,11 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
  */
 static void alc_eapd_shutup(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
+
        alc_auto_setup_eapd(codec, false);
-       msleep(200);
+       if (!spec->no_depop_delay)
+               msleep(200);
        snd_hda_shutup_pins(codec);
 }
 
@@ -365,6 +369,17 @@ static void alc_fixup_sku_ignore(struct hda_codec *codec,
        }
 }
 
+static void alc_fixup_no_depop_delay(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PROBE) {
+               spec->no_depop_delay = 1;
+               codec->depop_delay = 0;
+       }
+}
+
 static int alc_auto_parse_customize_define(struct hda_codec *codec)
 {
        unsigned int ass, tmp, i;
@@ -454,9 +469,7 @@ static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
  *     7  ~ 0  :       Assembly ID
  *     port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
  */
-static int alc_subsystem_id(struct hda_codec *codec,
-                           hda_nid_t porta, hda_nid_t porte,
-                           hda_nid_t portd, hda_nid_t porti)
+static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
 {
        unsigned int ass, tmp, i;
        unsigned nid;
@@ -546,14 +559,7 @@ do_sku:
              spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
                hda_nid_t nid;
                tmp = (ass >> 11) & 0x3;        /* HP to chassis */
-               if (tmp == 0)
-                       nid = porta;
-               else if (tmp == 1)
-                       nid = porte;
-               else if (tmp == 2)
-                       nid = portd;
-               else if (tmp == 3)
-                       nid = porti;
+               nid = ports[tmp];
                if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
                                      spec->gen.autocfg.line_outs))
                        return 1;
@@ -566,7 +572,7 @@ do_sku:
  * ports contains an array of 4 pin NIDs for port-A, E, D and I */
 static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
 {
-       if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
+       if (!alc_subsystem_id(codec, ports)) {
                struct alc_spec *spec = codec->spec;
                snd_printd("realtek: "
                           "Enable default setup for auto mode as fallback\n");
@@ -863,7 +869,10 @@ static int alc_suspend(struct hda_codec *codec)
 #ifdef CONFIG_PM
 static int alc_resume(struct hda_codec *codec)
 {
-       msleep(150); /* to avoid pop noise */
+       struct alc_spec *spec = codec->spec;
+
+       if (!spec->no_depop_delay)
+               msleep(150); /* to avoid pop noise */
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
@@ -903,7 +912,7 @@ static int alc_codec_rename(struct hda_codec *codec, const char *name)
 }
 
 /*
- * Rename codecs appropriately from COEF value
+ * Rename codecs appropriately from COEF value or subvendor id
  */
 struct alc_codec_rename_table {
        unsigned int vendor_id;
@@ -912,6 +921,13 @@ struct alc_codec_rename_table {
        const char *name;
 };
 
+struct alc_codec_rename_pci_table {
+       unsigned int codec_vendor_id;
+       unsigned short pci_subvendor;
+       unsigned short pci_subdevice;
+       const char *name;
+};
+
 static struct alc_codec_rename_table rename_tbl[] = {
        { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
        { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
@@ -931,9 +947,20 @@ static struct alc_codec_rename_table rename_tbl[] = {
        { } /* terminator */
 };
 
+static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
+       { 0x10ec0280, 0x1028, 0, "ALC3220" },
+       { 0x10ec0282, 0x1028, 0, "ALC3221" },
+       { 0x10ec0283, 0x1028, 0, "ALC3223" },
+       { 0x10ec0292, 0x1028, 0, "ALC3226" },
+       { 0x10ec0255, 0x1028, 0, "ALC3234" },
+       { 0x10ec0668, 0x1028, 0, "ALC3661" },
+       { } /* terminator */
+};
+
 static int alc_codec_rename_from_preset(struct hda_codec *codec)
 {
        const struct alc_codec_rename_table *p;
+       const struct alc_codec_rename_pci_table *q;
 
        for (p = rename_tbl; p->vendor_id; p++) {
                if (p->vendor_id != codec->vendor_id)
@@ -941,6 +968,17 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec)
                if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
                        return alc_codec_rename(codec, p->name);
        }
+
+       for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
+               if (q->codec_vendor_id != codec->vendor_id)
+                       continue;
+               if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
+                       continue;
+               if (!q->pci_subdevice ||
+                   q->pci_subdevice == codec->bus->pci->subsystem_device)
+                       return alc_codec_rename(codec, q->name);
+       }
+
        return 0;
 }
 
@@ -1763,6 +1801,7 @@ enum {
        ALC882_FIXUP_ACER_ASPIRE_7736,
        ALC882_FIXUP_ASUS_W90V,
        ALC889_FIXUP_CD,
+       ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
        ALC889_FIXUP_VAIO_TT,
        ALC888_FIXUP_EEE1601,
        ALC882_FIXUP_EAPD,
@@ -1780,8 +1819,11 @@ enum {
        ALC889_FIXUP_DAC_ROUTE,
        ALC889_FIXUP_MBP_VREF,
        ALC889_FIXUP_IMAC91_VREF,
+       ALC889_FIXUP_MBA21_VREF,
        ALC882_FIXUP_INV_DMIC,
        ALC882_FIXUP_NO_PRIMARY_HP,
+       ALC887_FIXUP_ASUS_BASS,
+       ALC887_FIXUP_BASS_CHMAP,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -1882,17 +1924,13 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec,
        }
 }
 
-/* Set VREF on speaker pins on imac91 */
-static void alc889_fixup_imac91_vref(struct hda_codec *codec,
-                                    const struct hda_fixup *fix, int action)
+static void alc889_fixup_mac_pins(struct hda_codec *codec,
+                                 const hda_nid_t *nids, int num_nids)
 {
        struct alc_spec *spec = codec->spec;
-       static hda_nid_t nids[2] = { 0x18, 0x1a };
        int i;
 
-       if (action != HDA_FIXUP_ACT_INIT)
-               return;
-       for (i = 0; i < ARRAY_SIZE(nids); i++) {
+       for (i = 0; i < num_nids; i++) {
                unsigned int val;
                val = snd_hda_codec_get_pin_target(codec, nids[i]);
                val |= AC_PINCTL_VREF_50;
@@ -1901,6 +1939,26 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
        spec->gen.keep_vref_in_automute = 1;
 }
 
+/* Set VREF on speaker pins on imac91 */
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[2] = { 0x18, 0x1a };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
+/* Set VREF on speaker pins on mba21 */
+static void alc889_fixup_mba21_vref(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[2] = { 0x18, 0x19 };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
 /* Don't take HP output as primary
  * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
  * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
@@ -1915,6 +1973,9 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
        }
 }
 
+static void alc_fixup_bass_chmap(struct hda_codec *codec,
+                                const struct hda_fixup *fix, int action);
+
 static const struct hda_fixup alc882_fixups[] = {
        [ALC882_FIXUP_ABIT_AW9D_MAX] = {
                .type = HDA_FIXUP_PINS,
@@ -1958,6 +2019,15 @@ static const struct hda_fixup alc882_fixups[] = {
                        { }
                }
        },
+       [ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC889_FIXUP_CD,
+       },
        [ALC889_FIXUP_VAIO_TT] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -2097,6 +2167,12 @@ static const struct hda_fixup alc882_fixups[] = {
                .chained = true,
                .chain_id = ALC882_FIXUP_GPIO1,
        },
+       [ALC889_FIXUP_MBA21_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc889_fixup_mba21_vref,
+               .chained = true,
+               .chain_id = ALC889_FIXUP_MBP_VREF,
+       },
        [ALC882_FIXUP_INV_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
@@ -2105,6 +2181,19 @@ static const struct hda_fixup alc882_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc882_fixup_no_primary_hp,
        },
+       [ALC887_FIXUP_ASUS_BASS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       {0x16, 0x99130130}, /* bass speaker */
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC887_FIXUP_BASS_CHMAP,
+       },
+       [ALC887_FIXUP_BASS_CHMAP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_bass_chmap,
+       },
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2138,6 +2227,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
        SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
        SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
+       SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
        SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
        SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
        SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
@@ -2153,7 +2243,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
-       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
+       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
        SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
@@ -2169,7 +2259,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -2272,6 +2362,7 @@ enum {
        ALC262_FIXUP_BENQ,
        ALC262_FIXUP_BENQ_T31,
        ALC262_FIXUP_INV_DMIC,
+       ALC262_FIXUP_INTEL_BAYLEYBAY,
 };
 
 static const struct hda_fixup alc262_fixups[] = {
@@ -2336,6 +2427,10 @@ static const struct hda_fixup alc262_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_no_depop_delay,
+       },
 };
 
 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
@@ -2347,6 +2442,7 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
        SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
        SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
+       SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
        {}
 };
 
@@ -3268,6 +3364,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
                alc_write_coef_idx(codec, 0x18, 0x7388);
                break;
        case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
                alc_write_coef_idx(codec, 0x15, 0x0d60);
                alc_write_coef_idx(codec, 0xc3, 0x0000);
                break;
@@ -3296,6 +3393,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
                alc_write_coef_idx(codec, 0x18, 0x7388);
                break;
        case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
                alc_write_coef_idx(codec, 0x15, 0x0d50);
                alc_write_coef_idx(codec, 0xc3, 0x0000);
                break;
@@ -3482,6 +3580,15 @@ static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
        alc_fixup_headset_mode(codec, fix, action);
 }
 
+static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
+                                       const struct hda_fixup *fix, int action)
+{
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               struct alc_spec *spec = codec->spec;
+               spec->gen.auto_mute_via_amp = 1;
+       }
+}
+
 static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
 {
@@ -3581,11 +3688,6 @@ static void alc283_hp_automute_hook(struct hda_codec *codec,
                            vref);
 }
 
-static void alc283_chromebook_caps(struct hda_codec *codec)
-{
-       snd_hda_override_wcaps(codec, 0x03, 0);
-}
-
 static void alc283_fixup_chromebook(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
@@ -3594,9 +3696,26 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
 
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
-               alc283_chromebook_caps(codec);
+               snd_hda_override_wcaps(codec, 0x03, 0);
                /* Disable AA-loopback as it causes white noise */
                spec->gen.mixer_nid = 0;
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               /* Enable Line1 input control by verb */
+               val = alc_read_coef_idx(codec, 0x1a);
+               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
+               break;
+       }
+}
+
+static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       int val;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
                spec->gen.hp_automute_hook = alc283_hp_automute_hook;
                break;
        case HDA_FIXUP_ACT_INIT:
@@ -3604,9 +3723,6 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
                /* Set to manual mode */
                val = alc_read_coef_idx(codec, 0x06);
                alc_write_coef_idx(codec, 0x06, val & ~0x000c);
-               /* Enable Line1 input control by verb */
-               val = alc_read_coef_idx(codec, 0x1a);
-               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
                break;
        }
 }
@@ -3664,101 +3780,18 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
 static void alc290_fixup_mono_speakers(struct hda_codec *codec,
                                       const struct hda_fixup *fix, int action)
 {
-       if (action == HDA_FIXUP_ACT_PRE_PROBE)
-               /* Remove DAC node 0x03, as it seems to be
-                  giving mono output */
-               snd_hda_override_wcaps(codec, 0x03, 0);
-}
-
-#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
-
-#include <linux/thinkpad_acpi.h>
-#include <acpi/acpi.h>
-
-static int (*led_set_func)(int, bool);
-
-static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
-                                void **rv)
-{
-       bool *found = context;
-       *found = true;
-       return AE_OK;
-}
-
-static bool is_thinkpad(struct hda_codec *codec)
-{
-       bool found = false;
-       if (codec->subsystem_id >> 16 != 0x17aa)
-               return false;
-       if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
-               return true;
-       found = false;
-       return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
-}
-
-static void update_tpacpi_mute_led(void *private_data, int enabled)
-{
-       if (led_set_func)
-               led_set_func(TPACPI_LED_MUTE, !enabled);
-}
-
-static void update_tpacpi_micmute_led(struct hda_codec *codec,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       if (!ucontrol || !led_set_func)
-               return;
-       if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
-               /* TODO: How do I verify if it's a mono or stereo here? */
-               bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
-               led_set_func(TPACPI_LED_MICMUTE, !val);
-       }
-}
-
-static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
-                                 const struct hda_fixup *fix, int action)
-{
-       struct alc_spec *spec = codec->spec;
-       bool removefunc = false;
-
-       if (action == HDA_FIXUP_ACT_PROBE) {
-               if (!is_thinkpad(codec))
-                       return;
-               if (!led_set_func)
-                       led_set_func = symbol_request(tpacpi_led_set);
-               if (!led_set_func) {
-                       snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
-                       return;
-               }
-
-               removefunc = true;
-               if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
-                       spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
-                       removefunc = false;
-               }
-               if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
-                       if (spec->gen.num_adc_nids > 1)
-                               snd_printdd("Skipping micmute LED control due to several ADCs");
-                       else {
-                               spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
-                               removefunc = false;
-                       }
-               }
-       }
-
-       if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
-               symbol_put(tpacpi_led_set);
-               led_set_func = NULL;
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               /* DAC node 0x03 is giving mono output. We therefore want to
+                  make sure 0x14 (front speaker) and 0x15 (headphones) use the
+                  stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
+               hda_nid_t conn1[2] = { 0x0c };
+               snd_hda_override_conn_list(codec, 0x14, 1, conn1);
+               snd_hda_override_conn_list(codec, 0x15, 1, conn1);
        }
 }
 
-#else
-
-static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
-                                 const struct hda_fixup *fix, int action)
-{
-}
-
-#endif
+/* for hda_fixup_thinkpad_acpi() */
+#include "thinkpad_helper.c"
 
 enum {
        ALC269_FIXUP_SONY_VAIO,
@@ -3796,14 +3829,20 @@ enum {
        ALC269_FIXUP_ASUS_X101,
        ALC271_FIXUP_AMIC_MIC2,
        ALC271_FIXUP_HP_GATE_MIC_JACK,
+       ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
        ALC269_FIXUP_ACER_AC700,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
+       ALC269VB_FIXUP_ASUS_ZENBOOK,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
        ALC269VB_FIXUP_ORDISSIMO_EVE2,
        ALC283_FIXUP_CHROME_BOOK,
+       ALC283_FIXUP_SENSE_COMBO_JACK,
        ALC282_FIXUP_ASUS_TX300,
        ALC283_FIXUP_INT_MIC,
        ALC290_FIXUP_MONO_SPEAKERS,
+       ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
+       ALC290_FIXUP_SUBWOOFER,
+       ALC290_FIXUP_SUBWOOFER_HSJACK,
        ALC269_FIXUP_THINKPAD_ACPI,
        ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC255_FIXUP_HEADSET_MODE,
@@ -4056,6 +4095,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC271_FIXUP_AMIC_MIC2,
        },
+       [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
+       },
        [ALC269_FIXUP_ACER_AC700] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -4075,6 +4120,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
        },
+       [ALC269VB_FIXUP_ASUS_ZENBOOK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC269VB_FIXUP_DMIC,
+       },
        [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc269_fixup_limit_int_mic_boost,
@@ -4094,6 +4145,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc283_fixup_chromebook,
        },
+       [ALC283_FIXUP_SENSE_COMBO_JACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc283_fixup_sense_combo_jack,
+               .chained = true,
+               .chain_id = ALC283_FIXUP_CHROME_BOOK,
+       },
        [ALC282_FIXUP_ASUS_TX300] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc282_fixup_asus_tx300,
@@ -4108,15 +4165,37 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
        },
+       [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x17, 0x90170112 }, /* subwoofer */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
+       },
+       [ALC290_FIXUP_SUBWOOFER] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x17, 0x90170112 }, /* subwoofer */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
+       },
        [ALC290_FIXUP_MONO_SPEAKERS] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc290_fixup_mono_speakers,
+       },
+       [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc290_fixup_mono_speakers,
                .chained = true,
                .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
        },
        [ALC269_FIXUP_THINKPAD_ACPI] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = alc_fixup_thinkpad_acpi,
+               .v.func = hda_fixup_thinkpad_acpi,
        },
        [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
@@ -4141,6 +4220,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4154,6 +4234,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
        SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -4172,11 +4253,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
+       SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+       SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
        SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
+       SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -4184,13 +4271,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
-       SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco Chromebook", ALC283_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
-       SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
+       SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
@@ -4292,6 +4378,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
        {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
        {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
+       {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-chrome"},
+       {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
        {}
 };
 
@@ -4421,7 +4509,7 @@ static int patch_alc269(struct hda_codec *codec)
        }
 
        if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
-               spec->has_alc5505_dsp = true;
+               spec->has_alc5505_dsp = 1;
                spec->init_hook = alc5505_dsp_init;
        }
 
@@ -4467,6 +4555,7 @@ enum {
        ALC861_FIXUP_AMP_VREF_0F,
        ALC861_FIXUP_NO_JACK_DETECT,
        ALC861_FIXUP_ASUS_A6RP,
+       ALC660_FIXUP_ASUS_W7J,
 };
 
 /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
@@ -4516,10 +4605,22 @@ static const struct hda_fixup alc861_fixups[] = {
                .v.func = alc861_fixup_asus_amp_vref_0f,
                .chained = true,
                .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
+       },
+       [ALC660_FIXUP_ASUS_W7J] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* ASUS W7J needs a magic pin setup on unused NID 0x10
+                        * for enabling outputs
+                        */
+                       {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+                       { }
+               },
        }
 };
 
 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
+       SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
        SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
        SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
        SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
@@ -4715,7 +4816,7 @@ static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
 };
 
 /* override the 2.1 chmap */
-static void alc662_fixup_bass_chmap(struct hda_codec *codec,
+static void alc_fixup_bass_chmap(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
        if (action == HDA_FIXUP_ACT_BUILD) {
@@ -4747,6 +4848,7 @@ enum {
        ALC662_FIXUP_BASS_CHMAP,
        ALC662_FIXUP_BASS_1A,
        ALC662_FIXUP_BASS_1A_CHMAP,
+       ALC668_FIXUP_AUTO_MUTE,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -4907,6 +5009,12 @@ static const struct hda_fixup alc662_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC668_FIXUP_AUTO_MUTE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_auto_mute_via_amp,
+               .chained = true,
+               .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
+       },
        [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -4923,7 +5031,7 @@ static const struct hda_fixup alc662_fixups[] = {
        },
        [ALC662_FIXUP_BASS_CHMAP] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = alc662_fixup_bass_chmap,
+               .v.func = alc_fixup_bass_chmap,
                .chained = true,
                .chain_id = ALC662_FIXUP_ASUS_MODE4
        },
@@ -4936,7 +5044,7 @@ static const struct hda_fixup alc662_fixups[] = {
        },
        [ALC662_FIXUP_BASS_1A_CHMAP] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = alc662_fixup_bass_chmap,
+               .v.func = alc_fixup_bass_chmap,
                .chained = true,
                .chain_id = ALC662_FIXUP_BASS_1A,
        },
@@ -4952,8 +5060,11 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE),
+       SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE),
        SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE),
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
        SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),
@@ -5118,6 +5229,7 @@ static int patch_alc662(struct hda_codec *codec)
                case 0x10ec0272:
                case 0x10ec0663:
                case 0x10ec0665:
+               case 0x10ec0668:
                        set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
                        break;
                case 0x10ec0273:
@@ -5175,6 +5287,7 @@ static int patch_alc680(struct hda_codec *codec)
  */
 static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
+       { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 },
        { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 },
        { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 },
        { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
index d2cc0041d9d3f92803002addf12f2ca8c98900ec..6998cf29b9bc34016e2d2ee1574b6b3d02ce8ef2 100644 (file)
@@ -368,6 +368,17 @@ static int stac_vrefout_set(struct hda_codec *codec,
        return 1;
 }
 
+/* prevent codec AFG to D3 state when vref-out pin is used for mute LED */
+/* this hook is set in stac_setup_gpio() */
+static unsigned int stac_vref_led_power_filter(struct hda_codec *codec,
+                                              hda_nid_t nid,
+                                              unsigned int power_state)
+{
+       if (nid == codec->afg && power_state == AC_PWRST_D3)
+               return AC_PWRST_D1;
+       return snd_hda_gen_path_power_filter(codec, nid, power_state);
+}
+
 /* update mute-LED accoring to the master switch */
 static void stac_update_led_status(struct hda_codec *codec, int enabled)
 {
@@ -2094,7 +2105,8 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
-               codec->bus->avoid_link_reset = 1;
+               /* resetting controller clears GPIO, so we need to keep on */
+               codec->bus->power_keep_link_on = 1;
        }
 }
 
@@ -4259,30 +4271,8 @@ static int stac_suspend(struct hda_codec *codec)
        stac_shutup(codec);
        return 0;
 }
-
-static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg,
-                                unsigned int power_state)
-{
-       unsigned int afg_power_state = power_state;
-       struct sigmatel_spec *spec = codec->spec;
-
-       if (power_state == AC_PWRST_D3) {
-               if (spec->vref_mute_led_nid) {
-                       /* with vref-out pin used for mute led control
-                        * codec AFG is prevented from D3 state
-                        */
-                       afg_power_state = AC_PWRST_D1;
-               }
-               /* this delay seems necessary to avoid click noise at power-down */
-               msleep(100);
-       }
-       snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
-                       afg_power_state);
-       snd_hda_codec_set_power_to_all(codec, fg, power_state);
-}
 #else
 #define stac_suspend           NULL
-#define stac_set_power_state   NULL
 #endif /* CONFIG_PM */
 
 static const struct hda_codec_ops stac_patch_ops = {
@@ -4465,8 +4455,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
                        spec->gpio_dir |= spec->gpio_led;
                        spec->gpio_data |= spec->gpio_led;
                } else {
-                       codec->patch_ops.set_power_state =
-                                       stac_set_power_state;
+                       codec->power_filter = stac_vref_led_power_filter;
                }
        }
 
index 0bc20ef5687ac3558996ca3fd56a741c75bc042b..f84195f3ea31e2f6bac3c1c5f79355e1ec24c0fb 100644 (file)
@@ -138,6 +138,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
        spec->gen.indep_hp = 1;
        spec->gen.keep_eapd_on = 1;
        spec->gen.pcm_playback_hook = via_playback_pcm_hook;
+       spec->gen.add_stereo_mix_input = 1;
        return spec;
 }
 
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c
new file mode 100644 (file)
index 0000000..5799fbc
--- /dev/null
@@ -0,0 +1,99 @@
+/* Helper functions for Thinkpad LED control;
+ * to be included from codec driver
+ */
+
+#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
+
+#include <linux/acpi.h>
+#include <linux/thinkpad_acpi.h>
+
+static int (*led_set_func)(int, bool);
+static void (*old_vmaster_hook)(void *, int);
+
+static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
+                                void **rv)
+{
+       bool *found = context;
+       *found = true;
+       return AE_OK;
+}
+
+static bool is_thinkpad(struct hda_codec *codec)
+{
+       bool found = false;
+       if (codec->subsystem_id >> 16 != 0x17aa)
+               return false;
+       if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
+               return true;
+       found = false;
+       return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
+}
+
+static void update_tpacpi_mute_led(void *private_data, int enabled)
+{
+       if (old_vmaster_hook)
+               old_vmaster_hook(private_data, enabled);
+
+       if (led_set_func)
+               led_set_func(TPACPI_LED_MUTE, !enabled);
+}
+
+static void update_tpacpi_micmute_led(struct hda_codec *codec,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       if (!ucontrol || !led_set_func)
+               return;
+       if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+               /* TODO: How do I verify if it's a mono or stereo here? */
+               bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
+               led_set_func(TPACPI_LED_MICMUTE, !val);
+       }
+}
+
+static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct hda_gen_spec *spec = codec->spec;
+       bool removefunc = false;
+
+       if (action == HDA_FIXUP_ACT_PROBE) {
+               if (!is_thinkpad(codec))
+                       return;
+               if (!led_set_func)
+                       led_set_func = symbol_request(tpacpi_led_set);
+               if (!led_set_func) {
+                       snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
+                       return;
+               }
+
+               removefunc = true;
+               if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
+                       old_vmaster_hook = spec->vmaster_mute.hook;
+                       spec->vmaster_mute.hook = update_tpacpi_mute_led;
+                       removefunc = false;
+               }
+               if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
+                       if (spec->num_adc_nids > 1)
+                               snd_printdd("Skipping micmute LED control due to several ADCs");
+                       else {
+                               spec->cap_sync_hook = update_tpacpi_micmute_led;
+                               removefunc = false;
+                       }
+               }
+       }
+
+       if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+               symbol_put(tpacpi_led_set);
+               led_set_func = NULL;
+               old_vmaster_hook = NULL;
+       }
+}
+
+#else /* CONFIG_THINKPAD_ACPI */
+
+static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+}
+
+#endif /* CONFIG_THINKPAD_ACPI */
index f59a321a6d6af04d6dce32751410e4eb3f9d9df0..bd90c80bb494e7049d830f13a3e6db46395d09cc 100644 (file)
@@ -584,10 +584,6 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
 {
        dmab->dev.type = SNDRV_DMA_TYPE_DEV;
        dmab->dev.dev = snd_dma_pci_data(pci);
-       if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
-               if (dmab->bytes >= size)
-                       return 0;
-       }
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
                                size, dmab) < 0)
                return -ENOMEM;
@@ -596,10 +592,8 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
 
 static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-       if (dmab->area) {
-               dmab->dev.dev = NULL; /* make it anonymous */
-               snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
-       }
+       if (dmab->area)
+               snd_dma_free_pages(dmab);
 }
 
 
index b96d9e1adf6de027cb57899a6f31998d69988300..1503ee3585fddee141b5df731055325b6a1292cc 100644 (file)
@@ -285,7 +285,7 @@ static char channel_map_9636_ds[26] = {
        /* ADAT channels are remapped */
        1, 3, 5, 7, 9, 11, 13, 15,
        /* channels 8 and 9 are S/PDIF */
-       24, 25
+       24, 25,
        /* others don't exist */
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
@@ -294,10 +294,6 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
 {
        dmab->dev.type = SNDRV_DMA_TYPE_DEV;
        dmab->dev.dev = snd_dma_pci_data(pci);
-       if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
-               if (dmab->bytes >= size)
-                       return 0;
-       }
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
                                size, dmab) < 0)
                return -ENOMEM;
@@ -306,10 +302,8 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
 
 static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-       if (dmab->area) {
-               dmab->dev.dev = NULL; /* make it anonymous */
-               snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
-       }
+       if (dmab->area)
+               snd_dma_free_pages(dmab);
 }
 
 
index a5e3a70c0d3d970450daa6cd6e65bcd693abf835..d62ce483a443a5298688f51462e807e6ea1b2cb4 100644 (file)
@@ -31,6 +31,7 @@ config SND_SOC_GENERIC_DMAENGINE_PCM
        select SND_DMAENGINE_PCM
 
 # All the supported SoCs
+source "sound/soc/adi/Kconfig"
 source "sound/soc/atmel/Kconfig"
 source "sound/soc/au1x/Kconfig"
 source "sound/soc/bcm/Kconfig"
@@ -43,7 +44,7 @@ source "sound/soc/jz4740/Kconfig"
 source "sound/soc/nuc900/Kconfig"
 source "sound/soc/omap/Kconfig"
 source "sound/soc/kirkwood/Kconfig"
-source "sound/soc/mid-x86/Kconfig"
+source "sound/soc/intel/Kconfig"
 source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/samsung/Kconfig"
index b52d4aad07160ec964d0434ee688752a9565833b..62a1822e77bf6f42410fd68c6d539c8cf97c922f 100644 (file)
@@ -8,6 +8,7 @@ endif
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
 obj-$(CONFIG_SND_SOC)  += codecs/
 obj-$(CONFIG_SND_SOC)  += generic/
+obj-$(CONFIG_SND_SOC)  += adi/
 obj-$(CONFIG_SND_SOC)  += atmel/
 obj-$(CONFIG_SND_SOC)  += au1x/
 obj-$(CONFIG_SND_SOC)  += bcm/
@@ -17,7 +18,7 @@ obj-$(CONFIG_SND_SOC) += davinci/
 obj-$(CONFIG_SND_SOC)  += dwc/
 obj-$(CONFIG_SND_SOC)  += fsl/
 obj-$(CONFIG_SND_SOC)  += jz4740/
-obj-$(CONFIG_SND_SOC)  += mid-x86/
+obj-$(CONFIG_SND_SOC)  += intel/
 obj-$(CONFIG_SND_SOC)  += mxs/
 obj-$(CONFIG_SND_SOC)  += nuc900/
 obj-$(CONFIG_SND_SOC)  += omap/
diff --git a/sound/soc/adi/Kconfig b/sound/soc/adi/Kconfig
new file mode 100644 (file)
index 0000000..dd763f5
--- /dev/null
@@ -0,0 +1,21 @@
+config SND_SOC_ADI
+       tristate "Audio support for Analog Devices reference designs"
+       depends on MICROBLAZE || ARCH_ZYNQ || COMPILE_TEST
+       help
+         Audio support for various reference designs by Analog Devices.
+
+config SND_SOC_ADI_AXI_I2S
+       tristate "AXI-I2S support"
+       depends on SND_SOC_ADI
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+       select REGMAP_MMIO
+       help
+         ASoC driver for the Analog Devices AXI-I2S softcore peripheral.
+
+config SND_SOC_ADI_AXI_SPDIF
+       tristate "AXI-SPDIF support"
+       depends on SND_SOC_ADI
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+       select REGMAP_MMIO
+       help
+         ASoC driver for the Analog Devices AXI-SPDIF softcore peripheral.
diff --git a/sound/soc/adi/Makefile b/sound/soc/adi/Makefile
new file mode 100644 (file)
index 0000000..64456c1
--- /dev/null
@@ -0,0 +1,5 @@
+snd-soc-adi-axi-i2s-objs := axi-i2s.o
+snd-soc-adi-axi-spdif-objs := axi-spdif.o
+
+obj-$(CONFIG_SND_SOC_ADI_AXI_I2S) += snd-soc-adi-axi-i2s.o
+obj-$(CONFIG_SND_SOC_ADI_AXI_SPDIF) += snd-soc-adi-axi-spdif.o
diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c
new file mode 100644 (file)
index 0000000..6058c1f
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012-2013, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#define AXI_I2S_REG_RESET      0x00
+#define AXI_I2S_REG_CTRL       0x04
+#define AXI_I2S_REG_CLK_CTRL   0x08
+#define AXI_I2S_REG_STATUS     0x10
+
+#define AXI_I2S_REG_RX_FIFO    0x28
+#define AXI_I2S_REG_TX_FIFO    0x2C
+
+#define AXI_I2S_RESET_GLOBAL   BIT(0)
+#define AXI_I2S_RESET_TX_FIFO  BIT(1)
+#define AXI_I2S_RESET_RX_FIFO  BIT(2)
+
+#define AXI_I2S_CTRL_TX_EN     BIT(0)
+#define AXI_I2S_CTRL_RX_EN     BIT(1)
+
+/* The frame size is configurable, but for now we always set it 64 bit */
+#define AXI_I2S_BITS_PER_FRAME 64
+
+struct axi_i2s {
+       struct regmap *regmap;
+       struct clk *clk;
+       struct clk *clk_ref;
+
+       struct snd_soc_dai_driver dai_driver;
+
+       struct snd_dmaengine_dai_dma_data capture_dma_data;
+       struct snd_dmaengine_dai_dma_data playback_dma_data;
+
+       struct snd_ratnum ratnum;
+       struct snd_pcm_hw_constraint_ratnums rate_constraints;
+};
+
+static int axi_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+       struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+       unsigned int mask, val;
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               mask = AXI_I2S_CTRL_RX_EN;
+       else
+               mask = AXI_I2S_CTRL_TX_EN;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               val = mask;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(i2s->regmap, AXI_I2S_REG_CTRL, mask, val);
+
+       return 0;
+}
+
+static int axi_i2s_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+       unsigned int bclk_div, word_size;
+       unsigned int bclk_rate;
+
+       bclk_rate = params_rate(params) * AXI_I2S_BITS_PER_FRAME;
+
+       word_size = AXI_I2S_BITS_PER_FRAME / 2 - 1;
+       bclk_div = DIV_ROUND_UP(clk_get_rate(i2s->clk_ref), bclk_rate) / 2 - 1;
+
+       regmap_write(i2s->regmap, AXI_I2S_REG_CLK_CTRL, (word_size << 16) |
+               bclk_div);
+
+       return 0;
+}
+
+static int axi_i2s_startup(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+       uint32_t mask;
+       int ret;
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               mask = AXI_I2S_RESET_RX_FIFO;
+       else
+               mask = AXI_I2S_RESET_TX_FIFO;
+
+       regmap_write(i2s->regmap, AXI_I2S_REG_RESET, mask);
+
+       ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_RATE,
+                          &i2s->rate_constraints);
+       if (ret)
+               return ret;
+
+       return clk_prepare_enable(i2s->clk_ref);
+}
+
+static void axi_i2s_shutdown(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+       clk_disable_unprepare(i2s->clk_ref);
+}
+
+static int axi_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data,
+               &i2s->capture_dma_data);
+
+       return 0;
+}
+
+static const struct snd_soc_dai_ops axi_i2s_dai_ops = {
+       .startup = axi_i2s_startup,
+       .shutdown = axi_i2s_shutdown,
+       .trigger = axi_i2s_trigger,
+       .hw_params = axi_i2s_hw_params,
+};
+
+static struct snd_soc_dai_driver axi_i2s_dai = {
+       .probe = axi_i2s_dai_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_KNOT,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE,
+       },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_KNOT,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE,
+       },
+       .ops = &axi_i2s_dai_ops,
+       .symmetric_rates = 1,
+};
+
+static const struct snd_soc_component_driver axi_i2s_component = {
+       .name = "axi-i2s",
+};
+
+static const struct regmap_config axi_i2s_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = AXI_I2S_REG_STATUS,
+};
+
+static int axi_i2s_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct axi_i2s *i2s;
+       void __iomem *base;
+       int ret;
+
+       i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
+       if (!i2s)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, i2s);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       i2s->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+               &axi_i2s_regmap_config);
+       if (IS_ERR(i2s->regmap))
+               return PTR_ERR(i2s->regmap);
+
+       i2s->clk = devm_clk_get(&pdev->dev, "axi");
+       if (IS_ERR(i2s->clk))
+               return PTR_ERR(i2s->clk);
+
+       i2s->clk_ref = devm_clk_get(&pdev->dev, "ref");
+       if (IS_ERR(i2s->clk_ref))
+               return PTR_ERR(i2s->clk_ref);
+
+       ret = clk_prepare_enable(i2s->clk);
+       if (ret)
+               return ret;
+
+       i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO;
+       i2s->playback_dma_data.addr_width = 4;
+       i2s->playback_dma_data.maxburst = 1;
+
+       i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO;
+       i2s->capture_dma_data.addr_width = 4;
+       i2s->capture_dma_data.maxburst = 1;
+
+       i2s->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME;
+       i2s->ratnum.den_step = 1;
+       i2s->ratnum.den_min = 1;
+       i2s->ratnum.den_max = 64;
+
+       i2s->rate_constraints.rats = &i2s->ratnum;
+       i2s->rate_constraints.nrats = 1;
+
+       regmap_write(i2s->regmap, AXI_I2S_REG_RESET, AXI_I2S_RESET_GLOBAL);
+
+       ret = devm_snd_soc_register_component(&pdev->dev, &axi_i2s_component,
+                                        &axi_i2s_dai, 1);
+       if (ret)
+               goto err_clk_disable;
+
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (ret)
+               goto err_clk_disable;
+
+err_clk_disable:
+       clk_disable_unprepare(i2s->clk);
+       return ret;
+}
+
+static int axi_i2s_dev_remove(struct platform_device *pdev)
+{
+       struct axi_i2s *i2s = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(i2s->clk);
+
+       return 0;
+}
+
+static const struct of_device_id axi_i2s_of_match[] = {
+       { .compatible = "adi,axi-i2s-1.00.a", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, axi_i2s_of_match);
+
+static struct platform_driver axi_i2s_driver = {
+       .driver = {
+               .name = "axi-i2s",
+               .owner = THIS_MODULE,
+               .of_match_table = axi_i2s_of_match,
+       },
+       .probe = axi_i2s_probe,
+       .remove = axi_i2s_dev_remove,
+};
+module_platform_driver(axi_i2s_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("AXI I2S driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/adi/axi-spdif.c b/sound/soc/adi/axi-spdif.c
new file mode 100644 (file)
index 0000000..198e3a4
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2012-2013, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/dmaengine_pcm.h>
+
+#define AXI_SPDIF_REG_CTRL     0x0
+#define AXI_SPDIF_REG_STAT     0x4
+#define AXI_SPDIF_REG_TX_FIFO  0xc
+
+#define AXI_SPDIF_CTRL_TXDATA BIT(1)
+#define AXI_SPDIF_CTRL_TXEN BIT(0)
+#define AXI_SPDIF_CTRL_CLKDIV_OFFSET 8
+#define AXI_SPDIF_CTRL_CLKDIV_MASK (0xff << 8)
+
+#define AXI_SPDIF_FREQ_44100   (0x0 << 6)
+#define AXI_SPDIF_FREQ_48000   (0x1 << 6)
+#define AXI_SPDIF_FREQ_32000   (0x2 << 6)
+#define AXI_SPDIF_FREQ_NA      (0x3 << 6)
+
+struct axi_spdif {
+       struct regmap *regmap;
+       struct clk *clk;
+       struct clk *clk_ref;
+
+       struct snd_dmaengine_dai_dma_data dma_data;
+
+       struct snd_ratnum ratnum;
+       struct snd_pcm_hw_constraint_ratnums rate_constraints;
+};
+
+static int axi_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+       struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+       unsigned int val;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               val = AXI_SPDIF_CTRL_TXDATA;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_TXDATA, val);
+
+       return 0;
+}
+
+static int axi_spdif_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+       unsigned int rate = params_rate(params);
+       unsigned int clkdiv, stat;
+
+       switch (params_rate(params)) {
+       case 32000:
+               stat = AXI_SPDIF_FREQ_32000;
+               break;
+       case 44100:
+               stat = AXI_SPDIF_FREQ_44100;
+               break;
+       case 48000:
+               stat = AXI_SPDIF_FREQ_48000;
+               break;
+       default:
+               stat = AXI_SPDIF_FREQ_NA;
+               break;
+       }
+
+       clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(spdif->clk_ref),
+                       rate * 64 * 2) - 1;
+       clkdiv <<= AXI_SPDIF_CTRL_CLKDIV_OFFSET;
+
+       regmap_write(spdif->regmap, AXI_SPDIF_REG_STAT, stat);
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_CLKDIV_MASK, clkdiv);
+
+       return 0;
+}
+
+static int axi_spdif_dai_probe(struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &spdif->dma_data, NULL);
+
+       return 0;
+}
+
+static int axi_spdif_startup(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+       int ret;
+
+       ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_RATE,
+                          &spdif->rate_constraints);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(spdif->clk_ref);
+       if (ret)
+               return ret;
+
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_TXEN, AXI_SPDIF_CTRL_TXEN);
+
+       return 0;
+}
+
+static void axi_spdif_shutdown(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_TXEN, 0);
+
+       clk_disable_unprepare(spdif->clk_ref);
+}
+
+static const struct snd_soc_dai_ops axi_spdif_dai_ops = {
+       .startup = axi_spdif_startup,
+       .shutdown = axi_spdif_shutdown,
+       .trigger = axi_spdif_trigger,
+       .hw_params = axi_spdif_hw_params,
+};
+
+static struct snd_soc_dai_driver axi_spdif_dai = {
+       .probe = axi_spdif_dai_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_KNOT,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = &axi_spdif_dai_ops,
+};
+
+static const struct snd_soc_component_driver axi_spdif_component = {
+       .name = "axi-spdif",
+};
+
+static const struct regmap_config axi_spdif_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = AXI_SPDIF_REG_STAT,
+};
+
+static int axi_spdif_probe(struct platform_device *pdev)
+{
+       struct axi_spdif *spdif;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
+       if (!spdif)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, spdif);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       spdif->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                           &axi_spdif_regmap_config);
+       if (IS_ERR(spdif->regmap))
+               return PTR_ERR(spdif->regmap);
+
+       spdif->clk = devm_clk_get(&pdev->dev, "axi");
+       if (IS_ERR(spdif->clk))
+               return PTR_ERR(spdif->clk);
+
+       spdif->clk_ref = devm_clk_get(&pdev->dev, "ref");
+       if (IS_ERR(spdif->clk_ref))
+               return PTR_ERR(spdif->clk_ref);
+
+       ret = clk_prepare_enable(spdif->clk);
+       if (ret)
+               return ret;
+
+       spdif->dma_data.addr = res->start + AXI_SPDIF_REG_TX_FIFO;
+       spdif->dma_data.addr_width = 4;
+       spdif->dma_data.maxburst = 1;
+
+       spdif->ratnum.num = clk_get_rate(spdif->clk_ref) / 128;
+       spdif->ratnum.den_step = 1;
+       spdif->ratnum.den_min = 1;
+       spdif->ratnum.den_max = 64;
+
+       spdif->rate_constraints.rats = &spdif->ratnum;
+       spdif->rate_constraints.nrats = 1;
+
+       ret = devm_snd_soc_register_component(&pdev->dev, &axi_spdif_component,
+                                        &axi_spdif_dai, 1);
+       if (ret)
+               goto err_clk_disable;
+
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (ret)
+               goto err_clk_disable;
+
+       return 0;
+
+err_clk_disable:
+       clk_disable_unprepare(spdif->clk);
+       return ret;
+}
+
+static int axi_spdif_dev_remove(struct platform_device *pdev)
+{
+       struct axi_spdif *spdif = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(spdif->clk);
+
+       return 0;
+}
+
+static const struct of_device_id axi_spdif_of_match[] = {
+       { .compatible = "adi,axi-spdif-tx-1.00.a", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, axi_spdif_of_match);
+
+static struct platform_driver axi_spdif_driver = {
+       .driver = {
+               .name = "axi-spdif",
+               .owner = THIS_MODULE,
+               .of_match_table = axi_spdif_of_match,
+       },
+       .probe = axi_spdif_probe,
+       .remove = axi_spdif_dev_remove,
+};
+module_platform_driver(axi_spdif_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("AXI SPDIF driver");
+MODULE_LICENSE("GPL");
index 06082e5e5dcb7d726e2bdba6e5f2d7f816dcf262..b79a2a864513e4a071879a0cfcc0033678dc1be2 100644 (file)
@@ -50,7 +50,6 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
                                  SNDRV_PCM_INFO_INTERLEAVED |
                                  SNDRV_PCM_INFO_RESUME |
                                  SNDRV_PCM_INFO_PAUSE,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
        .period_bytes_min       = 256,          /* lighting DMA overhead */
        .period_bytes_max       = 2 * 0xffff,   /* if 2 bytes format */
        .periods_min            = 8,
index 054ea4d9326a2e34f8f9bc6f6ae51f18fb1d98dd..33ec592ecd75d8f6f27c567effcd86551ec1632b 100644 (file)
@@ -58,7 +58,6 @@ static const struct snd_pcm_hardware atmel_pcm_hardware = {
                                  SNDRV_PCM_INFO_MMAP_VALID |
                                  SNDRV_PCM_INFO_INTERLEAVED |
                                  SNDRV_PCM_INFO_PAUSE,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
        .period_bytes_min       = 32,
        .period_bytes_max       = 8192,
        .periods_min            = 2,
index 8697cedccd21240f76b4b5076ba6d0968a394d75..1ead3c977a51743619b0bb2084ec174b7cf867a8 100644 (file)
@@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 
        dma_params = ssc_p->dma_params[dir];
 
-       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
        ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
        pr_debug("%s enabled SSC_SR=0x%08x\n",
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
+                            int cmd, struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct atmel_pcm_dma_params *dma_params;
+       int dir;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dir = 0;
+       else
+               dir = 1;
+
+       dma_params = ssc_p->dma_params[dir];
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+               break;
+       default:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+               break;
+       }
+
+       return 0;
+}
 
 #ifdef CONFIG_PM
 static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
@@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .startup        = atmel_ssc_startup,
        .shutdown       = atmel_ssc_shutdown,
        .prepare        = atmel_ssc_prepare,
+       .trigger        = atmel_ssc_trigger,
        .hw_params      = atmel_ssc_hw_params,
        .set_fmt        = atmel_ssc_set_dai_fmt,
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
index 992ae38d5a15afda177080da1032300bcffd18ac..3188036a18f004ad5e68f56ef4c10e3757c43f06 100644 (file)
@@ -97,6 +97,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
                goto out;
        }
 
+       snd_soc_card_set_drvdata(card, priv);
+
        card->dev = &pdev->dev;
        card->owner = THIS_MODULE;
        card->dai_link = dai;
@@ -107,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
        dai->stream_name = "WM8731 PCM";
        dai->codec_dai_name = "wm8731-hifi";
        dai->init = sam9x5_wm8731_init;
-       dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+       dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
                | SND_SOC_DAIFMT_CBM_CFM;
 
        ret = snd_soc_of_parse_card_name(card, "atmel,model");
@@ -153,8 +155,6 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
        of_node_put(codec_np);
        of_node_put(cpu_np);
 
-       platform_set_drvdata(pdev, card);
-
        ret = snd_soc_register_card(card);
        if (ret) {
                dev_err(&pdev->dev,
index 3b4eafaf30d3177d223f1a28c4374e55d32e8e68..17a24d804734f7539b456751708a206c9925319f 100644 (file)
@@ -65,19 +65,10 @@ struct au1xpsc_audio_dmadata {
 #define AU1XPSC_PERIOD_MIN_BYTES       1024
 #define AU1XPSC_BUFFER_MIN_BYTES       65536
 
-#define AU1XPSC_PCM_FMTS                                       \
-       (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_U8 |        \
-        SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |    \
-        SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |    \
-        SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |    \
-        SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE |    \
-        0)
-
 /* PCM hardware DMA capabilities - platform specific */
 static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
        .info             = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
                            SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
-       .formats          = AU1XPSC_PCM_FMTS,
        .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES,
        .period_bytes_max = 4096 * 1024 - 1,
        .periods_min      = 2,
index befd1074f9bdbd9b008dc6324b5669a7f8a549c7..e920b60bf6c2f9fe2a43cc515ba4dec69a977127 100644 (file)
 
 #include "psc.h"
 
-#define ALCHEMY_PCM_FMTS                                       \
-       (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_U8 |        \
-        SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |    \
-        SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |    \
-        SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |    \
-        SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE |    \
-        0)
-
 struct pcm_period {
        u32 start;
        u32 relative_end;       /* relative to start of buffer */
@@ -171,12 +163,6 @@ static irqreturn_t au1000_dma_interrupt(int irq, void *ptr)
 static const struct snd_pcm_hardware alchemy_pcm_hardware = {
        .info             = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
                            SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
-       .formats          = ALCHEMY_PCM_FMTS,
-       .rates            = SNDRV_PCM_RATE_8000_192000,
-       .rate_min         = SNDRV_PCM_RATE_8000,
-       .rate_max         = SNDRV_PCM_RATE_192000,
-       .channels_min     = 2,
-       .channels_max     = 2,
        .period_bytes_min = 1024,
        .period_bytes_max = 16 * 1024 - 1,
        .periods_min      = 4,
index 1d4c676eb6cc696e78f6722525923c91e3afe936..cdb8ee75ded924de68bbf33b168af3489c0fadcc 100644 (file)
@@ -107,7 +107,6 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
 #endif
                                   SNDRV_PCM_INFO_BLOCK_TRANSFER,
 
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
        .period_bytes_min       = 32,
        .period_bytes_max       = 0x10000,
        .periods_min            = 1,
index 2a5b43417fd5a5810ac36d1cc258f97987e9066a..a3881c4381c9151771ffca5e5133ef01707ba9ea 100644 (file)
@@ -52,9 +52,6 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
        .info                   = SNDRV_PCM_INFO_INTERLEAVED |
                                   SNDRV_PCM_INFO_MMAP_VALID |
                                   SNDRV_PCM_INFO_BLOCK_TRANSFER,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE |
-                                  SNDRV_PCM_FMTBIT_S24_LE |
-                                  SNDRV_PCM_FMTBIT_S32_LE,
        .period_bytes_min       = 32,
        .period_bytes_max       = 0x10000,
        .periods_min            = 1,
index c43fb214558a78f4bfef1c51ba316e860e3f3e13..4f900efc437c7ac136ecc3ed35ab3969c059d035 100644 (file)
@@ -63,7 +63,7 @@ static struct snd_soc_ops edb93xx_ops = {
 static struct snd_soc_dai_link edb93xx_dai = {
        .name           = "CS4271",
        .stream_name    = "CS4271 HiFi",
-       .platform_name  = "ep93xx-pcm-audio",
+       .platform_name  = "ep93xx-i2s",
        .cpu_dai_name   = "ep93xx-i2s",
        .codec_name     = "spi0.0",
        .codec_dai_name = "cs4271-hifi",
index efa75b5086a4b00e83802d476c87aae0a6914d0e..f30dadf85b9963a71629df4be96ec8f1fb05c3bb 100644 (file)
 #include <linux/slab.h>
 
 #include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/soc.h>
 
 #include <linux/platform_data/dma-ep93xx.h>
 
+#include "ep93xx-pcm.h"
+
 /*
  * Per channel (1-4) registers.
  */
@@ -95,6 +98,8 @@ struct ep93xx_ac97_info {
        struct device           *dev;
        void __iomem            *regs;
        struct completion       done;
+       struct snd_dmaengine_dai_dma_data dma_params_rx;
+       struct snd_dmaengine_dai_dma_data dma_params_tx;
 };
 
 /* currently ALSA only supports a single AC97 device */
@@ -315,8 +320,13 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
 
 static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai)
 {
-       dai->playback_dma_data = &ep93xx_ac97_pcm_out;
-       dai->capture_dma_data = &ep93xx_ac97_pcm_in;
+       struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
+
+       info->dma_params_tx.filter_data = &ep93xx_ac97_pcm_out;
+       info->dma_params_rx.filter_data = &ep93xx_ac97_pcm_in;
+
+       dai->playback_dma_data = &info->dma_params_tx;
+       dai->capture_dma_data = &info->dma_params_rx;
 
        return 0;
 }
@@ -394,8 +404,14 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
        if (ret)
                goto fail;
 
+       ret = devm_ep93xx_pcm_platform_register(&pdev->dev);
+       if (ret)
+               goto fail_unregister;
+
        return 0;
 
+fail_unregister:
+       snd_soc_unregister_component(&pdev->dev);
 fail:
        ep93xx_ac97_info = NULL;
        snd_soc_set_ac97_ops(NULL);
index a57643d6402f08ef5613aedd72ba005b4181ac77..943145f9d1b6f4a6ce521e99197baadc0fc2ba8c 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 
 #include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
@@ -30,6 +31,8 @@
 #include <mach/ep93xx-regs.h>
 #include <linux/platform_data/dma-ep93xx.h>
 
+#include "ep93xx-pcm.h"
+
 #define EP93XX_I2S_TXCLKCFG            0x00
 #define EP93XX_I2S_RXCLKCFG            0x04
 #define EP93XX_I2S_GLCTRL              0x0C
@@ -61,6 +64,8 @@ struct ep93xx_i2s_info {
        struct clk                      *sclk;
        struct clk                      *lrclk;
        void __iomem                    *regs;
+       struct snd_dmaengine_dai_dma_data dma_params_rx;
+       struct snd_dmaengine_dai_dma_data dma_params_tx;
 };
 
 static struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
@@ -140,8 +145,15 @@ static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
 
 static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai)
 {
-       dai->playback_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK];
-       dai->capture_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE];
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+
+       info->dma_params_tx.filter_data =
+               &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK];
+       info->dma_params_rx.filter_data =
+               &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE];
+
+       dai->playback_dma_data = &info->dma_params_tx;
+       dai->capture_dma_data = &info->dma_params_rx;
 
        return 0;
 }
@@ -405,8 +417,14 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
        if (err)
                goto fail_put_lrclk;
 
+       err = devm_ep93xx_pcm_platform_register(&pdev->dev);
+       if (err)
+               goto fail_unregister;
+
        return 0;
 
+fail_unregister:
+       snd_soc_unregister_component(&pdev->dev);
 fail_put_lrclk:
        clk_put(info->lrclk);
 fail_put_sclk:
index cfe517e6800969ab64c91c563c7b5839fc46da66..5f664471d99ee480fd38bd723e65d8023462973c 100644 (file)
 
 #include <linux/platform_data/dma-ep93xx.h>
 
+#include "ep93xx-pcm.h"
+
 static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
        .info                   = (SNDRV_PCM_INFO_MMAP          |
                                   SNDRV_PCM_INFO_MMAP_VALID    |
                                   SNDRV_PCM_INFO_INTERLEAVED   |
                                   SNDRV_PCM_INFO_BLOCK_TRANSFER),
-                                  
-       .rates                  = SNDRV_PCM_RATE_8000_192000,
-       .rate_min               = SNDRV_PCM_RATE_8000,
-       .rate_max               = SNDRV_PCM_RATE_192000,
-       
-       .formats                = (SNDRV_PCM_FMTBIT_S16_LE |
-                                  SNDRV_PCM_FMTBIT_S24_LE |
-                                  SNDRV_PCM_FMTBIT_S32_LE),
-       
        .buffer_bytes_max       = 131072,
        .period_bytes_min       = 32,
        .period_bytes_max       = 32768,
@@ -57,53 +50,22 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
        return false;
 }
 
-static struct dma_chan *ep93xx_compat_request_channel(
-       struct snd_soc_pcm_runtime *rtd,
-       struct snd_pcm_substream *substream)
-{
-       struct snd_dmaengine_dai_dma_data *dma_data;
-
-       dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-       return snd_dmaengine_pcm_request_channel(ep93xx_pcm_dma_filter,
-                                                dma_data);
-}
-
 static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = {
        .pcm_hardware = &ep93xx_pcm_hardware,
        .compat_filter_fn = ep93xx_pcm_dma_filter,
-       .compat_request_channel = ep93xx_compat_request_channel,
        .prealloc_buffer_size = 131072,
 };
 
-static int ep93xx_soc_platform_probe(struct platform_device *pdev)
+int devm_ep93xx_pcm_platform_register(struct device *dev)
 {
-       return snd_dmaengine_pcm_register(&pdev->dev,
+       return devm_snd_dmaengine_pcm_register(dev,
                &ep93xx_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
                SND_DMAENGINE_PCM_FLAG_NO_DT |
                SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
-
-static int ep93xx_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_dmaengine_pcm_unregister(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver ep93xx_pcm_driver = {
-       .driver = {
-                       .name = "ep93xx-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-
-       .probe = ep93xx_soc_platform_probe,
-       .remove = ep93xx_soc_platform_remove,
-};
-
-module_platform_driver(ep93xx_pcm_driver);
+EXPORT_SYMBOL_GPL(devm_ep93xx_pcm_platform_register);
 
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ep93xx-pcm-audio");
diff --git a/sound/soc/cirrus/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h
new file mode 100644 (file)
index 0000000..b7a12a2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __EP93XX_PCM_H__
+#define __EP93XX_PCM_H__
+
+int devm_ep93xx_pcm_platform_register(struct device *dev);
+
+#endif
index 4d094d00c34a295645642abc0923d1d221c05967..822a19a89e742e96d28b29a22f28a74d9c4a9298 100644 (file)
@@ -27,7 +27,7 @@ static struct snd_soc_dai_link simone_dai = {
        .cpu_dai_name   = "ep93xx-ac97",
        .codec_dai_name = "ac97-hifi",
        .codec_name     = "ac97-codec",
-       .platform_name  = "ep93xx-pcm-audio",
+       .platform_name  = "ep93xx-ac97",
 };
 
 static struct snd_soc_card snd_soc_simone = {
index 69041074f2c1a5df2083a2794ef9fd660113d6d7..29238a7476dd87e002d7500d0fffb3f37eada3d0 100644 (file)
@@ -83,7 +83,7 @@ static struct snd_soc_dai_link snappercl15_dai = {
        .cpu_dai_name   = "ep93xx-i2s",
        .codec_dai_name = "tlv320aic23-hifi",
        .codec_name     = "tlv320aic23-codec.0-001a",
-       .platform_name  =  "ep93xx-pcm-audio",
+       .platform_name  = "ep93xx-i2s",
        .init           = snappercl15_tlv320aic23_init,
        .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
                          SND_SOC_DAIFMT_CBS_CFS,
index b33b45dfceec54b205c512ca01638d947df56f66..983d087aa92aa83125903dc18cd420f57c2009eb 100644 (file)
@@ -163,8 +163,10 @@ config SND_SOC_WM_HUBS
 config SND_SOC_WM_ADSP
        tristate
        default y if SND_SOC_WM5102=y
+       default y if SND_SOC_WM5110=y
        default y if SND_SOC_WM2200=y
        default m if SND_SOC_WM5102=m
+       default m if SND_SOC_WM5110=m
        default m if SND_SOC_WM2200=m
 
 config SND_SOC_AB8500_CODEC
index 9a92b7962f41b67e3ba8461d1a88c584ef4822b0..77f459868579ad7f90d262f683f32e07ae4506a8 100644 (file)
@@ -168,17 +168,19 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
        int word_len = 0;
 
        /* bit size */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                word_len = AD1836_WORD_LEN_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                word_len = AD1836_WORD_LEN_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 24:
+       case 32:
                word_len = AD1836_WORD_LEN_24;
                break;
+       default:
+               return -EINVAL;
        }
 
        regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1,
index aea7e52cf714117a445347cbe528f6732d2bd662..5a42dca535b77c43f8f63e7131ce09aeb7943e4b 100644 (file)
@@ -249,15 +249,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
        struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
 
        /* bit size */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                word_len = 3;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                word_len = 1;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 24:
+       case 32:
                word_len = 0;
                break;
        }
@@ -413,7 +413,7 @@ static struct spi_driver ad193x_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 
 static const struct regmap_config ad193x_i2c_regmap_config = {
        .val_bits = 8,
@@ -470,7 +470,7 @@ static int __init ad193x_modinit(void)
 {
        int ret;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret =  i2c_add_driver(&ad193x_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
@@ -495,7 +495,7 @@ static void __exit ad193x_modexit(void)
        spi_unregister_driver(&ad193x_spi_driver);
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&ad193x_i2c_driver);
 #endif
 }
index 59654b1e7f3fbcd1262dca4c1066e505980aee2b..eb836ed5271f448631ad1268ddd548b69db39c51 100644 (file)
@@ -1078,17 +1078,17 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
                ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
                (div << 2) | ADAU1373_BCLKDIV_64);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                ctrl = ADAU1373_DAI_WLEN_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                ctrl = ADAU1373_DAI_WLEN_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                ctrl = ADAU1373_DAI_WLEN_24;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                ctrl = ADAU1373_DAI_WLEN_32;
                break;
        default:
index ebff1128be595ca7ff63f5ca049d2f30342dee45..d71c59cf7bdd5210ac20ee2c3d76d8d7578385da 100644 (file)
@@ -71,7 +71,7 @@
 
 #define ADAU1701_SEROCTL_WORD_LEN_24   0x0000
 #define ADAU1701_SEROCTL_WORD_LEN_20   0x0001
-#define ADAU1701_SEROCTL_WORD_LEN_16   0x0010
+#define ADAU1701_SEROCTL_WORD_LEN_16   0x0002
 #define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003
 
 #define ADAU1701_AUXNPOW_VBPD          0x40
@@ -299,20 +299,20 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
 }
 
 static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec,
-               snd_pcm_format_t format)
+                                          struct snd_pcm_hw_params *params)
 {
        struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
        unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK;
        unsigned int val;
 
-       switch (format) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                val = ADAU1701_SEROCTL_WORD_LEN_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                val = ADAU1701_SEROCTL_WORD_LEN_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                val = ADAU1701_SEROCTL_WORD_LEN_24;
                break;
        default:
@@ -320,14 +320,14 @@ static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec,
        }
 
        if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) {
-               switch (format) {
-               case SNDRV_PCM_FORMAT_S16_LE:
+               switch (params_width(params)) {
+               case 16:
                        val |= ADAU1701_SEROCTL_MSB_DEALY16;
                        break;
-               case SNDRV_PCM_FORMAT_S20_3LE:
+               case 20:
                        val |= ADAU1701_SEROCTL_MSB_DEALY12;
                        break;
-               case SNDRV_PCM_FORMAT_S24_LE:
+               case 24:
                        val |= ADAU1701_SEROCTL_MSB_DEALY8;
                        break;
                }
@@ -340,7 +340,7 @@ static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec,
 }
 
 static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec,
-                       snd_pcm_format_t format)
+                                           struct snd_pcm_hw_params *params)
 {
        struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
@@ -348,14 +348,14 @@ static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec,
        if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
                return 0;
 
-       switch (format) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                val = ADAU1701_SERICTL_RIGHTJ_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                val = ADAU1701_SERICTL_RIGHTJ_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                val = ADAU1701_SERICTL_RIGHTJ_24;
                break;
        default:
@@ -374,7 +374,6 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = dai->codec;
        struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
        unsigned int clkdiv = adau1701->sysclk / params_rate(params);
-       snd_pcm_format_t format;
        unsigned int val;
        int ret;
 
@@ -406,11 +405,10 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream,
        regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL,
                ADAU1701_DSPCTRL_SR_MASK, val);
 
-       format = params_format(params);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               return adau1701_set_playback_pcm_format(codec, format);
+               return adau1701_set_playback_pcm_format(codec, params);
        else
-               return adau1701_set_capture_pcm_format(codec, format);
+               return adau1701_set_capture_pcm_format(codec, params);
 }
 
 static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai,
index 14a7c169d004ebf97fabbbccfd8df0434327c639..f78b27a7c461d3e5580dad311fd583f30755a3b4 100644 (file)
@@ -453,22 +453,22 @@ static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
 }
 
 static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
-               struct snd_soc_dai *dai, snd_pcm_format_t format)
+               struct snd_soc_dai *dai, struct snd_pcm_hw_params *params)
 {
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
 
-       switch (format) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                val = ADAV80X_CAPTURE_WORD_LEN16;
                break;
-       case SNDRV_PCM_FORMAT_S18_3LE:
+       case 18:
                val = ADAV80X_CAPTRUE_WORD_LEN18;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                val = ADAV80X_CAPTURE_WORD_LEN20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                val = ADAV80X_CAPTURE_WORD_LEN24;
                break;
        default:
@@ -482,7 +482,7 @@ static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
 }
 
 static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec,
-               struct snd_soc_dai *dai, snd_pcm_format_t format)
+               struct snd_soc_dai *dai, struct snd_pcm_hw_params *params)
 {
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
@@ -490,17 +490,17 @@ static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec,
        if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J)
                return 0;
 
-       switch (format) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16;
                break;
-       case SNDRV_PCM_FORMAT_S18_3LE:
+       case 18:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24;
                break;
        default:
@@ -524,12 +524,10 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               adav80x_set_playback_pcm_format(codec, dai,
-                       params_format(params));
+               adav80x_set_playback_pcm_format(codec, dai, params);
                adav80x_set_dac_clock(codec, rate);
        } else {
-               adav80x_set_capture_pcm_format(codec, dai,
-                       params_format(params));
+               adav80x_set_capture_pcm_format(codec, dai, params);
                adav80x_set_adc_clock(codec, rate);
        }
        adav80x->rate = rate;
@@ -939,7 +937,7 @@ static struct spi_driver adav80x_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static const struct regmap_config adav80x_i2c_regmap_config = {
        .val_bits = 8,
        .pad_bits = 1,
@@ -985,7 +983,7 @@ static int __init adav80x_init(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&adav80x_i2c_driver);
        if (ret)
                return ret;
@@ -1001,7 +999,7 @@ module_init(adav80x_init);
 
 static void __exit adav80x_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&adav80x_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 49cc5f6d6dba41cd1d45712fc15037d8031ddaf5..94cbe508dd3748723197f7443f5a6ed8524b2b14 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -30,6 +31,7 @@
 
 /* codec private data */
 struct ak4641_priv {
+       struct regmap *regmap;
        unsigned int sysclk;
        int deemph;
        int playback_fs;
@@ -38,12 +40,12 @@ struct ak4641_priv {
 /*
  * ak4641 register cache
  */
-static const u8 ak4641_reg[AK4641_CACHEREGNUM] = {
-       0x00, 0x80, 0x00, 0x80,
-       0x02, 0x00, 0x11, 0x05,
-       0x00, 0x00, 0x36, 0x10,
-       0x00, 0x00, 0x57, 0x00,
-       0x88, 0x88, 0x08, 0x08
+static const struct reg_default ak4641_reg_defaults[] = {
+       {  0, 0x00 }, {  1, 0x80 }, {  2, 0x00 }, {  3, 0x80 },
+       {  4, 0x02 }, {  5, 0x00 }, {  6, 0x11 }, {  7, 0x05 },
+       {  8, 0x00 }, {  9, 0x00 }, { 10, 0x36 }, { 11, 0x10 },
+       { 12, 0x00 }, { 13, 0x00 }, { 14, 0x57 }, { 15, 0x00 },
+       { 16, 0x88 }, { 17, 0x88 }, { 18, 0x08 }, { 19, 0x08 }
 };
 
 static const int deemph_settings[] = {44100, 0, 48000, 32000};
@@ -396,6 +398,7 @@ static int ak4641_mute(struct snd_soc_dai *dai, int mute)
 static int ak4641_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
        struct ak4641_platform_data *pdata = codec->dev->platform_data;
        int ret;
 
@@ -417,7 +420,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
                                gpio_set_value(pdata->gpio_npdn, 1);
                        mdelay(1);
 
-                       ret = snd_soc_cache_sync(codec);
+                       ret = regcache_sync(ak4641->regmap);
                        if (ret) {
                                dev_err(codec->dev,
                                        "Failed to sync cache: %d\n", ret);
@@ -433,7 +436,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
                        gpio_set_value(pdata->gpio_npdn, 0);
                if (pdata && gpio_is_valid(pdata->gpio_power))
                        gpio_set_value(pdata->gpio_power, 0);
-               codec->cache_sync = 1;
+               regcache_mark_dirty(ak4641->regmap);
                break;
        }
        codec->dapm.bias_level = level;
@@ -518,7 +521,7 @@ static int ak4641_probe(struct snd_soc_codec *codec)
 {
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -550,12 +553,17 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
        .dapm_routes            = ak4641_audio_map,
        .num_dapm_routes        = ARRAY_SIZE(ak4641_audio_map),
        .set_bias_level         = ak4641_set_bias_level,
-       .reg_cache_size         = ARRAY_SIZE(ak4641_reg),
-       .reg_word_size          = sizeof(u8),
-       .reg_cache_default      = ak4641_reg,
-       .reg_cache_step         = 1,
 };
 
+static const struct regmap_config ak4641_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = AK4641_BTIF,
+       .reg_defaults = ak4641_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(ak4641_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
 
 static int ak4641_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
@@ -569,6 +577,10 @@ static int ak4641_i2c_probe(struct i2c_client *i2c,
        if (!ak4641)
                return -ENOMEM;
 
+       ak4641->regmap = devm_regmap_init_i2c(i2c, &ak4641_regmap);
+       if (IS_ERR(ak4641->regmap))
+               return PTR_ERR(ak4641->regmap);
+
        if (pdata) {
                if (gpio_is_valid(pdata->gpio_power)) {
                        ret = gpio_request_one(pdata->gpio_power,
index 090d499bb7ebca49d34fd2ac3142b782f8f46a1b..1f646c6e90c6b3ff688e0fd2582fcb1268679bb1 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/module.h>
+#include <linux/regmap.h>
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
@@ -198,30 +199,30 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
 /*
  * ak4642 register cache
  */
-static const u8 ak4642_reg[] = {
-       0x00, 0x00, 0x01, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0xe1, 0xe1, 0x18, 0x00,
-       0xe1, 0x18, 0x11, 0x08,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00,
+static const struct reg_default ak4642_reg[] = {
+       {  0, 0x00 }, {  1, 0x00 }, {  2, 0x01 }, {  3, 0x00 },
+       {  4, 0x02 }, {  5, 0x00 }, {  6, 0x00 }, {  7, 0x00 },
+       {  8, 0xe1 }, {  9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
+       { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0x08 },
+       { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 },
+       { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 },
+       { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 },
+       { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 },
+       { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 },
+       { 36, 0x00 },
 };
 
-static const u8 ak4648_reg[] = {
-       0x00, 0x00, 0x01, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0xe1, 0xe1, 0x18, 0x00,
-       0xe1, 0x18, 0x11, 0xb8,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x88, 0x88, 0x08,
+static const struct reg_default ak4648_reg[] = {
+       {  0, 0x00 }, {  1, 0x00 }, {  2, 0x01 }, {  3, 0x00 },
+       {  4, 0x02 }, {  5, 0x00 }, {  6, 0x00 }, {  7, 0x00 },
+       {  8, 0xe1 }, {  9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
+       { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0xb8 },
+       { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 },
+       { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 },
+       { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 },
+       { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 },
+       { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 },
+       { 36, 0x00 }, { 37, 0x88 }, { 38, 0x88 }, { 39, 0x08 },
 };
 
 static int ak4642_dai_startup(struct snd_pcm_substream *substream,
@@ -454,7 +455,10 @@ static struct snd_soc_dai_driver ak4642_dai = {
 
 static int ak4642_resume(struct snd_soc_codec *codec)
 {
-       snd_soc_cache_sync(codec);
+       struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
+
+       regcache_mark_dirty(regmap);
+       regcache_sync(regmap);
        return 0;
 }
 
@@ -463,15 +467,12 @@ static int ak4642_probe(struct snd_soc_codec *codec)
 {
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       snd_soc_add_codec_controls(codec, ak4642_snd_controls,
-                            ARRAY_SIZE(ak4642_snd_controls));
-
        ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -488,55 +489,59 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
        .remove                 = ak4642_remove,
        .resume                 = ak4642_resume,
        .set_bias_level         = ak4642_set_bias_level,
-       .reg_cache_default      = ak4642_reg,                   /* ak4642 reg */
-       .reg_cache_size         = ARRAY_SIZE(ak4642_reg),       /* ak4642 reg */
-       .reg_word_size          = sizeof(u8),
+       .controls               = ak4642_snd_controls,
+       .num_controls           = ARRAY_SIZE(ak4642_snd_controls),
        .dapm_widgets           = ak4642_dapm_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(ak4642_dapm_widgets),
        .dapm_routes            = ak4642_intercon,
        .num_dapm_routes        = ARRAY_SIZE(ak4642_intercon),
 };
 
-static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
-       .probe                  = ak4642_probe,
-       .remove                 = ak4642_remove,
-       .resume                 = ak4642_resume,
-       .set_bias_level         = ak4642_set_bias_level,
-       .reg_cache_default      = ak4648_reg,                   /* ak4648 reg */
-       .reg_cache_size         = ARRAY_SIZE(ak4648_reg),       /* ak4648 reg */
-       .reg_word_size          = sizeof(u8),
-       .dapm_widgets           = ak4642_dapm_widgets,
-       .num_dapm_widgets       = ARRAY_SIZE(ak4642_dapm_widgets),
-       .dapm_routes            = ak4642_intercon,
-       .num_dapm_routes        = ARRAY_SIZE(ak4642_intercon),
+static const struct regmap_config ak4642_regmap = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = ARRAY_SIZE(ak4642_reg) + 1,
+       .reg_defaults           = ak4642_reg,
+       .num_reg_defaults       = ARRAY_SIZE(ak4642_reg),
+};
+
+static const struct regmap_config ak4648_regmap = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = ARRAY_SIZE(ak4648_reg) + 1,
+       .reg_defaults           = ak4648_reg,
+       .num_reg_defaults       = ARRAY_SIZE(ak4648_reg),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static struct of_device_id ak4642_of_match[];
 static int ak4642_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct device_node *np = i2c->dev.of_node;
-       const struct snd_soc_codec_driver *driver;
+       const struct regmap_config *regmap_config = NULL;
+       struct regmap *regmap;
 
-       driver = NULL;
        if (np) {
                const struct of_device_id *of_id;
 
                of_id = of_match_device(ak4642_of_match, &i2c->dev);
                if (of_id)
-                       driver = of_id->data;
+                       regmap_config = of_id->data;
        } else {
-               driver = (struct snd_soc_codec_driver *)id->driver_data;
+               regmap_config = (const struct regmap_config *)id->driver_data;
        }
 
-       if (!driver) {
-               dev_err(&i2c->dev, "no driver\n");
+       if (!regmap_config) {
+               dev_err(&i2c->dev, "Unknown device type\n");
                return -EINVAL;
        }
 
+       regmap = devm_regmap_init_i2c(i2c, regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        return snd_soc_register_codec(&i2c->dev,
-                                     driver, &ak4642_dai, 1);
+                                     &soc_codec_dev_ak4642, &ak4642_dai, 1);
 }
 
 static int ak4642_i2c_remove(struct i2c_client *client)
@@ -546,17 +551,17 @@ static int ak4642_i2c_remove(struct i2c_client *client)
 }
 
 static struct of_device_id ak4642_of_match[] = {
-       { .compatible = "asahi-kasei,ak4642",   .data = &soc_codec_dev_ak4642},
-       { .compatible = "asahi-kasei,ak4643",   .data = &soc_codec_dev_ak4642},
-       { .compatible = "asahi-kasei,ak4648",   .data = &soc_codec_dev_ak4648},
+       { .compatible = "asahi-kasei,ak4642",   .data = &ak4642_regmap},
+       { .compatible = "asahi-kasei,ak4643",   .data = &ak4642_regmap},
+       { .compatible = "asahi-kasei,ak4648",   .data = &ak4648_regmap},
        {},
 };
 MODULE_DEVICE_TABLE(of, ak4642_of_match);
 
 static const struct i2c_device_id ak4642_i2c_id[] = {
-       { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 },
-       { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 },
-       { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 },
+       { "ak4642", (kernel_ulong_t)&ak4642_regmap },
+       { "ak4643", (kernel_ulong_t)&ak4642_regmap },
+       { "ak4648", (kernel_ulong_t)&ak4648_regmap },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
@@ -571,27 +576,8 @@ static struct i2c_driver ak4642_i2c_driver = {
        .remove         = ak4642_i2c_remove,
        .id_table       = ak4642_i2c_id,
 };
-#endif
-
-static int __init ak4642_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&ak4642_i2c_driver);
-#endif
-       return ret;
 
-}
-module_init(ak4642_modinit);
-
-static void __exit ak4642_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&ak4642_i2c_driver);
-#endif
-
-}
-module_exit(ak4642_exit);
+module_i2c_driver(ak4642_i2c_driver);
 
 MODULE_DESCRIPTION("Soc AK4642 driver");
 MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
index 256c364193a54ea6864adbf79640b3480983285a..d3036283482a10814453671ac33f991e46a54b89 100644 (file)
@@ -714,17 +714,17 @@ static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream,
        iface &= ~ALC5623_DAI_I2S_DL_MASK;
 
        /* bit size */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                iface |= ALC5623_DAI_I2S_DL_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                iface |= ALC5623_DAI_I2S_DL_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                iface |= ALC5623_DAI_I2S_DL_24;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                iface |= ALC5623_DAI_I2S_DL_32;
                break;
        default:
index 19e9f222d09c0934cb184843b40ff0ad52b4a1ec..fb001c56cf8d63525d3350f54c96e117454d06bd 100644 (file)
@@ -869,14 +869,14 @@ static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream,
        iface &= ~ALC5632_DAI_I2S_DL_MASK;
 
        /* bit size */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                iface |= ALC5632_DAI_I2S_DL_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                iface |= ALC5632_DAI_I2S_DL_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                iface |= ALC5632_DAI_I2S_DL_24;
                break;
        default:
index fea991031be18a05eab28e4922b10a2e472b5ea9..e4295fee8f13673f15f9811a9516ba84bb548584 100644 (file)
@@ -93,7 +93,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
                if (!priv->spk_ena && manual_ena) {
-                       snd_soc_write(codec, 0x4f5, 0x25a);
+                       regmap_write_async(arizona->regmap, 0x4f5, 0x25a);
                        priv->spk_ena_pending = true;
                }
                break;
@@ -105,12 +105,13 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
                        return -EBUSY;
                }
 
-               snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
-                                   1 << w->shift, 1 << w->shift);
+               regmap_update_bits_async(arizona->regmap,
+                                        ARIZONA_OUTPUT_ENABLES_1,
+                                        1 << w->shift, 1 << w->shift);
 
                if (priv->spk_ena_pending) {
                        msleep(75);
-                       snd_soc_write(codec, 0x4f5, 0xda);
+                       regmap_write_async(arizona->regmap, 0x4f5, 0xda);
                        priv->spk_ena_pending = false;
                        priv->spk_ena++;
                }
@@ -119,16 +120,19 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
                if (manual_ena) {
                        priv->spk_ena--;
                        if (!priv->spk_ena)
-                               snd_soc_write(codec, 0x4f5, 0x25a);
+                               regmap_write_async(arizona->regmap,
+                                                  0x4f5, 0x25a);
                }
 
-               snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
-                                   1 << w->shift, 0);
+               regmap_update_bits_async(arizona->regmap,
+                                        ARIZONA_OUTPUT_ENABLES_1,
+                                        1 << w->shift, 0);
                break;
        case SND_SOC_DAPM_POST_PMD:
                if (manual_ena) {
                        if (!priv->spk_ena)
-                               snd_soc_write(codec, 0x4f5, 0x0da);
+                               regmap_write_async(arizona->regmap,
+                                                  0x4f5, 0x0da);
                }
                break;
        }
@@ -292,6 +296,10 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
        "AIF1RX8",
        "AIF2RX1",
        "AIF2RX2",
+       "AIF2RX3",
+       "AIF2RX4",
+       "AIF2RX5",
+       "AIF2RX6",
        "AIF3RX1",
        "AIF3RX2",
        "SLIMRX1",
@@ -395,6 +403,10 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
        0x27,
        0x28,  /* AIF2RX1 */
        0x29,
+       0x2a,
+       0x2b,
+       0x2c,
+       0x2d,
        0x30,  /* AIF3RX1 */
        0x31,
        0x38,  /* SLIMRX1 */
@@ -486,6 +498,22 @@ const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
 EXPORT_SYMBOL_GPL(arizona_rate_val);
 
 
+const struct soc_enum arizona_isrc_fsh[] = {
+       SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_1,
+                             ARIZONA_ISRC1_FSH_SHIFT, 0xf,
+                             ARIZONA_RATE_ENUM_SIZE,
+                             arizona_rate_text, arizona_rate_val),
+       SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_1,
+                             ARIZONA_ISRC2_FSH_SHIFT, 0xf,
+                             ARIZONA_RATE_ENUM_SIZE,
+                             arizona_rate_text, arizona_rate_val),
+       SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_1,
+                             ARIZONA_ISRC3_FSH_SHIFT, 0xf,
+                             ARIZONA_RATE_ENUM_SIZE,
+                             arizona_rate_text, arizona_rate_val),
+};
+EXPORT_SYMBOL_GPL(arizona_isrc_fsh);
+
 const struct soc_enum arizona_isrc_fsl[] = {
        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
                              ARIZONA_ISRC1_FSL_SHIFT, 0xf,
@@ -502,6 +530,13 @@ const struct soc_enum arizona_isrc_fsl[] = {
 };
 EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
 
+const struct soc_enum arizona_asrc_rate1 =
+       SOC_VALUE_ENUM_SINGLE(ARIZONA_ASRC_RATE1,
+                             ARIZONA_ASRC_RATE1_SHIFT, 0xf,
+                             ARIZONA_RATE_ENUM_SIZE - 1,
+                             arizona_rate_text, arizona_rate_val);
+EXPORT_SYMBOL_GPL(arizona_asrc_rate1);
+
 static const char *arizona_vol_ramp_text[] = {
        "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
        "15ms/6dB", "30ms/6dB",
@@ -560,6 +595,16 @@ const struct soc_enum arizona_ng_hold =
                        4, arizona_ng_hold_text);
 EXPORT_SYMBOL_GPL(arizona_ng_hold);
 
+static const char * const arizona_in_hpf_cut_text[] = {
+       "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
+};
+
+const struct soc_enum arizona_in_hpf_cut_enum =
+       SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT,
+                       ARRAY_SIZE(arizona_in_hpf_cut_text),
+                       arizona_in_hpf_cut_text);
+EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
+
 static const char * const arizona_in_dmic_osr_text[] = {
        "1.536MHz", "3.072MHz", "6.144MHz",
 };
@@ -669,6 +714,7 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
                   int event)
 {
        struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
+       struct arizona *arizona = priv->arizona;
        unsigned int mask = 1 << w->shift;
        unsigned int val;
 
@@ -691,7 +737,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
        if (priv->arizona->hpdet_magic)
                val = 0;
 
-       snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val);
+       regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
+                                mask, val);
 
        return arizona_out_ev(w, kcontrol, event);
 }
@@ -846,6 +893,8 @@ EXPORT_SYMBOL_GPL(arizona_set_sysclk);
 static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = dai->codec;
+       struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+       struct arizona *arizona = priv->arizona;
        int lrclk, bclk, mode, base;
 
        base = dai->driver->base;
@@ -902,17 +951,19 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
-                           ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
-                           bclk);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
-                           ARIZONA_AIF1TX_LRCLK_INV |
-                           ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
-                           ARIZONA_AIF1RX_LRCLK_INV |
-                           ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
-                           ARIZONA_AIF1_FMT_MASK, mode);
+       regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
+                                ARIZONA_AIF1_BCLK_INV |
+                                ARIZONA_AIF1_BCLK_MSTR,
+                                bclk);
+       regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
+                                ARIZONA_AIF1TX_LRCLK_INV |
+                                ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
+       regmap_update_bits_async(arizona->regmap,
+                                base + ARIZONA_AIF_RX_PIN_CTRL,
+                                ARIZONA_AIF1RX_LRCLK_INV |
+                                ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
+       regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
+                          ARIZONA_AIF1_FMT_MASK, mode);
 
        return 0;
 }
@@ -1164,18 +1215,22 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
        if (ret != 0)
                return ret;
 
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
-                           ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
-                           ARIZONA_AIF1TX_BCPF_MASK, lrclk);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
-                           ARIZONA_AIF1RX_BCPF_MASK, lrclk);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
-                           ARIZONA_AIF1TX_WL_MASK |
-                           ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
-       snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
-                           ARIZONA_AIF1RX_WL_MASK |
-                           ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+       regmap_update_bits_async(arizona->regmap,
+                                base + ARIZONA_AIF_BCLK_CTRL,
+                                ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
+       regmap_update_bits_async(arizona->regmap,
+                                base + ARIZONA_AIF_TX_BCLK_RATE,
+                                ARIZONA_AIF1TX_BCPF_MASK, lrclk);
+       regmap_update_bits_async(arizona->regmap,
+                                base + ARIZONA_AIF_RX_BCLK_RATE,
+                                ARIZONA_AIF1RX_BCPF_MASK, lrclk);
+       regmap_update_bits_async(arizona->regmap,
+                                base + ARIZONA_AIF_FRAME_CTRL_1,
+                                ARIZONA_AIF1TX_WL_MASK |
+                                ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
+       regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
+                          ARIZONA_AIF1RX_WL_MASK |
+                          ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
 
        return 0;
 }
@@ -1428,31 +1483,31 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
                              struct arizona_fll_cfg *cfg, int source,
                              bool sync)
 {
-       regmap_update_bits(arizona->regmap, base + 3,
-                          ARIZONA_FLL1_THETA_MASK, cfg->theta);
-       regmap_update_bits(arizona->regmap, base + 4,
-                          ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
-       regmap_update_bits(arizona->regmap, base + 5,
-                          ARIZONA_FLL1_FRATIO_MASK,
-                          cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
-       regmap_update_bits(arizona->regmap, base + 6,
-                          ARIZONA_FLL1_CLK_REF_DIV_MASK |
-                          ARIZONA_FLL1_CLK_REF_SRC_MASK,
-                          cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
-                          source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
+       regmap_update_bits_async(arizona->regmap, base + 3,
+                                ARIZONA_FLL1_THETA_MASK, cfg->theta);
+       regmap_update_bits_async(arizona->regmap, base + 4,
+                                ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
+       regmap_update_bits_async(arizona->regmap, base + 5,
+                                ARIZONA_FLL1_FRATIO_MASK,
+                                cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
+       regmap_update_bits_async(arizona->regmap, base + 6,
+                                ARIZONA_FLL1_CLK_REF_DIV_MASK |
+                                ARIZONA_FLL1_CLK_REF_SRC_MASK,
+                                cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
+                                source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
 
        if (sync)
-               regmap_update_bits(arizona->regmap, base + 0x7,
-                                  ARIZONA_FLL1_GAIN_MASK,
-                                  cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+               regmap_update_bits_async(arizona->regmap, base + 0x7,
+                                        ARIZONA_FLL1_GAIN_MASK,
+                                        cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
        else
-               regmap_update_bits(arizona->regmap, base + 0x9,
-                                  ARIZONA_FLL1_GAIN_MASK,
-                                  cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
+               regmap_update_bits_async(arizona->regmap, base + 0x9,
+                                        ARIZONA_FLL1_GAIN_MASK,
+                                        cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
 
-       regmap_update_bits(arizona->regmap, base + 2,
-                          ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
-                          ARIZONA_FLL1_CTRL_UPD | cfg->n);
+       regmap_update_bits_async(arizona->regmap, base + 2,
+                                ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
+                                ARIZONA_FLL1_CTRL_UPD | cfg->n);
 }
 
 static bool arizona_is_enabled_fll(struct arizona_fll *fll)
@@ -1485,9 +1540,9 @@ static void arizona_enable_fll(struct arizona_fll *fll,
         */
        if (fll->ref_src >= 0 && fll->ref_freq &&
            fll->ref_src != fll->sync_src) {
-               regmap_update_bits(arizona->regmap, fll->base + 5,
-                                  ARIZONA_FLL1_OUTDIV_MASK,
-                                  ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+               regmap_update_bits_async(arizona->regmap, fll->base + 5,
+                                        ARIZONA_FLL1_OUTDIV_MASK,
+                                        ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
 
                arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
                                  false);
@@ -1497,15 +1552,15 @@ static void arizona_enable_fll(struct arizona_fll *fll,
                        use_sync = true;
                }
        } else if (fll->sync_src >= 0) {
-               regmap_update_bits(arizona->regmap, fll->base + 5,
-                                  ARIZONA_FLL1_OUTDIV_MASK,
-                                  sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
+               regmap_update_bits_async(arizona->regmap, fll->base + 5,
+                                        ARIZONA_FLL1_OUTDIV_MASK,
+                                        sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
 
                arizona_apply_fll(arizona, fll->base, sync,
                                  fll->sync_src, false);
 
-               regmap_update_bits(arizona->regmap, fll->base + 0x11,
-                                  ARIZONA_FLL1_SYNC_ENA, 0);
+               regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
+                                        ARIZONA_FLL1_SYNC_ENA, 0);
        } else {
                arizona_fll_err(fll, "No clocks provided\n");
                return;
@@ -1516,11 +1571,12 @@ static void arizona_enable_fll(struct arizona_fll *fll,
         * sync source.
         */
        if (use_sync && fll->sync_freq > 100000)
-               regmap_update_bits(arizona->regmap, fll->base + 0x17,
-                                  ARIZONA_FLL1_SYNC_BW, 0);
+               regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
+                                        ARIZONA_FLL1_SYNC_BW, 0);
        else
-               regmap_update_bits(arizona->regmap, fll->base + 0x17,
-                                  ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
+               regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
+                                        ARIZONA_FLL1_SYNC_BW,
+                                        ARIZONA_FLL1_SYNC_BW);
 
        if (!arizona_is_enabled_fll(fll))
                pm_runtime_get(arizona->dev);
@@ -1528,14 +1584,14 @@ static void arizona_enable_fll(struct arizona_fll *fll,
        /* Clear any pending completions */
        try_wait_for_completion(&fll->ok);
 
-       regmap_update_bits(arizona->regmap, fll->base + 1,
-                          ARIZONA_FLL1_FREERUN, 0);
-       regmap_update_bits(arizona->regmap, fll->base + 1,
-                          ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
+       regmap_update_bits_async(arizona->regmap, fll->base + 1,
+                                ARIZONA_FLL1_FREERUN, 0);
+       regmap_update_bits_async(arizona->regmap, fll->base + 1,
+                                ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
        if (use_sync)
-               regmap_update_bits(arizona->regmap, fll->base + 0x11,
-                                  ARIZONA_FLL1_SYNC_ENA,
-                                  ARIZONA_FLL1_SYNC_ENA);
+               regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
+                                        ARIZONA_FLL1_SYNC_ENA,
+                                        ARIZONA_FLL1_SYNC_ENA);
 
        ret = wait_for_completion_timeout(&fll->ok,
                                          msecs_to_jiffies(250));
@@ -1548,8 +1604,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
        struct arizona *arizona = fll->arizona;
        bool change;
 
-       regmap_update_bits(arizona->regmap, fll->base + 1,
-                          ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
+       regmap_update_bits_async(arizona->regmap, fll->base + 1,
+                                ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
        regmap_update_bits_check(arizona->regmap, fll->base + 1,
                                 ARIZONA_FLL1_ENA, 0, &change);
        regmap_update_bits(arizona->regmap, fll->base + 0x11,
index 9e81b6392692cbd78e7e9ad7b263fcd00c214a1d..16df0f9133537569c2a84f677e4fcb23d7af1b4e 100644 (file)
@@ -81,7 +81,7 @@ struct arizona_priv {
        unsigned int spk_ena_pending:1;
 };
 
-#define ARIZONA_NUM_MIXER_INPUTS 99
+#define ARIZONA_NUM_MIXER_INPUTS 103
 
 extern const unsigned int arizona_mixer_tlv[];
 extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
@@ -166,26 +166,29 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
 
 #define ARIZONA_DSP_ROUTES(name) \
-       { name, NULL, name " Aux 1" }, \
-       { name, NULL, name " Aux 2" }, \
-       { name, NULL, name " Aux 3" }, \
-       { name, NULL, name " Aux 4" }, \
-       { name, NULL, name " Aux 5" }, \
-       { name, NULL, name " Aux 6" }, \
+       { name, NULL, name " Preloader"}, \
+       { name " Preloader", NULL, name " Aux 1" }, \
+       { name " Preloader", NULL, name " Aux 2" }, \
+       { name " Preloader", NULL, name " Aux 3" }, \
+       { name " Preloader", NULL, name " Aux 4" }, \
+       { name " Preloader", NULL, name " Aux 5" }, \
+       { name " Preloader", NULL, name " Aux 6" }, \
        ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
-       ARIZONA_MIXER_ROUTES(name, name "L"), \
-       ARIZONA_MIXER_ROUTES(name, name "R")
+       ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \
+       ARIZONA_MIXER_ROUTES(name " Preloader", name "R")
 
 #define ARIZONA_RATE_ENUM_SIZE 4
 extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
 extern const int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE];
 
 extern const struct soc_enum arizona_isrc_fsl[];
+extern const struct soc_enum arizona_isrc_fsh[];
+extern const struct soc_enum arizona_asrc_rate1;
 
 extern const struct soc_enum arizona_in_vi_ramp;
 extern const struct soc_enum arizona_in_vd_ramp;
@@ -199,6 +202,7 @@ extern const struct soc_enum arizona_lhpf3_mode;
 extern const struct soc_enum arizona_lhpf4_mode;
 
 extern const struct soc_enum arizona_ng_hold;
+extern const struct soc_enum arizona_in_hpf_cut_enum;
 extern const struct soc_enum arizona_in_dmic_osr[];
 
 extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
index f6e953454bc0856ffccb87ec6680a670d3e90cbd..ce05fd93dc748c3cc8e1405b1d50296f5e9780e3 100644 (file)
@@ -675,7 +675,7 @@ static struct spi_driver cs4271_spi_driver = {
 };
 #endif /* defined(CONFIG_SPI_MASTER) */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static const struct i2c_device_id cs4271_i2c_id[] = {
        {"cs4271", 0},
        {}
@@ -728,7 +728,7 @@ static struct i2c_driver cs4271_i2c_driver = {
        .probe          = cs4271_i2c_probe,
        .remove         = cs4271_i2c_remove,
 };
-#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
+#endif /* IS_ENABLED(CONFIG_I2C) */
 
 /*
  * We only register our serial bus driver here without
@@ -741,7 +741,7 @@ static int __init cs4271_modinit(void)
 {
        int ret;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&cs4271_i2c_driver);
        if (ret) {
                pr_err("Failed to register CS4271 I2C driver: %d\n", ret);
@@ -767,7 +767,7 @@ static void __exit cs4271_modexit(void)
        spi_unregister_driver(&cs4271_spi_driver);
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&cs4271_i2c_driver);
 #endif
 }
index 1e0fa3b5f79a5e5659ec76acf5c4a70457fad328..6e9ea8379a91272de475985429a21643fbabec22 100644 (file)
@@ -423,21 +423,17 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
                intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24);
                break;
        case SND_SOC_DAIFMT_RIGHT_J:
-               switch (params_format(params)) {
-               case SNDRV_PCM_FORMAT_S16_LE:
-               case SNDRV_PCM_FORMAT_S16_BE:
+               switch (params_width(params)) {
+               case 16:
                        fmt = CS42L51_DAC_DIF_RJ16;
                        break;
-               case SNDRV_PCM_FORMAT_S18_3LE:
-               case SNDRV_PCM_FORMAT_S18_3BE:
+               case 18:
                        fmt = CS42L51_DAC_DIF_RJ18;
                        break;
-               case SNDRV_PCM_FORMAT_S20_3LE:
-               case SNDRV_PCM_FORMAT_S20_3BE:
+               case 20:
                        fmt = CS42L51_DAC_DIF_RJ20;
                        break;
-               case SNDRV_PCM_FORMAT_S24_LE:
-               case SNDRV_PCM_FORMAT_S24_BE:
+               case 24:
                        fmt = CS42L51_DAC_DIF_RJ24;
                        break;
                default:
index 8b427c97708365e5e1e40aad701f740b62c365be..0bac6d5a4ac8fac7c00e3a909f044a499f11761b 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
@@ -50,7 +50,7 @@ struct  cs42l52_private {
        u8 mclksel;
        u32 mclk;
        u8 flags;
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
        struct input_dev *beep;
        struct work_struct beep_work;
        int beep_rate;
@@ -233,7 +233,7 @@ static const struct soc_enum mic_bias_level_enum =
        SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0,
                        ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text);
 
-static const char * const cs42l52_mic_text[] = { "Single", "Differential" };
+static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" };
 
 static const struct soc_enum mica_enum =
        SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5,
@@ -243,12 +243,6 @@ static const struct soc_enum micb_enum =
        SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5,
                        ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
 
-static const struct snd_kcontrol_new mica_mux =
-       SOC_DAPM_ENUM("Left Mic Input Capture Mux", mica_enum);
-
-static const struct snd_kcontrol_new micb_mux =
-       SOC_DAPM_ENUM("Right Mic Input Capture Mux", micb_enum);
-
 static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
 
 static const struct soc_enum digital_output_mux_enum =
@@ -531,6 +525,30 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 
 };
 
+static const struct snd_kcontrol_new cs42l52_mica_controls[] = {
+       SOC_ENUM("MICA Select", mica_enum),
+};
+
+static const struct snd_kcontrol_new cs42l52_micb_controls[] = {
+       SOC_ENUM("MICB Select", micb_enum),
+};
+
+static int cs42l52_add_mic_controls(struct snd_soc_codec *codec)
+{
+       struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+       struct cs42l52_platform_data *pdata = &cs42l52->pdata;
+
+       if (!pdata->mica_diff_cfg)
+               snd_soc_add_codec_controls(codec, cs42l52_mica_controls,
+                                    ARRAY_SIZE(cs42l52_mica_controls));
+
+       if (!pdata->micb_diff_cfg)
+               snd_soc_add_codec_controls(codec, cs42l52_micb_controls,
+                                    ARRAY_SIZE(cs42l52_micb_controls));
+
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
 
        SND_SOC_DAPM_INPUT("AIN1L"),
@@ -550,9 +568,6 @@ static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
        SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL,  0,
                        SND_SOC_NOPM, 0, 0),
 
-       SND_SOC_DAPM_MUX("MICA Mux", SND_SOC_NOPM, 0, 0, &mica_mux),
-       SND_SOC_DAPM_MUX("MICB Mux", SND_SOC_NOPM, 0, 0, &micb_mux),
-
        SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1),
        SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1),
        SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0),
@@ -953,7 +968,7 @@ static int cs42l52_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
 static int beep_rates[] = {
        261, 522, 585, 667, 706, 774, 889, 1000,
        1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
@@ -1110,6 +1125,8 @@ static int cs42l52_probe(struct snd_soc_codec *codec)
        }
        regcache_cache_only(cs42l52->regmap, true);
 
+       cs42l52_add_mic_controls(codec);
+
        cs42l52_init_beep(codec);
 
        cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1176,6 +1193,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
        int ret;
        unsigned int devid = 0;
        unsigned int reg;
+       u32 val32;
 
        cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private),
                               GFP_KERNEL);
@@ -1189,9 +1207,39 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
                dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
                return ret;
        }
-
-       if (pdata)
+       if (pdata) {
+               cs42l52->pdata = *pdata;
+       } else {
+               pdata = devm_kzalloc(&i2c_client->dev,
+                                    sizeof(struct cs42l52_platform_data),
+                               GFP_KERNEL);
+               if (!pdata) {
+                       dev_err(&i2c_client->dev, "could not allocate pdata\n");
+                       return -ENOMEM;
+               }
+               if (i2c_client->dev.of_node) {
+                       if (of_property_read_bool(i2c_client->dev.of_node,
+                               "cirrus,mica-differential-cfg"))
+                               pdata->mica_diff_cfg = true;
+
+                       if (of_property_read_bool(i2c_client->dev.of_node,
+                               "cirrus,micb-differential-cfg"))
+                               pdata->micb_diff_cfg = true;
+
+                       if (of_property_read_u32(i2c_client->dev.of_node,
+                               "cirrus,micbias-lvl", &val32) >= 0)
+                               pdata->micbias_lvl = val32;
+
+                       if (of_property_read_u32(i2c_client->dev.of_node,
+                               "cirrus,chgfreq-divisor", &val32) >= 0)
+                               pdata->chgfreq = val32;
+
+                       pdata->reset_gpio =
+                               of_get_named_gpio(i2c_client->dev.of_node,
+                                               "cirrus,reset-gpio", 0);
+               }
                cs42l52->pdata = *pdata;
+       }
 
        if (cs42l52->pdata.reset_gpio) {
                ret = gpio_request_one(cs42l52->pdata.reset_gpio,
@@ -1227,29 +1275,18 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
                        reg & 0xFF);
 
        /* Set Platform Data */
-       if (cs42l52->pdata.mica_cfg)
+       if (cs42l52->pdata.mica_diff_cfg)
                regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
                                   CS42L52_MIC_CTL_TYPE_MASK,
-                               cs42l52->pdata.mica_cfg <<
+                               cs42l52->pdata.mica_diff_cfg <<
                                CS42L52_MIC_CTL_TYPE_SHIFT);
 
-       if (cs42l52->pdata.micb_cfg)
+       if (cs42l52->pdata.micb_diff_cfg)
                regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
                                   CS42L52_MIC_CTL_TYPE_MASK,
-                               cs42l52->pdata.micb_cfg <<
+                               cs42l52->pdata.micb_diff_cfg <<
                                CS42L52_MIC_CTL_TYPE_SHIFT);
 
-       if (cs42l52->pdata.mica_sel)
-               regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
-                                  CS42L52_MIC_CTL_MIC_SEL_MASK,
-                               cs42l52->pdata.mica_sel <<
-                               CS42L52_MIC_CTL_MIC_SEL_SHIFT);
-       if (cs42l52->pdata.micb_sel)
-               regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
-                                  CS42L52_MIC_CTL_MIC_SEL_MASK,
-                               cs42l52->pdata.micb_sel <<
-                               CS42L52_MIC_CTL_MIC_SEL_SHIFT);
-
        if (cs42l52->pdata.chgfreq)
                regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP,
                                   CS42L52_CHARGE_PUMP_MASK,
@@ -1274,6 +1311,13 @@ static int cs42l52_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct of_device_id cs42l52_of_match[] = {
+       { .compatible = "cirrus,cs42l52", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, cs42l52_of_match);
+
+
 static const struct i2c_device_id cs42l52_id[] = {
        { "cs42l52", 0 },
        { }
@@ -1284,6 +1328,7 @@ static struct i2c_driver cs42l52_i2c_driver = {
        .driver = {
                .name = "cs42l52",
                .owner = THIS_MODULE,
+               .of_match_table = cs42l52_of_match,
        },
        .id_table = cs42l52_id,
        .probe =    cs42l52_i2c_probe,
index 9c12314565024fcb80d5091a6fc57a6dddf0555b..e62e294a8033a02ed4e7a90c6c9b41317df79d18 100644 (file)
@@ -778,17 +778,17 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
 
        dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                dai_cfg1 |= DA7210_DAI_WORD_S16_LE;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                dai_cfg1 |= DA7210_DAI_WORD_S20_3LE;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                dai_cfg1 |= DA7210_DAI_WORD_S24_LE;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                dai_cfg1 |= DA7210_DAI_WORD_S32_LE;
                break;
        default:
@@ -1188,7 +1188,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
        .num_dapm_routes        = ARRAY_SIZE(da7210_audio_map),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 
 static struct reg_default da7210_regmap_i2c_patch[] = {
 
@@ -1362,7 +1362,7 @@ static struct spi_driver da7210_spi_driver = {
 static int __init da7210_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&da7210_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
@@ -1378,7 +1378,7 @@ module_init(da7210_modinit);
 
 static void __exit da7210_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&da7210_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 4a6f1daf911fc0685f16ea5f54fe774bc58581ac..0c77e7ad7423fcf9f7929bfe03d19e4d4427cff1 100644 (file)
@@ -1067,17 +1067,17 @@ static int da7213_hw_params(struct snd_pcm_substream *substream,
        u8 fs;
 
        /* Set DAI format */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                dai_ctrl |= DA7213_DAI_WORD_LENGTH_S16_LE;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                dai_ctrl |= DA7213_DAI_WORD_LENGTH_S20_LE;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                dai_ctrl |= DA7213_DAI_WORD_LENGTH_S24_LE;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                dai_ctrl |= DA7213_DAI_WORD_LENGTH_S32_LE;
                break;
        default:
index dc0284dc9e6f85dde0fa61819b5e86145f55d608..f295b65699105897743fad1ecbc4439a71e58f0e 100644 (file)
@@ -973,17 +973,17 @@ static int da732x_hw_params(struct snd_pcm_substream *substream,
 
        reg_aif = dai->driver->base;
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                aif |= DA732X_AIF_WORD_16;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                aif |= DA732X_AIF_WORD_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                aif |= DA732X_AIF_WORD_24;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                aif |= DA732X_AIF_WORD_32;
                break;
        default:
index fc9802d1281dcad0d8ba57ea9d62a02322b5864a..52b79a487ac7db318dd252fe30befd6a3c56b2ec 100644 (file)
@@ -1058,17 +1058,17 @@ static int da9055_hw_params(struct snd_pcm_substream *substream,
        u8 aif_ctrl, fs;
        u32 sysclk;
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                aif_ctrl = DA9055_AIF_WORD_S16_LE;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                aif_ctrl = DA9055_AIF_WORD_S20_3LE;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                aif_ctrl = DA9055_AIF_WORD_S24_LE;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                aif_ctrl = DA9055_AIF_WORD_S32_LE;
                break;
        default:
index 68342b121c966aa7c90ace1384bbfbefe4737ab7..9cb1c7d3e1dca6dafbeaf1247c2bccf073212061 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/module.h>
 #include <sound/soc.h>
+#include <linux/of_device.h>
 
 #define DRV_NAME "hdmi-audio-codec"
 
@@ -44,7 +45,7 @@ static struct snd_soc_dai_driver hdmi_codec_dai = {
                        SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
                        SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
                .formats = SNDRV_PCM_FMTBIT_S16_LE |
-                       SNDRV_PCM_FMTBIT_S24_LE,
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
        },
        .capture = {
                .stream_name = "Capture",
@@ -60,6 +61,14 @@ static struct snd_soc_dai_driver hdmi_codec_dai = {
 
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id hdmi_audio_codec_ids[] = {
+       { .compatible = "linux,hdmi-audio", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, hdmi_audio_codec_ids);
+#endif
+
 static struct snd_soc_codec_driver hdmi_codec = {
        .dapm_widgets = hdmi_widgets,
        .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
@@ -83,6 +92,7 @@ static struct platform_driver hdmi_codec_driver = {
        .driver         = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(hdmi_audio_codec_ids),
        },
 
        .probe          = hdmi_codec_probe,
index 53b455b8c07a76dfabd63e46d2ca934a418061bb..5839048ec4674e5d20cc5f06e206c2210977999e 100644 (file)
@@ -951,11 +951,11 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream,
                        ISABELLE_FS_RATE_MASK, fs_val);
 
        /* bit size */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       switch (params_width(params)) {
+       case 20:
                aif |= ISABELLE_AIF_LENGTH_20;
                break;
-       case SNDRV_PCM_FORMAT_S32_LE:
+       case 32:
                aif |= ISABELLE_AIF_LENGTH_32;
                break;
        default:
index 53d7dab4e054ccd93a25986561fc2016da934316..ee660e2d3df3ba0ced0587ee13bab59fc86de6f9 100644 (file)
@@ -1233,12 +1233,12 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream,
 
        rate = params_rate(params);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
                        M98088_DAI_WS, 0);
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
                        M98088_DAI_WS, M98088_DAI_WS);
                break;
index 0569a4c3ae00e7ce8b8fb27952387d87913f4098..51f9b3d16b41dbf4cc80dddc6d0a081ccb83fe90 100644 (file)
@@ -1840,8 +1840,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
 
        max98090->lrclk = params_rate(params);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                snd_soc_update_bits(codec, M98090_REG_INTERFACE_FORMAT,
                        M98090_WS_MASK, 0);
                break;
index 67244315c721994f68ecd5f6df59720a8f03843f..3ba1170ebb53dcdb05d56e043121d83f3a20cbfe 100644 (file)
@@ -1213,12 +1213,12 @@ static int max98095_dai1_hw_params(struct snd_pcm_substream *substream,
 
        rate = params_rate(params);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT,
                        M98095_DAI_WS, 0);
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT,
                        M98095_DAI_WS, M98095_DAI_WS);
                break;
index c5dd61785f8d6318097ae3d0878f881d93e78c29..82757ebf0301df25ab7d2a15da0d6af5cc5623ce 100644 (file)
@@ -149,14 +149,14 @@ static int max9850_hw_params(struct snd_pcm_substream *substream,
        snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f);
        snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff);
 
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                da = 0;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                da = 0x2;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                da = 0x3;
                break;
        default:
index bae60164c7b7355408ab77676daa680bcb5946b0..582c2bbd42cb9eae83346b5fbcd4e497d6101493 100644 (file)
@@ -750,30 +750,26 @@ static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
        .num_dapm_routes = ARRAY_SIZE(mc13783_routes),
 };
 
-static int mc13783_codec_probe(struct platform_device *pdev)
+static int __init mc13783_codec_probe(struct platform_device *pdev)
 {
-       struct mc13xxx *mc13xxx;
        struct mc13783_priv *priv;
        struct mc13xxx_codec_platform_data *pdata = pdev->dev.platform_data;
        int ret;
 
-       mc13xxx = dev_get_drvdata(pdev->dev.parent);
-
-
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (priv == NULL)
+       if (!priv)
                return -ENOMEM;
 
-       dev_set_drvdata(&pdev->dev, priv);
-       priv->mc13xxx = mc13xxx;
        if (pdata) {
                priv->adc_ssi_port = pdata->adc_ssi_port;
                priv->dac_ssi_port = pdata->dac_ssi_port;
        } else {
-               priv->adc_ssi_port = MC13783_SSI1_PORT;
-               priv->dac_ssi_port = MC13783_SSI2_PORT;
+               return -ENOSYS;
        }
 
+       dev_set_drvdata(&pdev->dev, priv);
+       priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
+
        if (priv->adc_ssi_port == priv->dac_ssi_port)
                ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
                        mc13783_dai_sync, ARRAY_SIZE(mc13783_dai_sync));
@@ -781,14 +777,6 @@ static int mc13783_codec_probe(struct platform_device *pdev)
                ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_mc13783,
                        mc13783_dai_async, ARRAY_SIZE(mc13783_dai_async));
 
-       if (ret)
-               goto err_register_codec;
-
-       return 0;
-
-err_register_codec:
-       dev_err(&pdev->dev, "register codec failed with %d\n", ret);
-
        return ret;
 }
 
@@ -801,14 +789,12 @@ static int mc13783_codec_remove(struct platform_device *pdev)
 
 static struct platform_driver mc13783_codec_driver = {
        .driver = {
-                  .name = "mc13783-codec",
-                  .owner = THIS_MODULE,
-                  },
-       .probe = mc13783_codec_probe,
+               .name   = "mc13783-codec",
+               .owner  = THIS_MODULE,
+       },
        .remove = mc13783_codec_remove,
 };
-
-module_platform_driver(mc13783_codec_driver);
+module_platform_driver_probe(mc13783_codec_driver, mc13783_codec_probe);
 
 MODULE_DESCRIPTION("ASoC MC13783 driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
index 1f4093f3f3a19219318eb0f3c407d8f302ce34d3..0fcbe90f3ef24520dbbd74092829d892b287ca1c 100644 (file)
@@ -115,6 +115,7 @@ struct sgtl5000_priv {
        struct ldo_regulator *ldo;
        struct regmap *regmap;
        struct clk *mclk;
+       int revision;
 };
 
 /*
@@ -1285,41 +1286,45 @@ static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
 
        sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
-                       sgtl5000->supplies);
-
-       if (ret) {
-               ldo_regulator_remove(codec);
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               return ret;
-       }
-
        dev_info(codec->dev, "Using internal LDO instead of VDDD\n");
        return 0;
 }
 
 static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
 {
-       int reg;
        int ret;
-       int rev;
        int i;
        int external_vddd = 0;
        struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+       struct regulator *vddd;
 
        for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++)
                sgtl5000->supplies[i].supply = supply_names[i];
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
-                               sgtl5000->supplies);
-       if (!ret)
-               external_vddd = 1;
-       else {
+       /* External VDDD only works before revision 0x11 */
+       if (sgtl5000->revision < 0x11) {
+               vddd = regulator_get_optional(codec->dev, "VDDD");
+               if (IS_ERR(vddd)) {
+                       /* See if it's just not registered yet */
+                       if (PTR_ERR(vddd) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+               } else {
+                       external_vddd = 1;
+                       regulator_put(vddd);
+               }
+       }
+
+       if (!external_vddd) {
                ret = sgtl5000_replace_vddd_with_ldo(codec);
                if (ret)
                        return ret;
        }
 
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
+                                sgtl5000->supplies);
+       if (ret)
+               goto err_ldo_remove;
+
        ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
                                        sgtl5000->supplies);
        if (ret)
@@ -1328,47 +1333,13 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
        /* wait for all power rails bring up */
        udelay(10);
 
-       /*
-        * workaround for revision 0x11 and later,
-        * roll back to use internal LDO
-        */
-
-       ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg);
-       if (ret)
-               goto err_regulator_disable;
-
-       rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
-
-       if (external_vddd && rev >= 0x11) {
-               /* disable all regulator first */
-               regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
-                                       sgtl5000->supplies);
-               /* free VDDD regulator */
-               regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
-                                       sgtl5000->supplies);
-
-               ret = sgtl5000_replace_vddd_with_ldo(codec);
-               if (ret)
-                       return ret;
-
-               ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
-                                               sgtl5000->supplies);
-               if (ret)
-                       goto err_regulator_free;
-
-               /* wait for all power rails bring up */
-               udelay(10);
-       }
-
        return 0;
 
-err_regulator_disable:
-       regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
-                               sgtl5000->supplies);
 err_regulator_free:
        regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
                                sgtl5000->supplies);
-       if (external_vddd)
+err_ldo_remove:
+       if (!external_vddd)
                ldo_regulator_remove(codec);
        return ret;
 
@@ -1566,6 +1537,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
 
        rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
        dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev);
+       sgtl5000->revision = rev;
 
        i2c_set_clientdata(client, sgtl5000);
 
index 95aed552139a1a363bd54d8d88bc7a97486beb81..cc8debce752f73055a3253f5ac0928803fbc1091 100644 (file)
@@ -549,13 +549,13 @@ static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
                right_slot = 0;
        } else {
                /* We assume the left channel < right channel */
-               left_slot = ffs(tx_mask);
-               tx_mask &= ~(1 << tx_mask);
+               left_slot = __ffs(tx_mask);
+               tx_mask &= ~(1 << left_slot);
                if (tx_mask == 0) {
                        right_slot = left_slot;
                } else {
-                       right_slot = ffs(tx_mask);
-                       tx_mask &= ~(1 << tx_mask);
+                       right_slot = __ffs(tx_mask);
+                       tx_mask &= ~(1 << right_slot);
                }
        }
 
index 492644e67ace909d2f6b71c7685259955f76661d..af76bbd1b24fbde13e686618c9ab2409a8e18624 100644 (file)
@@ -53,8 +53,6 @@ enum ssm2602_type {
 struct ssm2602_priv {
        unsigned int sysclk;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
-       struct snd_pcm_substream *master_substream;
-       struct snd_pcm_substream *slave_substream;
 
        struct regmap *regmap;
 
@@ -196,7 +194,7 @@ static const struct snd_soc_dapm_route ssm2604_routes[] = {
 };
 
 static const unsigned int ssm2602_rates_12288000[] = {
-       8000, 32000, 48000, 96000,
+       8000, 16000, 32000, 48000, 96000,
 };
 
 static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
@@ -233,6 +231,11 @@ static const struct ssm2602_coeff ssm2602_coeff_table[] = {
        {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)},
        {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)},
 
+       /* 16k */
+       {12288000, 16000, SSM2602_COEFF_SRATE(0x5, 0x0, 0x0)},
+       {18432000, 16000, SSM2602_COEFF_SRATE(0x5, 0x1, 0x0)},
+       {12000000, 16000, SSM2602_COEFF_SRATE(0xa, 0x0, 0x1)},
+
        /* 8k */
        {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)},
        {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)},
@@ -277,11 +280,6 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
        int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params));
        unsigned int iface;
 
-       if (substream == ssm2602->slave_substream) {
-               dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
-               return 0;
-       }
-
        if (srate < 0)
                return srate;
 
@@ -314,33 +312,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
 {
        struct snd_soc_codec *codec = dai->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-       struct snd_pcm_runtime *master_runtime;
-
-       /* The DAI has shared clocks so if we already have a playback or
-        * capture going then constrain this substream to match it.
-        * TODO: the ssm2602 allows pairs of non-matching PB/REC rates
-        */
-       if (ssm2602->master_substream) {
-               master_runtime = ssm2602->master_substream->runtime;
-               dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n",
-                       master_runtime->sample_bits,
-                       master_runtime->rate);
-
-               if (master_runtime->rate != 0)
-                       snd_pcm_hw_constraint_minmax(substream->runtime,
-                                                    SNDRV_PCM_HW_PARAM_RATE,
-                                                    master_runtime->rate,
-                                                    master_runtime->rate);
-
-               if (master_runtime->sample_bits != 0)
-                       snd_pcm_hw_constraint_minmax(substream->runtime,
-                                                    SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-                                                    master_runtime->sample_bits,
-                                                    master_runtime->sample_bits);
-
-               ssm2602->slave_substream = substream;
-       } else
-               ssm2602->master_substream = substream;
 
        if (ssm2602->sysclk_constraints) {
                snd_pcm_hw_constraint_list(substream->runtime, 0,
@@ -351,19 +322,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static void ssm2602_shutdown(struct snd_pcm_substream *substream,
-                            struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-
-       if (ssm2602->master_substream == substream)
-               ssm2602->master_substream = ssm2602->slave_substream;
-
-       ssm2602->slave_substream = NULL;
-}
-
-
 static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
 {
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec);
@@ -520,9 +478,10 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\
-               SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
-               SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+               SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+               SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
+               SNDRV_PCM_RATE_96000)
 
 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -530,7 +489,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
 static const struct snd_soc_dai_ops ssm2602_dai_ops = {
        .startup        = ssm2602_startup,
        .hw_params      = ssm2602_hw_params,
-       .shutdown       = ssm2602_shutdown,
        .digital_mute   = ssm2602_mute,
        .set_sysclk     = ssm2602_set_dai_sysclk,
        .set_fmt        = ssm2602_set_dai_fmt,
@@ -551,6 +509,8 @@ static struct snd_soc_dai_driver ssm2602_dai = {
                .rates = SSM2602_RATES,
                .formats = SSM2602_FORMATS,},
        .ops = &ssm2602_dai_ops,
+       .symmetric_rates = 1,
+       .symmetric_samplebits = 1,
 };
 
 static int ssm2602_suspend(struct snd_soc_codec *codec)
@@ -730,7 +690,7 @@ static struct spi_driver ssm2602_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 /*
  * ssm2602 2 wire address is determined by GPIO5
  * state during powerup.
@@ -797,7 +757,7 @@ static int __init ssm2602_modinit(void)
                return ret;
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&ssm2602_i2c_driver);
        if (ret)
                return ret;
@@ -813,7 +773,7 @@ static void __exit ssm2602_exit(void)
        spi_unregister_driver(&ssm2602_spi_driver);
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&ssm2602_i2c_driver);
 #endif
 }
index 18cdcca9014cc66d394dd9e1df875f6edc2a7874..385dec16eb8a18150a7d6005f310af8c44001938 100644 (file)
@@ -267,8 +267,8 @@ static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
                .selector_mask  = 0xff,
                .window_start = 0,
                .window_len = 128,
-               .range_min = AIC32X4_PAGE1,
-               .range_max = AIC32X4_PAGE1 + 127,
+               .range_min = 0,
+               .range_max = AIC32X4_RMICPGAVOL,
        },
 };
 
index 546d16b7d38f87cd456e35286dbf3b9a8eab4b33..470fbfb4b3861314b6ecc74dfd95d5c2cd8b0d89 100644 (file)
@@ -350,16 +350,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
                         DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
                         0, 118, 1, output_stage_tlv),
 
-       SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
-                        LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
-                        PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
-                        DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-
        SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
                         LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
                         0, 118, 1, output_stage_tlv),
@@ -383,7 +373,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        /* Output pin mute controls */
        SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
                     0x01, 0),
-       SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
        SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
                     0x01, 0),
        SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
@@ -412,6 +401,20 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
 };
 
+static const struct snd_kcontrol_new aic3x_mono_controls[] = {
+       SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
+                        LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+       SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
+                        PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+       SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
+                        DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
+};
+
 /*
  * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps
  */
@@ -565,9 +568,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("Right HP Out", HPROUT_CTRL, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("Right HP Com", HPRCOM_CTRL, 0, 0, NULL, 0),
 
-       /* Mono Output */
-       SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
-
        /* Inputs to Left ADC */
        SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
        SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
@@ -626,9 +626,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0,
                           &aic3x_right_line_mixer_controls[0],
                           ARRAY_SIZE(aic3x_right_line_mixer_controls)),
-       SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_mono_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_mono_mixer_controls)),
        SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
                           &aic3x_left_hp_mixer_controls[0],
                           ARRAY_SIZE(aic3x_left_hp_mixer_controls)),
@@ -644,7 +641,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
 
        SND_SOC_DAPM_OUTPUT("LLOUT"),
        SND_SOC_DAPM_OUTPUT("RLOUT"),
-       SND_SOC_DAPM_OUTPUT("MONO_LOUT"),
        SND_SOC_DAPM_OUTPUT("HPLOUT"),
        SND_SOC_DAPM_OUTPUT("HPROUT"),
        SND_SOC_DAPM_OUTPUT("HPLCOM"),
@@ -666,6 +662,17 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("Detection"),
 };
 
+static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = {
+       /* Mono Output */
+       SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_mono_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_mono_mixer_controls)),
+
+       SND_SOC_DAPM_OUTPUT("MONO_LOUT"),
+};
+
 static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = {
        /* Class-D outputs */
        SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0),
@@ -754,17 +761,6 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"Right Line Out", NULL, "Right DAC Mux"},
        {"RLOUT", NULL, "Right Line Out"},
 
-       /* Mono Output */
-       {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
-       {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
-       {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
-       {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
-       {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
-       {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
-
-       {"Mono Out", NULL, "Mono Mixer"},
-       {"MONO_LOUT", NULL, "Mono Out"},
-
        /* Left HP Output */
        {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
        {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
@@ -820,6 +816,18 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"HPRCOM", NULL, "Right HP Com"},
 };
 
+static const struct snd_soc_dapm_route intercon_mono[] = {
+       /* Mono Output */
+       {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
+       {"Mono Out", NULL, "Mono Mixer"},
+       {"MONO_LOUT", NULL, "Mono Out"},
+};
+
 static const struct snd_soc_dapm_route intercon_3007[] = {
        /* Class-D outputs */
        {"Left Class-D Out", NULL, "Left Line Out"},
@@ -833,11 +841,20 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
        struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-       if (aic3x->model == AIC3X_MODEL_3007) {
+       switch (aic3x->model) {
+       case AIC3X_MODEL_3X:
+       case AIC3X_MODEL_33:
+               snd_soc_dapm_new_controls(dapm, aic3x_dapm_mono_widgets,
+                       ARRAY_SIZE(aic3x_dapm_mono_widgets));
+               snd_soc_dapm_add_routes(dapm, intercon_mono,
+                                       ARRAY_SIZE(intercon_mono));
+               break;
+       case AIC3X_MODEL_3007:
                snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
                        ARRAY_SIZE(aic3007_dapm_widgets));
                snd_soc_dapm_add_routes(dapm, intercon_3007,
                                        ARRAY_SIZE(intercon_3007));
+               break;
        }
 
        return 0;
@@ -1218,6 +1235,24 @@ static int aic3x_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
+static void aic3x_mono_init(struct snd_soc_codec *codec)
+{
+       /* DAC to Mono Line Out default volume and route to Output mixer */
+       snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+
+       /* unmute all outputs */
+       snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
+
+       /* PGA to Mono Line Out default volume, disconnect from Output Mixer */
+       snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
+
+       /* Line2 to Mono Out default volume, disconnect from Output Mixer */
+       snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
+}
+
 /*
  * initialise the AIC3X driver
  * register the mixer and dsp interfaces with the kernel
@@ -1241,14 +1276,10 @@ static int aic3x_init(struct snd_soc_codec *codec)
        /* DAC to Line Out default volume and route to Output mixer */
        snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
        snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
-       /* DAC to Mono Line Out default volume and route to Output mixer */
-       snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
-       snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
 
        /* unmute all outputs */
        snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE);
-       snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE);
@@ -1269,9 +1300,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
        /* PGA to Line Out default volume, disconnect from Output Mixer */
        snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
        snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
-       /* PGA to Mono Line Out default volume, disconnect from Output Mixer */
-       snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
 
        /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
        snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
@@ -1281,12 +1309,15 @@ static int aic3x_init(struct snd_soc_codec *codec)
        /* Line2 Line Out default volume, disconnect from Output Mixer */
        snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
        snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
-       /* Line2 to Mono Out default volume, disconnect from Output Mixer */
-       snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
 
-       if (aic3x->model == AIC3X_MODEL_3007) {
+       switch (aic3x->model) {
+       case AIC3X_MODEL_3X:
+       case AIC3X_MODEL_33:
+               aic3x_mono_init(codec);
+               break;
+       case AIC3X_MODEL_3007:
                snd_soc_write(codec, CLASSD_CTRL, 0);
+               break;
        }
 
        return 0;
@@ -1343,8 +1374,17 @@ static int aic3x_probe(struct snd_soc_codec *codec)
                              (aic3x->setup->gpio_func[1] & 0xf) << 4);
        }
 
-       if (aic3x->model == AIC3X_MODEL_3007)
-               snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+       switch (aic3x->model) {
+       case AIC3X_MODEL_3X:
+       case AIC3X_MODEL_33:
+               snd_soc_add_codec_controls(codec, aic3x_mono_controls,
+                               ARRAY_SIZE(aic3x_mono_controls));
+               break;
+       case AIC3X_MODEL_3007:
+               snd_soc_add_codec_controls(codec,
+                               &aic3x_classd_amp_gain_ctrl, 1);
+               break;
+       }
 
        /* set mic bias voltage */
        switch (aic3x->micbias_vg) {
index dfc51bb425da93b5dc6e2ac55af8ea3125b9e1b9..00665ada23e20bf37bc2b5e1af81b2a5afe3332e 100644 (file)
 
 #define TWL4030_CACHEREGNUM    (TWL4030_REG_MISC_SET_2 + 1)
 
-/*
- * twl4030 register cache & default register settings
- */
-static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
-       0x00, /* this register not used         */
-       0x00, /* REG_CODEC_MODE         (0x1)   */
-       0x00, /* REG_OPTION             (0x2)   */
-       0x00, /* REG_UNKNOWN            (0x3)   */
-       0x00, /* REG_MICBIAS_CTL        (0x4)   */
-       0x00, /* REG_ANAMICL            (0x5)   */
-       0x00, /* REG_ANAMICR            (0x6)   */
-       0x00, /* REG_AVADC_CTL          (0x7)   */
-       0x00, /* REG_ADCMICSEL          (0x8)   */
-       0x00, /* REG_DIGMIXING          (0x9)   */
-       0x0f, /* REG_ATXL1PGA           (0xA)   */
-       0x0f, /* REG_ATXR1PGA           (0xB)   */
-       0x0f, /* REG_AVTXL2PGA          (0xC)   */
-       0x0f, /* REG_AVTXR2PGA          (0xD)   */
-       0x00, /* REG_AUDIO_IF           (0xE)   */
-       0x00, /* REG_VOICE_IF           (0xF)   */
-       0x3f, /* REG_ARXR1PGA           (0x10)  */
-       0x3f, /* REG_ARXL1PGA           (0x11)  */
-       0x3f, /* REG_ARXR2PGA           (0x12)  */
-       0x3f, /* REG_ARXL2PGA           (0x13)  */
-       0x25, /* REG_VRXPGA             (0x14)  */
-       0x00, /* REG_VSTPGA             (0x15)  */
-       0x00, /* REG_VRX2ARXPGA         (0x16)  */
-       0x00, /* REG_AVDAC_CTL          (0x17)  */
-       0x00, /* REG_ARX2VTXPGA         (0x18)  */
-       0x32, /* REG_ARXL1_APGA_CTL     (0x19)  */
-       0x32, /* REG_ARXR1_APGA_CTL     (0x1A)  */
-       0x32, /* REG_ARXL2_APGA_CTL     (0x1B)  */
-       0x32, /* REG_ARXR2_APGA_CTL     (0x1C)  */
-       0x00, /* REG_ATX2ARXPGA         (0x1D)  */
-       0x00, /* REG_BT_IF              (0x1E)  */
-       0x55, /* REG_BTPGA              (0x1F)  */
-       0x00, /* REG_BTSTPGA            (0x20)  */
-       0x00, /* REG_EAR_CTL            (0x21)  */
-       0x00, /* REG_HS_SEL             (0x22)  */
-       0x00, /* REG_HS_GAIN_SET        (0x23)  */
-       0x00, /* REG_HS_POPN_SET        (0x24)  */
-       0x00, /* REG_PREDL_CTL          (0x25)  */
-       0x00, /* REG_PREDR_CTL          (0x26)  */
-       0x00, /* REG_PRECKL_CTL         (0x27)  */
-       0x00, /* REG_PRECKR_CTL         (0x28)  */
-       0x00, /* REG_HFL_CTL            (0x29)  */
-       0x00, /* REG_HFR_CTL            (0x2A)  */
-       0x05, /* REG_ALC_CTL            (0x2B)  */
-       0x00, /* REG_ALC_SET1           (0x2C)  */
-       0x00, /* REG_ALC_SET2           (0x2D)  */
-       0x00, /* REG_BOOST_CTL          (0x2E)  */
-       0x00, /* REG_SOFTVOL_CTL        (0x2F)  */
-       0x13, /* REG_DTMF_FREQSEL       (0x30)  */
-       0x00, /* REG_DTMF_TONEXT1H      (0x31)  */
-       0x00, /* REG_DTMF_TONEXT1L      (0x32)  */
-       0x00, /* REG_DTMF_TONEXT2H      (0x33)  */
-       0x00, /* REG_DTMF_TONEXT2L      (0x34)  */
-       0x79, /* REG_DTMF_TONOFF        (0x35)  */
-       0x11, /* REG_DTMF_WANONOFF      (0x36)  */
-       0x00, /* REG_I2S_RX_SCRAMBLE_H  (0x37)  */
-       0x00, /* REG_I2S_RX_SCRAMBLE_M  (0x38)  */
-       0x00, /* REG_I2S_RX_SCRAMBLE_L  (0x39)  */
-       0x06, /* REG_APLL_CTL           (0x3A)  */
-       0x00, /* REG_DTMF_CTL           (0x3B)  */
-       0x44, /* REG_DTMF_PGA_CTL2      (0x3C)  */
-       0x69, /* REG_DTMF_PGA_CTL1      (0x3D)  */
-       0x00, /* REG_MISC_SET_1         (0x3E)  */
-       0x00, /* REG_PCMBTMUX           (0x3F)  */
-       0x00, /* not used               (0x40)  */
-       0x00, /* not used               (0x41)  */
-       0x00, /* not used               (0x42)  */
-       0x00, /* REG_RX_PATH_SEL        (0x43)  */
-       0x32, /* REG_VDL_APGA_CTL       (0x44)  */
-       0x00, /* REG_VIBRA_CTL          (0x45)  */
-       0x00, /* REG_VIBRA_SET          (0x46)  */
-       0x00, /* REG_VIBRA_PWM_SET      (0x47)  */
-       0x00, /* REG_ANAMIC_GAIN        (0x48)  */
-       0x00, /* REG_MISC_SET_2         (0x49)  */
-};
-
 /* codec private data */
 struct twl4030_priv {
        unsigned int codec_powered;
@@ -150,81 +70,108 @@ struct twl4030_priv {
        u8 earpiece_enabled;
        u8 predrivel_enabled, predriver_enabled;
        u8 carkitl_enabled, carkitr_enabled;
+       u8 ctl_cache[TWL4030_REG_PRECKR_CTL - TWL4030_REG_EAR_CTL + 1];
 
        struct twl4030_codec_data *pdata;
 };
 
-/*
- * read twl4030 register cache
- */
-static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
+static void tw4030_init_ctl_cache(struct twl4030_priv *twl4030)
 {
-       u8 *cache = codec->reg_cache;
-
-       if (reg >= TWL4030_CACHEREGNUM)
-               return -EIO;
+       int i;
+       u8 byte;
 
-       return cache[reg];
+       for (i = TWL4030_REG_EAR_CTL; i <= TWL4030_REG_PRECKR_CTL; i++) {
+               twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, i);
+               twl4030->ctl_cache[i - TWL4030_REG_EAR_CTL] = byte;
+       }
 }
 
-/*
- * write twl4030 register cache
- */
-static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
-                                               u8 reg, u8 value)
+static unsigned int twl4030_read(struct snd_soc_codec *codec, unsigned int reg)
 {
-       u8 *cache = codec->reg_cache;
+       struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
+       u8 value = 0;
 
        if (reg >= TWL4030_CACHEREGNUM)
-               return;
-       cache[reg] = value;
+               return -EIO;
+
+       switch (reg) {
+       case TWL4030_REG_EAR_CTL:
+       case TWL4030_REG_PREDL_CTL:
+       case TWL4030_REG_PREDR_CTL:
+       case TWL4030_REG_PRECKL_CTL:
+       case TWL4030_REG_PRECKR_CTL:
+       case TWL4030_REG_HS_GAIN_SET:
+               value = twl4030->ctl_cache[reg - TWL4030_REG_EAR_CTL];
+               break;
+       default:
+               twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &value, reg);
+               break;
+       }
+
+       return value;
 }
 
-/*
- * write to the twl4030 register space
- */
-static int twl4030_write(struct snd_soc_codec *codec,
-                       unsigned int reg, unsigned int value)
+static bool twl4030_can_write_to_chip(struct twl4030_priv *twl4030,
+                                     unsigned int reg)
 {
-       struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
-       int write_to_reg = 0;
+       bool write_to_reg = false;
 
-       twl4030_write_reg_cache(codec, reg, value);
        /* Decide if the given register can be written */
        switch (reg) {
        case TWL4030_REG_EAR_CTL:
                if (twl4030->earpiece_enabled)
-                       write_to_reg = 1;
+                       write_to_reg = true;
                break;
        case TWL4030_REG_PREDL_CTL:
                if (twl4030->predrivel_enabled)
-                       write_to_reg = 1;
+                       write_to_reg = true;
                break;
        case TWL4030_REG_PREDR_CTL:
                if (twl4030->predriver_enabled)
-                       write_to_reg = 1;
+                       write_to_reg = true;
                break;
        case TWL4030_REG_PRECKL_CTL:
                if (twl4030->carkitl_enabled)
-                       write_to_reg = 1;
+                       write_to_reg = true;
                break;
        case TWL4030_REG_PRECKR_CTL:
                if (twl4030->carkitr_enabled)
-                       write_to_reg = 1;
+                       write_to_reg = true;
                break;
        case TWL4030_REG_HS_GAIN_SET:
                if (twl4030->hsl_enabled || twl4030->hsr_enabled)
-                       write_to_reg = 1;
+                       write_to_reg = true;
                break;
        default:
                /* All other register can be written */
-               write_to_reg = 1;
+               write_to_reg = true;
+               break;
+       }
+
+       return write_to_reg;
+}
+
+static int twl4030_write(struct snd_soc_codec *codec, unsigned int reg,
+                        unsigned int value)
+{
+       struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
+
+       /* Update the ctl cache */
+       switch (reg) {
+       case TWL4030_REG_EAR_CTL:
+       case TWL4030_REG_PREDL_CTL:
+       case TWL4030_REG_PREDR_CTL:
+       case TWL4030_REG_PRECKL_CTL:
+       case TWL4030_REG_PRECKR_CTL:
+       case TWL4030_REG_HS_GAIN_SET:
+               twl4030->ctl_cache[reg - TWL4030_REG_EAR_CTL] = value;
+               break;
+       default:
                break;
        }
-       if (write_to_reg)
-               return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                           value, reg);
+
+       if (twl4030_can_write_to_chip(twl4030, reg))
+               return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
 
        return 0;
 }
@@ -252,46 +199,14 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
        else
                mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
 
-       if (mode >= 0) {
-               twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode);
+       if (mode >= 0)
                twl4030->codec_powered = enable;
-       }
 
        /* REVISIT: this delay is present in TI sample drivers */
        /* but there seems to be no TRM requirement for it     */
        udelay(10);
 }
 
-static inline void twl4030_check_defaults(struct snd_soc_codec *codec)
-{
-       int i, difference = 0;
-       u8 val;
-
-       dev_dbg(codec->dev, "Checking TWL audio default configuration\n");
-       for (i = 1; i <= TWL4030_REG_MISC_SET_2; i++) {
-               twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val, i);
-               if (val != twl4030_reg[i]) {
-                       difference++;
-                       dev_dbg(codec->dev,
-                                "Reg 0x%02x: chip: 0x%02x driver: 0x%02x\n",
-                                i, val, twl4030_reg[i]);
-               }
-       }
-       dev_dbg(codec->dev, "Found %d non-matching registers. %s\n",
-                difference, difference ? "Not OK" : "OK");
-}
-
-static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
-{
-       int i;
-
-       /* set all audio section registers to reasonable defaults */
-       for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
-               if (i != TWL4030_REG_APLL_CTL)
-                       twl4030_write(codec, i, twl4030_reg[i]);
-
-}
-
 static void twl4030_setup_pdata_of(struct twl4030_codec_data *pdata,
                                   struct device_node *node)
 {
@@ -372,27 +287,17 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
                }
        }
 
-       /* Check defaults, if instructed before anything else */
-       if (pdata && pdata->check_defaults)
-               twl4030_check_defaults(codec);
-
-       /* Reset registers, if no setup data or if instructed to do so */
-       if (!pdata || (pdata && pdata->reset_registers))
-               twl4030_reset_registers(codec);
-
-       /* Refresh APLL_CTL register from HW */
-       twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
-                           TWL4030_REG_APLL_CTL);
-       twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, byte);
+       /* Initialize the local ctl register cache */
+       tw4030_init_ctl_cache(twl4030);
 
        /* anti-pop when changing analog gain */
-       reg = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
+       reg = twl4030_read(codec, TWL4030_REG_MISC_SET_1);
        twl4030_write(codec, TWL4030_REG_MISC_SET_1,
-               reg | TWL4030_SMOOTH_ANAVOL_EN);
+                     reg | TWL4030_SMOOTH_ANAVOL_EN);
 
        twl4030_write(codec, TWL4030_REG_OPTION,
-               TWL4030_ATXL1_EN | TWL4030_ATXR1_EN |
-               TWL4030_ARXL2_EN | TWL4030_ARXR2_EN);
+                     TWL4030_ATXL1_EN | TWL4030_ATXR1_EN |
+                     TWL4030_ARXL2_EN | TWL4030_ARXR2_EN);
 
        /* REG_ARXR2_APGA_CTL reset according to the TRM: 0dB, DA_EN */
        twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32);
@@ -403,19 +308,19 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
 
        twl4030->pdata = pdata;
 
-       reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+       reg = twl4030_read(codec, TWL4030_REG_HS_POPN_SET);
        reg &= ~TWL4030_RAMP_DELAY;
        reg |= (pdata->ramp_delay_value << 2);
-       twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg);
+       twl4030_write(codec, TWL4030_REG_HS_POPN_SET, reg);
 
        /* initiate offset cancellation */
        twl4030_codec_enable(codec, 1);
 
-       reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
+       reg = twl4030_read(codec, TWL4030_REG_ANAMICL);
        reg &= ~TWL4030_OFFSET_CNCL_SEL;
        reg |= pdata->offset_cncl_path;
        twl4030_write(codec, TWL4030_REG_ANAMICL,
-               reg | TWL4030_CNCL_OFFSET_START);
+                     reg | TWL4030_CNCL_OFFSET_START);
 
        /*
         * Wait for offset cancellation to complete.
@@ -425,15 +330,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
        msleep(20);
        do {
                usleep_range(1000, 2000);
+               twl_set_regcache_bypass(TWL4030_MODULE_AUDIO_VOICE, true);
                twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
-                                   TWL4030_REG_ANAMICL);
+                               TWL4030_REG_ANAMICL);
+               twl_set_regcache_bypass(TWL4030_MODULE_AUDIO_VOICE, false);
        } while ((i++ < 100) &&
                 ((byte & TWL4030_CNCL_OFFSET_START) ==
                  TWL4030_CNCL_OFFSET_START));
 
-       /* Make sure that the reg_cache has the same value as the HW */
-       twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte);
-
        twl4030_codec_enable(codec, 0);
 }
 
@@ -453,9 +357,6 @@ static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
                        status = twl4030_audio_disable_resource(
                                                        TWL4030_AUDIO_RES_APLL);
        }
-
-       if (status >= 0)
-               twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status);
 }
 
 /* Earpiece */
@@ -671,20 +572,18 @@ static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control =
  */
 #define TWL4030_OUTPUT_PGA(pin_name, reg, mask)                                \
 static int pin_name##pga_event(struct snd_soc_dapm_widget *w,          \
-               struct snd_kcontrol *kcontrol, int event)               \
+                              struct snd_kcontrol *kcontrol, int event) \
 {                                                                      \
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); \
                                                                        \
        switch (event) {                                                \
        case SND_SOC_DAPM_POST_PMU:                                     \
                twl4030->pin_name##_enabled = 1;                        \
-               twl4030_write(w->codec, reg,                            \
-                       twl4030_read_reg_cache(w->codec, reg));         \
+               twl4030_write(w->codec, reg, twl4030_read(w->codec, reg)); \
                break;                                                  \
        case SND_SOC_DAPM_POST_PMD:                                     \
                twl4030->pin_name##_enabled = 0;                        \
-               twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,            \
-                                       0, reg);                        \
+               twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 0, reg);   \
                break;                                                  \
        }                                                               \
        return 0;                                                       \
@@ -700,7 +599,7 @@ static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
 {
        unsigned char hs_ctl;
 
-       hs_ctl = twl4030_read_reg_cache(codec, reg);
+       hs_ctl = twl4030_read(codec, reg);
 
        if (ramp) {
                /* HF ramp-up */
@@ -727,7 +626,7 @@ static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
 }
 
 static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                              struct snd_kcontrol *kcontrol, int event)
 {
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
@@ -741,7 +640,7 @@ static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
 }
 
 static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                              struct snd_kcontrol *kcontrol, int event)
 {
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
@@ -755,14 +654,14 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
 }
 
 static int vibramux_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                         struct snd_kcontrol *kcontrol, int event)
 {
        twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff);
        return 0;
 }
 
 static int apll_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                     struct snd_kcontrol *kcontrol, int event)
 {
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
@@ -776,11 +675,11 @@ static int apll_event(struct snd_soc_dapm_widget *w,
 }
 
 static int aif_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                    struct snd_kcontrol *kcontrol, int event)
 {
        u8 audio_if;
 
-       audio_if = twl4030_read_reg_cache(w->codec, TWL4030_REG_AUDIO_IF);
+       audio_if = twl4030_read(w->codec, TWL4030_REG_AUDIO_IF);
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
                /* Enable AIF */
@@ -788,12 +687,12 @@ static int aif_event(struct snd_soc_dapm_widget *w,
                twl4030_apll_enable(w->codec, 1);
 
                twl4030_write(w->codec, TWL4030_REG_AUDIO_IF,
-                                               audio_if | TWL4030_AIF_EN);
+                             audio_if | TWL4030_AIF_EN);
                break;
        case SND_SOC_DAPM_POST_PMD:
                /* disable the DAI before we stop it's source PLL */
                twl4030_write(w->codec, TWL4030_REG_AUDIO_IF,
-                                               audio_if &  ~TWL4030_AIF_EN);
+                             audio_if &  ~TWL4030_AIF_EN);
                twl4030_apll_enable(w->codec, 0);
                break;
        }
@@ -810,8 +709,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
                                    8388608, 16777216, 33554432, 67108864};
        unsigned int delay;
 
-       hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
-       hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
+       hs_gain = twl4030_read(codec, TWL4030_REG_HS_GAIN_SET);
+       hs_pop = twl4030_read(codec, TWL4030_REG_HS_POPN_SET);
        delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
                twl4030->sysclk) + 1;
 
@@ -831,9 +730,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
                hs_pop |= TWL4030_VMID_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
                /* Actually write to the register */
-               twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       hs_gain,
-                                       TWL4030_REG_HS_GAIN_SET);
+               twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain,
+                                TWL4030_REG_HS_GAIN_SET);
                hs_pop |= TWL4030_RAMP_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
                /* Wait ramp delay time + 1, so the VMID can settle */
@@ -846,9 +744,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
                /* Wait ramp delay time + 1, so the VMID can settle */
                twl4030_wait_ms(delay);
                /* Bypass the reg_cache to mute the headset */
-               twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       hs_gain & (~0x0f),
-                                       TWL4030_REG_HS_GAIN_SET);
+               twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain & (~0x0f),
+                                TWL4030_REG_HS_GAIN_SET);
 
                hs_pop &= ~TWL4030_VMID_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -866,7 +763,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
 }
 
 static int headsetlpga_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                            struct snd_kcontrol *kcontrol, int event)
 {
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
 
@@ -890,7 +787,7 @@ static int headsetlpga_event(struct snd_soc_dapm_widget *w,
 }
 
 static int headsetrpga_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                            struct snd_kcontrol *kcontrol, int event)
 {
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
 
@@ -914,7 +811,7 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w,
 }
 
 static int digimic_event(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+                        struct snd_kcontrol *kcontrol, int event)
 {
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
        struct twl4030_codec_data *pdata = twl4030->pdata;
@@ -935,7 +832,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
  * Custom volsw and volsw_2r get/put functions to handle these gain bits.
  */
 static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
+                                    struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
@@ -964,7 +861,7 @@ static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
 }
 
 static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
+                                    struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
@@ -993,7 +890,7 @@ static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
 }
 
 static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
+                                       struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
@@ -1020,7 +917,7 @@ static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
 }
 
 static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
+                                       struct snd_ctl_elem_value *ucontrol)
 {
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
@@ -1751,11 +1648,11 @@ static void twl4030_constraints(struct twl4030_priv *twl4030,
 /* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for
  * capture has to be enabled/disabled. */
 static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction,
-                               int enable)
+                              int enable)
 {
        u8 reg, mask;
 
-       reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
+       reg = twl4030_read(codec, TWL4030_REG_OPTION);
 
        if (direction == SNDRV_PCM_STREAM_PLAYBACK)
                mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN;
@@ -1784,14 +1681,14 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
                if (twl4030->configured)
                        twl4030_constraints(twl4030, twl4030->master_substream);
        } else {
-               if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) &
+               if (!(twl4030_read(codec, TWL4030_REG_CODEC_MODE) &
                        TWL4030_OPTION_1)) {
                        /* In option2 4 channel is not supported, set the
                         * constraint for the first stream for channels, the
                         * second stream will 'inherit' this cosntraint */
                        snd_pcm_hw_constraint_minmax(substream->runtime,
-                                               SNDRV_PCM_HW_PARAM_CHANNELS,
-                                               2, 2);
+                                                    SNDRV_PCM_HW_PARAM_CHANNELS,
+                                                    2, 2);
                }
                twl4030->master_substream = substream;
        }
@@ -1823,8 +1720,8 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
 }
 
 static int twl4030_hw_params(struct snd_pcm_substream *substream,
-                          struct snd_pcm_hw_params *params,
-                          struct snd_soc_dai *dai)
+                            struct snd_pcm_hw_params *params,
+                            struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -1832,8 +1729,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
 
         /* If the substream has 4 channel, do the necessary setup */
        if (params_channels(params) == 4) {
-               format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
-               mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
+               format = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
+               mode = twl4030_read(codec, TWL4030_REG_CODEC_MODE);
 
                /* Safety check: are we in the correct operating mode and
                 * the interface is in TDM mode? */
@@ -1849,8 +1746,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
                return 0;
 
        /* bit rate */
-       old_mode = twl4030_read_reg_cache(codec,
-                       TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
+       old_mode = twl4030_read(codec,
+                               TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
        mode = old_mode & ~TWL4030_APLL_RATE;
 
        switch (params_rate(params)) {
@@ -1891,7 +1788,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* sample size */
-       old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+       old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
        format = old_format;
        format &= ~TWL4030_DATA_WIDTH;
        switch (params_format(params)) {
@@ -1940,8 +1837,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-               int clk_id, unsigned int freq, int dir)
+static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
+                                 unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -1966,15 +1863,14 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
-                            unsigned int fmt)
+static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 old_format, format;
 
        /* get format */
-       old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+       old_format = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
        format = old_format;
 
        /* set master/slave audio interface */
@@ -2024,7 +1920,7 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+       u8 reg = twl4030_read(codec, TWL4030_REG_AUDIO_IF);
 
        if (tristate)
                reg |= TWL4030_AIF_TRI_EN;
@@ -2037,11 +1933,11 @@ static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate)
 /* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
  * (VTXL, VTXR) for uplink has to be enabled/disabled. */
 static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
-                               int enable)
+                                int enable)
 {
        u8 reg, mask;
 
-       reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION);
+       reg = twl4030_read(codec, TWL4030_REG_OPTION);
 
        if (direction == SNDRV_PCM_STREAM_PLAYBACK)
                mask = TWL4030_ARXL1_VRX_EN;
@@ -2057,7 +1953,7 @@ static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
 }
 
 static int twl4030_voice_startup(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
+                                struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -2076,7 +1972,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
        /* If the codec mode is not option2, the voice PCM interface is not
         * available.
         */
-       mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
+       mode = twl4030_read(codec, TWL4030_REG_CODEC_MODE)
                & TWL4030_OPT_MODE;
 
        if (mode != TWL4030_OPTION_2) {
@@ -2089,7 +1985,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
 }
 
 static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
-                               struct snd_soc_dai *dai)
+                                  struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
 
@@ -2098,7 +1994,8 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
 }
 
 static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
-               struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+                                  struct snd_pcm_hw_params *params,
+                                  struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -2108,8 +2005,8 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
        twl4030_voice_enable(codec, substream->stream, 1);
 
        /* bit rate */
-       old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
-               & ~(TWL4030_CODECPDZ);
+       old_mode = twl4030_read(codec,
+                               TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
        mode = old_mode;
 
        switch (params_rate(params)) {
@@ -2143,7 +2040,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
 }
 
 static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-               int clk_id, unsigned int freq, int dir)
+                                       int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@@ -2164,14 +2061,14 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 }
 
 static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt)
+                                    unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 old_format, format;
 
        /* get format */
-       old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
+       old_format = twl4030_read(codec, TWL4030_REG_VOICE_IF);
        format = old_format;
 
        /* set master/slave audio interface */
@@ -2218,7 +2115,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
+       u8 reg = twl4030_read(codec, TWL4030_REG_VOICE_IF);
 
        if (tristate)
                reg |= TWL4030_VIF_TRI_EN;
@@ -2310,8 +2207,6 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec)
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        struct twl4030_codec_data *pdata = twl4030->pdata;
 
-       /* Reset registers to their chip default before leaving */
-       twl4030_reset_registers(codec);
        twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio))
@@ -2323,13 +2218,10 @@ static int twl4030_soc_remove(struct snd_soc_codec *codec)
 static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
        .probe = twl4030_soc_probe,
        .remove = twl4030_soc_remove,
-       .read = twl4030_read_reg_cache,
+       .read = twl4030_read,
        .write = twl4030_write,
        .set_bias_level = twl4030_set_bias_level,
        .idle_bias_off = true,
-       .reg_cache_size = sizeof(twl4030_reg),
-       .reg_word_size = sizeof(u8),
-       .reg_cache_default = twl4030_reg,
 
        .controls = twl4030_snd_controls,
        .num_controls = ARRAY_SIZE(twl4030_snd_controls),
@@ -2342,7 +2234,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
 static int twl4030_codec_probe(struct platform_device *pdev)
 {
        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
-                       twl4030_dai, ARRAY_SIZE(twl4030_dai));
+                                     twl4030_dai, ARRAY_SIZE(twl4030_dai));
 }
 
 static int twl4030_codec_remove(struct platform_device *pdev)
index f2f4bcb2ff71527b6dde8b264be2c99de7bf4c37..0afe8bef6765645ef75a9454f929c20b0d3c86b4 100644 (file)
@@ -72,6 +72,7 @@ struct twl6040_data {
        int hs_power_mode_locked;
        bool dl1_unmuted;
        bool dl2_unmuted;
+       u8 dl12_cache[TWL6040_REG_HFRCTL - TWL6040_REG_HSLCTL + 1];
        unsigned int clk_in;
        unsigned int sysclk;
        struct twl6040_jack_data hs_jack;
@@ -79,75 +80,6 @@ struct twl6040_data {
        struct mutex mutex;
 };
 
-/*
- * twl6040 register cache & default register settings
- */
-static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
-       0x00, /* not used       0x00    */
-       0x4B, /* REG_ASICID     0x01 (ro) */
-       0x00, /* REG_ASICREV    0x02 (ro) */
-       0x00, /* REG_INTID      0x03    */
-       0x00, /* REG_INTMR      0x04    */
-       0x00, /* REG_NCPCTRL    0x05    */
-       0x00, /* REG_LDOCTL     0x06    */
-       0x60, /* REG_HPPLLCTL   0x07    */
-       0x00, /* REG_LPPLLCTL   0x08    */
-       0x4A, /* REG_LPPLLDIV   0x09    */
-       0x00, /* REG_AMICBCTL   0x0A    */
-       0x00, /* REG_DMICBCTL   0x0B    */
-       0x00, /* REG_MICLCTL    0x0C    */
-       0x00, /* REG_MICRCTL    0x0D    */
-       0x00, /* REG_MICGAIN    0x0E    */
-       0x1B, /* REG_LINEGAIN   0x0F    */
-       0x00, /* REG_HSLCTL     0x10    */
-       0x00, /* REG_HSRCTL     0x11    */
-       0x00, /* REG_HSGAIN     0x12    */
-       0x00, /* REG_EARCTL     0x13    */
-       0x00, /* REG_HFLCTL     0x14    */
-       0x00, /* REG_HFLGAIN    0x15    */
-       0x00, /* REG_HFRCTL     0x16    */
-       0x00, /* REG_HFRGAIN    0x17    */
-       0x00, /* REG_VIBCTLL    0x18    */
-       0x00, /* REG_VIBDATL    0x19    */
-       0x00, /* REG_VIBCTLR    0x1A    */
-       0x00, /* REG_VIBDATR    0x1B    */
-       0x00, /* REG_HKCTL1     0x1C    */
-       0x00, /* REG_HKCTL2     0x1D    */
-       0x00, /* REG_GPOCTL     0x1E    */
-       0x00, /* REG_ALB        0x1F    */
-       0x00, /* REG_DLB        0x20    */
-       0x00, /* not used       0x21    */
-       0x00, /* not used       0x22    */
-       0x00, /* not used       0x23    */
-       0x00, /* not used       0x24    */
-       0x00, /* not used       0x25    */
-       0x00, /* not used       0x26    */
-       0x00, /* not used       0x27    */
-       0x00, /* REG_TRIM1      0x28    */
-       0x00, /* REG_TRIM2      0x29    */
-       0x00, /* REG_TRIM3      0x2A    */
-       0x00, /* REG_HSOTRIM    0x2B    */
-       0x00, /* REG_HFOTRIM    0x2C    */
-       0x09, /* REG_ACCCTL     0x2D    */
-       0x00, /* REG_STATUS     0x2E (ro) */
-};
-
-/* List of registers to be restored after power up */
-static const int twl6040_restore_list[] = {
-       TWL6040_REG_MICLCTL,
-       TWL6040_REG_MICRCTL,
-       TWL6040_REG_MICGAIN,
-       TWL6040_REG_LINEGAIN,
-       TWL6040_REG_HSLCTL,
-       TWL6040_REG_HSRCTL,
-       TWL6040_REG_HSGAIN,
-       TWL6040_REG_EARCTL,
-       TWL6040_REG_HFLCTL,
-       TWL6040_REG_HFLGAIN,
-       TWL6040_REG_HFRCTL,
-       TWL6040_REG_HFRGAIN,
-};
-
 /* set of rates for each pll: low-power and high-performance */
 static unsigned int lp_rates[] = {
        8000,
@@ -174,53 +106,33 @@ static struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
        { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
 };
 
-/*
- * read twl6040 register cache
- */
-static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec,
-                                               unsigned int reg)
-{
-       u8 *cache = codec->reg_cache;
-
-       if (reg >= TWL6040_CACHEREGNUM)
-               return -EIO;
-
-       return cache[reg];
-}
-
-/*
- * write twl6040 register cache
- */
-static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec,
-                                               u8 reg, u8 value)
-{
-       u8 *cache = codec->reg_cache;
-
-       if (reg >= TWL6040_CACHEREGNUM)
-               return;
-       cache[reg] = value;
-}
-
-/*
- * read from twl6040 hardware register
- */
-static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
-                       unsigned int reg)
+static unsigned int twl6040_read(struct snd_soc_codec *codec, unsigned int reg)
 {
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        struct twl6040 *twl6040 = codec->control_data;
        u8 value;
 
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
-       value = twl6040_reg_read(twl6040, reg);
-       twl6040_write_reg_cache(codec, reg, value);
+       switch (reg) {
+       case TWL6040_REG_HSLCTL:
+       case TWL6040_REG_HSRCTL:
+       case TWL6040_REG_EARCTL:
+       case TWL6040_REG_HFLCTL:
+       case TWL6040_REG_HFRCTL:
+               value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL];
+               break;
+       default:
+               value = twl6040_reg_read(twl6040, reg);
+               break;
+       }
 
        return value;
 }
 
-static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec,
+                                 unsigned int reg)
 {
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
@@ -238,9 +150,24 @@ static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec,
        }
 }
 
-/*
- * write to the twl6040 register space
- */
+static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec,
+                                            u8 reg, u8 value)
+{
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
+
+       switch (reg) {
+       case TWL6040_REG_HSLCTL:
+       case TWL6040_REG_HSRCTL:
+       case TWL6040_REG_EARCTL:
+       case TWL6040_REG_HFLCTL:
+       case TWL6040_REG_HFRCTL:
+               priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value;
+               break;
+       default:
+               break;
+       }
+}
+
 static int twl6040_write(struct snd_soc_codec *codec,
                        unsigned int reg, unsigned int value)
 {
@@ -249,8 +176,8 @@ static int twl6040_write(struct snd_soc_codec *codec,
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
-       twl6040_write_reg_cache(codec, reg, value);
-       if (twl6040_is_path_unmuted(codec, reg))
+       twl6040_update_dl12_cache(codec, reg, value);
+       if (twl6040_can_write_to_chip(codec, reg))
                return twl6040_reg_write(twl6040, reg, value);
        else
                return 0;
@@ -258,45 +185,27 @@ static int twl6040_write(struct snd_soc_codec *codec,
 
 static void twl6040_init_chip(struct snd_soc_codec *codec)
 {
-       struct twl6040 *twl6040 = codec->control_data;
-       u8 val;
-
-       /* Update reg_cache: ASICREV, and TRIM values */
-       val = twl6040_get_revid(twl6040);
-       twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
-
-       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1);
-       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2);
-       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3);
-       twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM);
-       twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM);
+       twl6040_read(codec, TWL6040_REG_TRIM1);
+       twl6040_read(codec, TWL6040_REG_TRIM2);
+       twl6040_read(codec, TWL6040_REG_TRIM3);
+       twl6040_read(codec, TWL6040_REG_HSOTRIM);
+       twl6040_read(codec, TWL6040_REG_HFOTRIM);
 
        /* Change chip defaults */
        /* No imput selected for microphone amplifiers */
-       twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18);
-       twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18);
+       twl6040_write(codec, TWL6040_REG_MICLCTL, 0x18);
+       twl6040_write(codec, TWL6040_REG_MICRCTL, 0x18);
 
        /*
         * We need to lower the default gain values, so the ramp code
         * can work correctly for the first playback.
         * This reduces the pop noise heard at the first playback.
         */
-       twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff);
-       twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e);
-       twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d);
-       twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d);
-       twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0);
-}
-
-static void twl6040_restore_regs(struct snd_soc_codec *codec)
-{
-       u8 *cache = codec->reg_cache;
-       int reg, i;
-
-       for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) {
-               reg = twl6040_restore_list[i];
-               twl6040_write(codec, reg, cache[reg]);
-       }
+       twl6040_write(codec, TWL6040_REG_HSGAIN, 0xff);
+       twl6040_write(codec, TWL6040_REG_EARCTL, 0x1e);
+       twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1d);
+       twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1d);
+       twl6040_write(codec, TWL6040_REG_LINEGAIN, 0);
 }
 
 /* set headset dac and driver power mode */
@@ -305,8 +214,8 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
        int hslctl, hsrctl;
        int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
 
-       hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
-       hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
+       hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
+       hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
 
        if (high_perf) {
                hslctl &= ~mask;
@@ -333,8 +242,8 @@ static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
         * Both HS DAC need to be turned on (before the HS driver) and off at
         * the same time.
         */
-       hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
-       hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
+       hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
+       hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
        if (SND_SOC_DAPM_EVENT_ON(event)) {
                hslctl |= TWL6040_HSDACENA;
                hsrctl |= TWL6040_HSDACENA;
@@ -379,7 +288,7 @@ static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
        mutex_lock(&priv->mutex);
 
        /* Sync status */
-       status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS);
+       status = twl6040_read(codec, TWL6040_REG_STATUS);
        if (status & TWL6040_PLUGCOMP)
                snd_soc_jack_report(jack, report, report);
        else
@@ -431,7 +340,7 @@ static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
        unsigned int val;
 
        /* Do not allow changes while Input/FF efect is running */
-       val = twl6040_read_reg_volatile(codec, e->reg);
+       val = twl6040_read(codec, e->reg);
        if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
                return -EBUSY;
 
@@ -656,7 +565,7 @@ int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
        if (unlikely(trim >= TWL6040_TRIM_INVAL))
                return -EINVAL;
 
-       return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim);
+       return twl6040_read(codec, TWL6040_REG_TRIM1 + trim);
 }
 EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
 
@@ -931,8 +840,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 
                priv->codec_powered = 1;
 
-               twl6040_restore_regs(codec);
-
                /* Set external boost GPO */
                twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
                break;
@@ -1053,9 +960,9 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
 
        switch (id) {
        case TWL6040_DAI_DL1:
-               hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
-               hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
-               earctl = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL);
+               hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
+               hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
+               earctl = twl6040_read(codec, TWL6040_REG_EARCTL);
 
                if (mute) {
                        /* Power down drivers and DACs */
@@ -1071,8 +978,8 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
                priv->dl1_unmuted = !mute;
                break;
        case TWL6040_DAI_DL2:
-               hflctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL);
-               hfrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL);
+               hflctl = twl6040_read(codec, TWL6040_REG_HFLCTL);
+               hfrctl = twl6040_read(codec, TWL6040_REG_HFRCTL);
 
                if (mute) {
                        /* Power down drivers and DACs */
@@ -1209,6 +1116,7 @@ static int twl6040_resume(struct snd_soc_codec *codec)
 static int twl6040_probe(struct snd_soc_codec *codec)
 {
        struct twl6040_data *priv;
+       struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent);
        struct platform_device *pdev = container_of(codec->dev,
                                                   struct platform_device, dev);
        int ret = 0;
@@ -1220,7 +1128,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
        snd_soc_codec_set_drvdata(codec, priv);
 
        priv->codec = codec;
-       codec->control_data = dev_get_drvdata(codec->dev->parent);
+       codec->control_data = twl6040;
 
        priv->plug_irq = platform_get_irq(pdev, 0);
        if (priv->plug_irq < 0) {
@@ -1240,10 +1148,10 @@ static int twl6040_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
+       twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        twl6040_init_chip(codec);
 
-       /* power on device */
-       return twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
 }
 
 static int twl6040_remove(struct snd_soc_codec *codec)
@@ -1261,12 +1169,9 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
        .remove = twl6040_remove,
        .suspend = twl6040_suspend,
        .resume = twl6040_resume,
-       .read = twl6040_read_reg_cache,
+       .read = twl6040_read,
        .write = twl6040_write,
        .set_bias_level = twl6040_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(twl6040_reg),
-       .reg_word_size = sizeof(u8),
-       .reg_cache_default = twl6040_reg,
        .ignore_pmdown_time = true,
 
        .controls = twl6040_snd_controls,
index fd0a314bc209a4005e8b3488930b6b7d3215526f..726df6d43c2b69227adc503e38397f977db4f220 100644 (file)
@@ -794,7 +794,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
        .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int uda1380_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
@@ -840,7 +840,7 @@ static struct i2c_driver uda1380_i2c_driver = {
 static int __init uda1380_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&uda1380_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
@@ -851,7 +851,7 @@ module_init(uda1380_modinit);
 
 static void __exit uda1380_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&uda1380_i2c_driver);
 #endif
 }
index a08e8bf6d07cb7db76cf8075d2e61d2ec2464b18..ce9c8e14d4bd105cfc33991604a06440e67ca1f0 100644 (file)
@@ -601,8 +601,8 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                if (patch)
                        for (i = 0; i < patch_size; i++)
-                               regmap_write(regmap, patch[i].reg,
-                                            patch[i].def);
+                               regmap_write_async(regmap, patch[i].reg,
+                                                  patch[i].def);
                break;
 
        default:
index c3c7396a618115d06171bb87314b363cc8ac9f6d..d862f76b59f9ecba646e065863d2040a04a0d0b0 100644 (file)
 #include <linux/mfd/arizona/registers.h>
 
 #include "arizona.h"
+#include "wm_adsp.h"
 #include "wm5110.h"
 
+#define WM5110_NUM_ADSP 4
+
 struct wm5110_priv {
        struct arizona_priv core;
        struct arizona_fll fll[2];
 };
 
+static const struct wm_adsp_region wm5110_dsp1_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
+};
+
+static const struct wm_adsp_region wm5110_dsp2_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x200000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x280000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x290000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x2a8000 },
+};
+
+static const struct wm_adsp_region wm5110_dsp3_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x300000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x380000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x390000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x3a8000 },
+};
+
+static const struct wm_adsp_region wm5110_dsp4_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x400000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x480000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x490000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x4a8000 },
+};
+
+static const struct wm_adsp_region *wm5110_dsp_regions[] = {
+       wm5110_dsp1_regions,
+       wm5110_dsp2_regions,
+       wm5110_dsp3_regions,
+       wm5110_dsp4_regions,
+};
+
 static const struct reg_default wm5110_sysclk_revd_patch[] = {
        { 0x3093, 0x1001 },
        { 0x30E3, 0x1301 },
@@ -67,8 +105,8 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                if (patch)
                        for (i = 0; i < patch_size; i++)
-                               regmap_write(regmap, patch[i].reg,
-                                            patch[i].def);
+                               regmap_write_async(regmap, patch[i].reg,
+                                                  patch[i].def);
                break;
 
        default:
@@ -117,6 +155,25 @@ SOC_SINGLE_RANGE_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL,
 SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL,
                     ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
 
+SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum),
+
+SOC_SINGLE("IN1L HPF Switch", ARIZONA_IN1L_CONTROL,
+          ARIZONA_IN1L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN1R HPF Switch", ARIZONA_IN1R_CONTROL,
+          ARIZONA_IN1R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN2L HPF Switch", ARIZONA_IN2L_CONTROL,
+          ARIZONA_IN2L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN2R HPF Switch", ARIZONA_IN2R_CONTROL,
+          ARIZONA_IN2R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN3L HPF Switch", ARIZONA_IN3L_CONTROL,
+          ARIZONA_IN3L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN3R HPF Switch", ARIZONA_IN3R_CONTROL,
+          ARIZONA_IN3R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN4L HPF Switch", ARIZONA_IN4L_CONTROL,
+          ARIZONA_IN4L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN4R HPF Switch", ARIZONA_IN4R_CONTROL,
+          ARIZONA_IN4R_HPF_SHIFT, 1, 0),
+
 SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
               ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
 SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R,
@@ -220,6 +277,14 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
 
+SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_VALUE_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
+SOC_VALUE_ENUM("ISRC1 FSH", arizona_isrc_fsh[0]),
+SOC_VALUE_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),
+SOC_VALUE_ENUM("ISRC3 FSH", arizona_isrc_fsh[2]),
+SOC_VALUE_ENUM("ASRC RATE 1", arizona_asrc_rate1),
+
 ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE),
@@ -248,18 +313,12 @@ ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE),
 
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-          ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("HPOUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-          ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("HPOUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-          ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
-          ARIZONA_OUT4_OSR_SHIFT, 1, 0),
-SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
-          ARIZONA_OUT5_OSR_SHIFT, 1, 0),
-SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
-          ARIZONA_OUT6_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT1 SC Protect Switch", ARIZONA_HP1_SHORT_CIRCUIT_CTRL,
+          ARIZONA_HP1_SC_ENA_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT2 SC Protect Switch", ARIZONA_HP2_SHORT_CIRCUIT_CTRL,
+          ARIZONA_HP2_SC_ENA_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT3 SC Protect Switch", ARIZONA_HP3_SHORT_CIRCUIT_CTRL,
+          ARIZONA_HP3_SC_ENA_SHIFT, 1, 0),
 
 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
             ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
@@ -293,23 +352,18 @@ SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L,
                 ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_1R,
-                      ARIZONA_OUT1L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_2R,
-                      ARIZONA_OUT2L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_3R,
-                      ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
-
 SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
           ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
           ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
 
+SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE,
+          ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0),
+SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE,
+          ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0),
+SOC_DOUBLE("HPOUT3 DRE Switch", ARIZONA_DRE_ENABLE,
+          ARIZONA_DRE3L_ENA_SHIFT, ARIZONA_DRE3R_ENA_SHIFT, 1, 0),
+
 SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
 SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
 
@@ -343,6 +397,10 @@ ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
 
 ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX3", ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX4", ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX5", ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE),
 
 ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
@@ -372,6 +430,22 @@ ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
 
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP2L, ARIZONA_DSP2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP2R, ARIZONA_DSP2RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP2, ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP3L, ARIZONA_DSP3LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP3R, ARIZONA_DSP3RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP3, ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP4L, ARIZONA_DSP4LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP4R, ARIZONA_DSP4RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP4, ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE);
+
 ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
 
@@ -402,6 +476,10 @@ ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
 
 ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX3, ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX4, ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX5, ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX6, ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE);
 
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
@@ -420,6 +498,36 @@ ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
 ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
 ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
 
+ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT3, ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT4, ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC3, ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC4, ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT3, ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT4, ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC3, ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC4, ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC3INT1, ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT2, ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT3, ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT4, ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC3DEC1, ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC2, ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC3, ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC4, ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE);
+
 static const char *wm5110_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
        "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R",
@@ -560,6 +668,65 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
                 NULL, 0),
 
+WM_ADSP2("DSP1", 0),
+WM_ADSP2("DSP2", 1),
+WM_ADSP2("DSP3", 2),
+WM_ADSP2("DSP4", 3),
+
+SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT3", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT4", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC3", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC4", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT3", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT4", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC3", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC4", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC3INT1", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT2", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT3", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT4", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC3DEC1", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC2", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0),
+
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
                       ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
                       &wm5110_aec_loopback_mux),
@@ -602,11 +769,27 @@ SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
                     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
 SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
                     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0),
 
 SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
                    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
 SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
                    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0),
 
 SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
                    ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
@@ -744,6 +927,10 @@ ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
 
 ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
 ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+ARIZONA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"),
+ARIZONA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"),
+ARIZONA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"),
+ARIZONA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"),
 
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
@@ -762,6 +949,41 @@ ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
 ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
 ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
 
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+ARIZONA_DSP_WIDGETS(DSP2, "DSP2"),
+ARIZONA_DSP_WIDGETS(DSP3, "DSP3"),
+ARIZONA_DSP_WIDGETS(DSP4, "DSP4"),
+
+ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"),
+ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"),
+ARIZONA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"),
+ARIZONA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"),
+
+ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
+ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
+ARIZONA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"),
+ARIZONA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"),
+
+ARIZONA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC3, "ISRC3DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC4, "ISRC3DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"),
+ARIZONA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"),
+ARIZONA_MUX_WIDGETS(ISRC3INT3, "ISRC3INT3"),
+ARIZONA_MUX_WIDGETS(ISRC3INT4, "ISRC3INT4"),
+
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
 SND_SOC_DAPM_OUTPUT("HPOUT2L"),
@@ -805,6 +1027,10 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"),
        { name, "AIF1RX8", "AIF1RX8" }, \
        { name, "AIF2RX1", "AIF2RX1" }, \
        { name, "AIF2RX2", "AIF2RX2" }, \
+       { name, "AIF2RX3", "AIF2RX3" }, \
+       { name, "AIF2RX4", "AIF2RX4" }, \
+       { name, "AIF2RX5", "AIF2RX5" }, \
+       { name, "AIF2RX6", "AIF2RX6" }, \
        { name, "AIF3RX1", "AIF3RX1" }, \
        { name, "AIF3RX2", "AIF3RX2" }, \
        { name, "SLIMRX1", "SLIMRX1" }, \
@@ -830,7 +1056,55 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"),
        { name, "ASRC1L", "ASRC1L" }, \
        { name, "ASRC1R", "ASRC1R" }, \
        { name, "ASRC2L", "ASRC2L" }, \
-       { name, "ASRC2R", "ASRC2R" }
+       { name, "ASRC2R", "ASRC2R" }, \
+       { name, "ISRC1DEC1", "ISRC1DEC1" }, \
+       { name, "ISRC1DEC2", "ISRC1DEC2" }, \
+       { name, "ISRC1DEC3", "ISRC1DEC3" }, \
+       { name, "ISRC1DEC4", "ISRC1DEC4" }, \
+       { name, "ISRC1INT1", "ISRC1INT1" }, \
+       { name, "ISRC1INT2", "ISRC1INT2" }, \
+       { name, "ISRC1INT3", "ISRC1INT3" }, \
+       { name, "ISRC1INT4", "ISRC1INT4" }, \
+       { name, "ISRC2DEC1", "ISRC2DEC1" }, \
+       { name, "ISRC2DEC2", "ISRC2DEC2" }, \
+       { name, "ISRC2DEC3", "ISRC2DEC3" }, \
+       { name, "ISRC2DEC4", "ISRC2DEC4" }, \
+       { name, "ISRC2INT1", "ISRC2INT1" }, \
+       { name, "ISRC2INT2", "ISRC2INT2" }, \
+       { name, "ISRC2INT3", "ISRC2INT3" }, \
+       { name, "ISRC2INT4", "ISRC2INT4" }, \
+       { name, "ISRC3DEC1", "ISRC3DEC1" }, \
+       { name, "ISRC3DEC2", "ISRC3DEC2" }, \
+       { name, "ISRC3DEC3", "ISRC3DEC3" }, \
+       { name, "ISRC3DEC4", "ISRC3DEC4" }, \
+       { name, "ISRC3INT1", "ISRC3INT1" }, \
+       { name, "ISRC3INT2", "ISRC3INT2" }, \
+       { name, "ISRC3INT3", "ISRC3INT3" }, \
+       { name, "ISRC3INT4", "ISRC3INT4" }, \
+       { name, "DSP1.1", "DSP1" }, \
+       { name, "DSP1.2", "DSP1" }, \
+       { name, "DSP1.3", "DSP1" }, \
+       { name, "DSP1.4", "DSP1" }, \
+       { name, "DSP1.5", "DSP1" }, \
+       { name, "DSP1.6", "DSP1" }, \
+       { name, "DSP2.1", "DSP2" }, \
+       { name, "DSP2.2", "DSP2" }, \
+       { name, "DSP2.3", "DSP2" }, \
+       { name, "DSP2.4", "DSP2" }, \
+       { name, "DSP2.5", "DSP2" }, \
+       { name, "DSP2.6", "DSP2" }, \
+       { name, "DSP3.1", "DSP3" }, \
+       { name, "DSP3.2", "DSP3" }, \
+       { name, "DSP3.3", "DSP3" }, \
+       { name, "DSP3.4", "DSP3" }, \
+       { name, "DSP3.5", "DSP3" }, \
+       { name, "DSP3.6", "DSP3" }, \
+       { name, "DSP4.1", "DSP4" }, \
+       { name, "DSP4.2", "DSP4" }, \
+       { name, "DSP4.3", "DSP4" }, \
+       { name, "DSP4.4", "DSP4" }, \
+       { name, "DSP4.5", "DSP4" }, \
+       { name, "DSP4.6", "DSP4" }
 
 static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "AIF2 Capture", NULL, "DBVDD2" },
@@ -902,9 +1176,17 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
 
        { "AIF2 Capture", NULL, "AIF2TX1" },
        { "AIF2 Capture", NULL, "AIF2TX2" },
+       { "AIF2 Capture", NULL, "AIF2TX3" },
+       { "AIF2 Capture", NULL, "AIF2TX4" },
+       { "AIF2 Capture", NULL, "AIF2TX5" },
+       { "AIF2 Capture", NULL, "AIF2TX6" },
 
        { "AIF2RX1", NULL, "AIF2 Playback" },
        { "AIF2RX2", NULL, "AIF2 Playback" },
+       { "AIF2RX3", NULL, "AIF2 Playback" },
+       { "AIF2RX4", NULL, "AIF2 Playback" },
+       { "AIF2RX5", NULL, "AIF2 Playback" },
+       { "AIF2RX6", NULL, "AIF2 Playback" },
 
        { "AIF3 Capture", NULL, "AIF3TX1" },
        { "AIF3 Capture", NULL, "AIF3TX2" },
@@ -988,6 +1270,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
 
        ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
        ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+       ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"),
+       ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"),
+       ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"),
+       ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"),
 
        ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
        ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
@@ -1024,6 +1310,41 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
        ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
 
+       ARIZONA_DSP_ROUTES("DSP1"),
+       ARIZONA_DSP_ROUTES("DSP2"),
+       ARIZONA_DSP_ROUTES("DSP3"),
+       ARIZONA_DSP_ROUTES("DSP4"),
+
+       ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"),
+       ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"),
+       ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"),
+       ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"),
+
+       ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"),
+       ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"),
+       ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"),
+       ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"),
+
+       ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"),
+       ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"),
+       ARIZONA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"),
+       ARIZONA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"),
+
+       ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"),
+       ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"),
+       ARIZONA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"),
+       ARIZONA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"),
+
+       ARIZONA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"),
+       ARIZONA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"),
+       ARIZONA_MUX_ROUTES("ISRC3INT3", "ISRC3INT3"),
+       ARIZONA_MUX_ROUTES("ISRC3INT4", "ISRC3INT4"),
+
+       ARIZONA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"),
+       ARIZONA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"),
+       ARIZONA_MUX_ROUTES("ISRC3DEC3", "ISRC3DEC3"),
+       ARIZONA_MUX_ROUTES("ISRC3DEC4", "ISRC3DEC4"),
+
        { "AEC Loopback", "HPOUT1L", "OUT1L" },
        { "AEC Loopback", "HPOUT1R", "OUT1R" },
        { "HPOUT1L", NULL, "OUT1L" },
@@ -1037,7 +1358,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "AEC Loopback", "HPOUT3L", "OUT3L" },
        { "AEC Loopback", "HPOUT3R", "OUT3R" },
        { "HPOUT3L", NULL, "OUT3L" },
-       { "HPOUT3R", NULL, "OUT3L" },
+       { "HPOUT3R", NULL, "OUT3R" },
 
        { "AEC Loopback", "SPKOUTL", "OUT4L" },
        { "SPKOUTLN", NULL, "OUT4L" },
@@ -1120,14 +1441,14 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
                .playback = {
                        .stream_name = "AIF2 Playback",
                        .channels_min = 1,
-                       .channels_max = 2,
+                       .channels_max = 6,
                        .rates = WM5110_RATES,
                        .formats = WM5110_FORMATS,
                },
                .capture = {
                         .stream_name = "AIF2 Capture",
                         .channels_min = 1,
-                        .channels_max = 2,
+                        .channels_max = 6,
                         .rates = WM5110_RATES,
                         .formats = WM5110_FORMATS,
                 },
@@ -1229,6 +1550,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
        arizona_init_spk(codec);
        arizona_init_gpio(codec);
 
+       ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8);
+       if (ret != 0)
+               return ret;
+
        snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
 
        priv->core.arizona->dapm = &codec->dapm;
@@ -1283,7 +1608,7 @@ static int wm5110_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct wm5110_priv *wm5110;
-       int i;
+       int i, ret;
 
        wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv),
                              GFP_KERNEL);
@@ -1294,6 +1619,24 @@ static int wm5110_probe(struct platform_device *pdev)
        wm5110->core.arizona = arizona;
        wm5110->core.num_inputs = 8;
 
+       for (i = 0; i < WM5110_NUM_ADSP; i++) {
+               wm5110->core.adsp[i].part = "wm5110";
+               wm5110->core.adsp[i].num = i + 1;
+               wm5110->core.adsp[i].type = WMFW_ADSP2;
+               wm5110->core.adsp[i].dev = arizona->dev;
+               wm5110->core.adsp[i].regmap = arizona->regmap;
+
+               wm5110->core.adsp[i].base = ARIZONA_DSP1_CONTROL_1
+                       + (0x100 * i);
+               wm5110->core.adsp[i].mem = wm5110_dsp_regions[i];
+               wm5110->core.adsp[i].num_mems
+                       = ARRAY_SIZE(wm5110_dsp1_regions);
+
+               ret = wm_adsp2_init(&wm5110->core.adsp[i], false);
+               if (ret != 0)
+                       return ret;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
                wm5110->fll[i].vco_mult = 3;
 
@@ -1304,6 +1647,12 @@ static int wm5110_probe(struct platform_device *pdev)
                         ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
                         &wm5110->fll[1]);
 
+       /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
+       regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
+                          ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
+       regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
+                          ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
+
        for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++)
                arizona_init_dai(&wm5110->core, i);
 
index 6ed5433943eaae4716f54a75f7b4cf4d9fd83fc2..7df7d45727559e98501eef2500b3cc610ee8a4b0 100644 (file)
@@ -684,7 +684,7 @@ static struct spi_driver wm8510_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8510_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -735,7 +735,7 @@ static struct i2c_driver wm8510_i2c_driver = {
 static int __init wm8510_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8510_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
@@ -755,7 +755,7 @@ module_init(wm8510_modinit);
 
 static void __exit wm8510_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8510_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 139bf9ac94078152470fc639816a328eac8dbfa6..74d106dc76676d5481ae367ad2c5115e8d7df32a 100644 (file)
@@ -452,7 +452,7 @@ static const struct regmap_config wm8523_regmap = {
        .volatile_reg = wm8523_volatile_register,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8523_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -555,7 +555,7 @@ static struct i2c_driver wm8523_i2c_driver = {
 static int __init wm8523_modinit(void)
 {
        int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8523_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n",
@@ -568,7 +568,7 @@ module_init(wm8523_modinit);
 
 static void __exit wm8523_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8523_i2c_driver);
 #endif
 }
index 08a414b57b1ea8179819adc03dd300233f24d72e..318989acbbe5fbb97878856ccab46330422f6bdf 100644 (file)
@@ -941,7 +941,7 @@ static const struct regmap_config wm8580_regmap = {
        .volatile_reg = wm8580_volatile,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8580_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1003,7 +1003,7 @@ static int __init wm8580_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8580_i2c_driver);
        if (ret != 0) {
                pr_err("Failed to register WM8580 I2C driver: %d\n", ret);
@@ -1016,7 +1016,7 @@ module_init(wm8580_modinit);
 
 static void __exit wm8580_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8580_i2c_driver);
 #endif
 }
index 5b428b060d418da78286a605060c4cb4c019801b..d99f948c513cd80bf56f96f6657ce20224f2fb0d 100644 (file)
@@ -469,7 +469,7 @@ static struct spi_driver wm8711_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8711_i2c_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
@@ -520,7 +520,7 @@ static struct i2c_driver wm8711_i2c_driver = {
 static int __init wm8711_modinit(void)
 {
        int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8711_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n",
@@ -540,7 +540,7 @@ module_init(wm8711_modinit);
 
 static void __exit wm8711_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8711_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index c6a292dcded0c11eda10c5dfa8fd70e2be84ec0c..cd89033e84c08a1d290cb012cee545273b35badd 100644 (file)
@@ -320,7 +320,7 @@ static struct spi_driver wm8728_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8728_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -371,7 +371,7 @@ static struct i2c_driver wm8728_i2c_driver = {
 static int __init wm8728_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8728_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n",
@@ -391,7 +391,7 @@ module_init(wm8728_modinit);
 
 static void __exit wm8728_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8728_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 456bb8c6d759176a3bf31c5f7003a6e8cfc2d799..029720366ff8f65f7d6b208216f7cba64b6523af 100644 (file)
@@ -447,10 +447,10 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
                iface |= 0x0001;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               iface |= 0x0003;
+               iface |= 0x0013;
                break;
        case SND_SOC_DAIFMT_DSP_B:
-               iface |= 0x0013;
+               iface |= 0x0003;
                break;
        default:
                return -EINVAL;
@@ -732,7 +732,7 @@ static struct spi_driver wm8731_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8731_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -791,7 +791,7 @@ static struct i2c_driver wm8731_i2c_driver = {
 static int __init wm8731_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8731_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n",
@@ -811,7 +811,7 @@ module_init(wm8731_modinit);
 
 static void __exit wm8731_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8731_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index b18813cc7ba9f06c87b399834abbceac5d3b9f49..2895c8d3b5e4cce600114dcab949f28b82cf2c7e 100644 (file)
@@ -500,7 +500,7 @@ static const struct regmap_config wm8741_regmap = {
        .readable_reg = wm8741_readable,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8741_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -617,7 +617,7 @@ static int __init wm8741_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8741_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
@@ -639,7 +639,7 @@ static void __exit wm8741_exit(void)
 #if defined(CONFIG_SPI_MASTER)
        spi_unregister_driver(&wm8741_spi_driver);
 #endif
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8741_i2c_driver);
 #endif
 }
index 50d5ff616232676bb094054d44a0c1076ddba0ab..78616a638a55ad4a76f11559f08c6dc4bdb708f6 100644 (file)
@@ -816,7 +816,7 @@ static struct spi_driver wm8750_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8750_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -868,7 +868,7 @@ static struct i2c_driver wm8750_i2c_driver = {
 static int __init wm8750_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8750_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n",
@@ -888,7 +888,7 @@ module_init(wm8750_modinit);
 
 static void __exit wm8750_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8750_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index d96ebf52d953e850016184f4615f2faf979a738d..be85da93a2682fb89c7c668042f772fc08ca7452 100644 (file)
@@ -1596,7 +1596,7 @@ static struct spi_driver wm8753_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8753_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1653,7 +1653,7 @@ static struct i2c_driver wm8753_i2c_driver = {
 static int __init wm8753_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8753_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n",
@@ -1673,7 +1673,7 @@ module_init(wm8753_modinit);
 
 static void __exit wm8753_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8753_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 942d58e455f384f9b8c5cdc83363c861ff5366b5..ef824672523206a1a3f5d593647a20ae5487b941 100644 (file)
@@ -532,7 +532,7 @@ static struct spi_driver wm8776_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8776_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -584,7 +584,7 @@ static struct i2c_driver wm8776_i2c_driver = {
 static int __init wm8776_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8776_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n",
@@ -604,7 +604,7 @@ module_init(wm8776_modinit);
 
 static void __exit wm8776_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8776_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 1704b1e119cb021db8fced2be8482c5da40810d9..9bc8206a68071267cbb18856dc5c9722930af147 100644 (file)
@@ -739,7 +739,7 @@ static struct spi_driver wm8804_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8804_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -791,7 +791,7 @@ static int __init wm8804_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8804_i2c_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
@@ -811,7 +811,7 @@ module_init(wm8804_modinit);
 
 static void __exit wm8804_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8804_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 734209e252c3c7cc049b9f982de6539154aa67ab..e98bc7038a086b39231ecbb5196fb7a40fc92d1e 100644 (file)
@@ -1288,7 +1288,7 @@ static struct spi_driver wm8900_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8900_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1338,7 +1338,7 @@ static struct i2c_driver wm8900_i2c_driver = {
 static int __init wm8900_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8900_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n",
@@ -1358,7 +1358,7 @@ module_init(wm8900_modinit);
 
 static void __exit wm8900_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8900_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 3938fb1c203ed86b5452ff130071d349a6821a87..53bbfac6a83ad14ed43d2aafca2514ea3a319468 100644 (file)
@@ -1444,7 +1444,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
-               aif1 |= WM8904_AIF_LRCLK_INV;
+               aif1 |= 0x3 | WM8904_AIF_LRCLK_INV;
        case SND_SOC_DAIFMT_DSP_A:
                aif1 |= 0x3;
                break;
index b1591c61c254ebc1f12d0a19e682e45df632ed77..b404c26c1753407c849c61fdc5ac2db5254deaf0 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 struct wm8940_priv {
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
 };
 
-static int wm8940_volatile_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool wm8940_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8940_SOFTRESET:
-               return 1;
+               return true;
        default:
-               return 0;
+               return false;
+       }
+}
+
+static bool wm8940_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8940_SOFTRESET:
+       case WM8940_POWER1:
+       case WM8940_POWER2:
+       case WM8940_POWER3:
+       case WM8940_IFACE:
+       case WM8940_COMPANDINGCTL:
+       case WM8940_CLOCK:
+       case WM8940_ADDCNTRL:
+       case WM8940_GPIO:
+       case WM8940_CTLINT:
+       case WM8940_DAC:
+       case WM8940_DACVOL:
+       case WM8940_ADC:
+       case WM8940_ADCVOL:
+       case WM8940_NOTCH1:
+       case WM8940_NOTCH2:
+       case WM8940_NOTCH3:
+       case WM8940_NOTCH4:
+       case WM8940_NOTCH5:
+       case WM8940_NOTCH6:
+       case WM8940_NOTCH7:
+       case WM8940_NOTCH8:
+       case WM8940_DACLIM1:
+       case WM8940_DACLIM2:
+       case WM8940_ALC1:
+       case WM8940_ALC2:
+       case WM8940_ALC3:
+       case WM8940_NOISEGATE:
+       case WM8940_PLLN:
+       case WM8940_PLLK1:
+       case WM8940_PLLK2:
+       case WM8940_PLLK3:
+       case WM8940_ALC4:
+       case WM8940_INPUTCTL:
+       case WM8940_PGAGAIN:
+       case WM8940_ADCBOOST:
+       case WM8940_OUTPUTCTL:
+       case WM8940_SPKMIX:
+       case WM8940_SPKVOL:
+       case WM8940_MONOMIX:
+               return true;
+       default:
+               return false;
        }
 }
 
-static u16 wm8940_reg_defaults[] = {
-       0x8940, /* Soft Reset */
-       0x0000, /* Power 1 */
-       0x0000, /* Power 2 */
-       0x0000, /* Power 3 */
-       0x0010, /* Interface Control */
-       0x0000, /* Companding Control */
-       0x0140, /* Clock Control */
-       0x0000, /* Additional Controls */
-       0x0000, /* GPIO Control */
-       0x0002, /* Auto Increment Control */
-       0x0000, /* DAC Control */
-       0x00FF, /* DAC Volume */
-       0,
-       0,
-       0x0100, /* ADC Control */
-       0x00FF, /* ADC Volume */
-       0x0000, /* Notch Filter 1 Control 1 */
-       0x0000, /* Notch Filter 1 Control 2 */
-       0x0000, /* Notch Filter 2 Control 1 */
-       0x0000, /* Notch Filter 2 Control 2 */
-       0x0000, /* Notch Filter 3 Control 1 */
-       0x0000, /* Notch Filter 3 Control 2 */
-       0x0000, /* Notch Filter 4 Control 1 */
-       0x0000, /* Notch Filter 4 Control 2 */
-       0x0032, /* DAC Limit Control 1 */
-       0x0000, /* DAC Limit Control 2 */
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0x0038, /* ALC Control 1 */
-       0x000B, /* ALC Control 2 */
-       0x0032, /* ALC Control 3 */
-       0x0000, /* Noise Gate */
-       0x0041, /* PLLN */
-       0x000C, /* PLLK1 */
-       0x0093, /* PLLK2 */
-       0x00E9, /* PLLK3 */
-       0,
-       0,
-       0x0030, /* ALC Control 4 */
-       0,
-       0x0002, /* Input Control */
-       0x0050, /* PGA Gain */
-       0,
-       0x0002, /* ADC Boost Control */
-       0,
-       0x0002, /* Output Control */
-       0x0000, /* Speaker Mixer Control */
-       0,
-       0,
-       0,
-       0x0079, /* Speaker Volume */
-       0,
-       0x0000, /* Mono Mixer Control */
+static const struct reg_default wm8940_reg_defaults[] = {
+       {  0x1, 0x0000 }, /* Power 1 */
+       {  0x2, 0x0000 }, /* Power 2 */
+       {  0x3, 0x0000 }, /* Power 3 */
+       {  0x4, 0x0010 }, /* Interface Control */
+       {  0x5, 0x0000 }, /* Companding Control */
+       {  0x6, 0x0140 }, /* Clock Control */
+       {  0x7, 0x0000 }, /* Additional Controls */
+       {  0x8, 0x0000 }, /* GPIO Control */
+       {  0x9, 0x0002 }, /* Auto Increment Control */
+       {  0xa, 0x0000 }, /* DAC Control */
+       {  0xb, 0x00FF }, /* DAC Volume */
+
+       {  0xe, 0x0100 }, /* ADC Control */
+       {  0xf, 0x00FF }, /* ADC Volume */
+       { 0x10, 0x0000 }, /* Notch Filter 1 Control 1 */
+       { 0x11, 0x0000 }, /* Notch Filter 1 Control 2 */
+       { 0x12, 0x0000 }, /* Notch Filter 2 Control 1 */
+       { 0x13, 0x0000 }, /* Notch Filter 2 Control 2 */
+       { 0x14, 0x0000 }, /* Notch Filter 3 Control 1 */
+       { 0x15, 0x0000 }, /* Notch Filter 3 Control 2 */
+       { 0x16, 0x0000 }, /* Notch Filter 4 Control 1 */
+       { 0x17, 0x0000 }, /* Notch Filter 4 Control 2 */
+       { 0x18, 0x0032 }, /* DAC Limit Control 1 */
+       { 0x19, 0x0000 }, /* DAC Limit Control 2 */
+
+       { 0x20, 0x0038 }, /* ALC Control 1 */
+       { 0x21, 0x000B }, /* ALC Control 2 */
+       { 0x22, 0x0032 }, /* ALC Control 3 */
+       { 0x23, 0x0000 }, /* Noise Gate */
+       { 0x24, 0x0041 }, /* PLLN */
+       { 0x25, 0x000C }, /* PLLK1 */
+       { 0x26, 0x0093 }, /* PLLK2 */
+       { 0x27, 0x00E9 }, /* PLLK3 */
+
+       { 0x2a, 0x0030 }, /* ALC Control 4 */
+
+       { 0x2c, 0x0002 }, /* Input Control */
+       { 0x2d, 0x0050 }, /* PGA Gain */
+
+       { 0x2f, 0x0002 }, /* ADC Boost Control */
+
+       { 0x31, 0x0002 }, /* Output Control */
+       { 0x32, 0x0000 }, /* Speaker Mixer Control */
+
+       { 0x36, 0x0079 }, /* Speaker Volume */
+
+       { 0x38, 0x0000 }, /* Mono Mixer Control */
 };
 
 static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
@@ -264,7 +302,7 @@ static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("AUX"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8940_dapm_routes[] = {
        /* Mono output mixer */
        {"Mono Mixer", "PCM Playback Switch", "DAC"},
        {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -296,21 +334,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"ADC", NULL, "Boost Mixer"},
 };
 
-static int wm8940_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
-
-       ret = snd_soc_dapm_new_controls(dapm, wm8940_dapm_widgets,
-                                       ARRAY_SIZE(wm8940_dapm_widgets));
-       if (ret)
-               goto error_ret;
-       ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-error_ret:
-       return ret;
-}
-
 #define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0);
 
 static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -446,6 +469,7 @@ static int wm8940_mute(struct snd_soc_dai *dai, int mute)
 static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
        u16 val;
        u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0;
        int ret = 0;
@@ -469,7 +493,7 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                break;
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = snd_soc_cache_sync(codec);
+                       ret = regcache_sync(wm8940->regmap);
                        if (ret < 0) {
                                dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
                                return ret;
@@ -684,12 +708,11 @@ static int wm8940_resume(struct snd_soc_codec *codec)
 
 static int wm8940_probe(struct snd_soc_codec *codec)
 {
-       struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
        struct wm8940_setup_data *pdata = codec->dev->platform_data;
        int ret;
        u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -716,11 +739,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
                        return ret;
        }
 
-       ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
-                            ARRAY_SIZE(wm8940_snd_controls));
-       if (ret)
-               return ret;
-       ret = wm8940_add_widgets(codec);
        return ret;
 }
 
@@ -736,10 +754,24 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
        .suspend =      wm8940_suspend,
        .resume =       wm8940_resume,
        .set_bias_level = wm8940_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8940_reg_defaults,
-       .volatile_register = wm8940_volatile_register,
+       .controls =     wm8940_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8940_snd_controls),
+       .dapm_widgets = wm8940_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets),
+       .dapm_routes =  wm8940_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes),
+};
+
+static const struct regmap_config wm8940_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8940_MONOMIX,
+       .reg_defaults = wm8940_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8940_reg_defaults),
+
+       .readable_reg = wm8940_readable_register,
+       .volatile_reg = wm8940_volatile_register,
 };
 
 static int wm8940_i2c_probe(struct i2c_client *i2c,
@@ -753,8 +785,11 @@ static int wm8940_i2c_probe(struct i2c_client *i2c,
        if (wm8940 == NULL)
                return -ENOMEM;
 
+       wm8940->regmap = devm_regmap_init_i2c(i2c, &wm8940_regmap);
+       if (IS_ERR(wm8940->regmap))
+               return PTR_ERR(wm8940->regmap);
+
        i2c_set_clientdata(i2c, wm8940);
-       wm8940->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8940, &wm8940_dai, 1);
index 543c5c2631b61827bcebca8af1926ea02b5655e9..97db3b45b4113ad5fe7f7d42dd0e4e018b8c8c51 100644 (file)
@@ -74,7 +74,7 @@ struct wm8962_priv {
        struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8962_NUM_SUPPLIES];
 
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
        struct input_dev *beep;
        struct work_struct beep_work;
        int beep_rate;
@@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8962_CLOCKING_4,
                            WM8962_SYSCLK_RATE_MASK, clocking4);
 
+       /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK.
+        * So we here provisionally enable it and then disable it afterward
+        * if current bias_level hasn't reached SND_SOC_BIAS_ON.
+        */
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
+
        dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, 0);
+
        if (dspclk < 0) {
                dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
                return;
@@ -3108,7 +3121,7 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
 }
 EXPORT_SYMBOL_GPL(wm8962_mic_detect);
 
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
 static int beep_rates[] = {
        500, 1000, 2000, 4000,
 };
index a2d01d10a5dd8866747b335a027ed3049c9c71d3..15f45c7bd8334971bb63235ade92a26cb82c2f57 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 #include "wm8974.h"
 
-static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0050, 0x0000, 0x0140, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x00ff,
-       0x0000, 0x0000, 0x0100, 0x00ff,
-       0x0000, 0x0000, 0x012c, 0x002c,
-       0x002c, 0x002c, 0x002c, 0x0000,
-       0x0032, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0038, 0x000b, 0x0032, 0x0000,
-       0x0008, 0x000c, 0x0093, 0x00e9,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0003, 0x0010, 0x0000, 0x0000,
-       0x0000, 0x0002, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0039, 0x0000,
-       0x0000,
+static const struct reg_default wm8974_reg_defaults[] = {
+       {  0, 0x0000 }, {  1, 0x0000 }, {  2, 0x0000 }, {  3, 0x0000 },
+       {  4, 0x0050 }, {  5, 0x0000 }, {  6, 0x0140 }, {  7, 0x0000 },
+       {  8, 0x0000 }, {  9, 0x0000 }, { 10, 0x0000 }, { 11, 0x00ff },
+       { 12, 0x0000 }, { 13, 0x0000 }, { 14, 0x0100 }, { 15, 0x00ff },
+       { 16, 0x0000 }, { 17, 0x0000 }, { 18, 0x012c }, { 19, 0x002c },
+       { 20, 0x002c }, { 21, 0x002c }, { 22, 0x002c }, { 23, 0x0000 },
+       { 24, 0x0032 }, { 25, 0x0000 }, { 26, 0x0000 }, { 27, 0x0000 },
+       { 28, 0x0000 }, { 29, 0x0000 }, { 30, 0x0000 }, { 31, 0x0000 },
+       { 32, 0x0038 }, { 33, 0x000b }, { 34, 0x0032 }, { 35, 0x0000 },
+       { 36, 0x0008 }, { 37, 0x000c }, { 38, 0x0093 }, { 39, 0x00e9 },
+       { 40, 0x0000 }, { 41, 0x0000 }, { 42, 0x0000 }, { 43, 0x0000 },
+       { 44, 0x0003 }, { 45, 0x0010 }, { 46, 0x0000 }, { 47, 0x0000 },
+       { 48, 0x0000 }, { 49, 0x0002 }, { 50, 0x0000 }, { 51, 0x0000 },
+       { 52, 0x0000 }, { 53, 0x0000 }, { 54, 0x0039 }, { 55, 0x0000 },
+       { 56, 0x0000 },
 };
 
 #define WM8974_POWER1_BIASEN  0x08
@@ -514,7 +515,7 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
                power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
 
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(dev_get_regmap(codec->dev, NULL));
 
                        /* Initial cap charge at VMID 5k */
                        snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
@@ -579,11 +580,20 @@ static int wm8974_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
+static const struct regmap_config wm8974_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8974_MONOMIX,
+       .reg_defaults = wm8974_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8974_reg_defaults),
+};
+
 static int wm8974_probe(struct snd_soc_codec *codec)
 {
        int ret = 0;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -613,9 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
        .suspend =      wm8974_suspend,
        .resume =       wm8974_resume,
        .set_bias_level = wm8974_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8974_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8974_reg,
 
        .controls = wm8974_snd_controls,
        .num_controls = ARRAY_SIZE(wm8974_snd_controls),
@@ -628,8 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
 static int wm8974_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
+       struct regmap *regmap;
        int ret;
 
+       regmap = devm_regmap_init_i2c(i2c, &wm8974_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8974, &wm8974_dai, 1);
 
index 18f2babe1090bf0ee061cf169c5f0f8e867dafd3..271b517911a4bc0d4d6003356afcf7a1cc317bed 100644 (file)
@@ -1148,7 +1148,7 @@ static struct spi_driver wm8985_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8985_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1201,7 +1201,7 @@ static int __init wm8985_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8985_i2c_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n",
@@ -1221,7 +1221,7 @@ module_init(wm8985_modinit);
 
 static void __exit wm8985_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8985_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 39b9acceb595185d60821270073d9e5895305baa..a55e1c2c382edde43985e2213f0502564bf8e17b 100644 (file)
@@ -912,7 +912,7 @@ static struct spi_driver wm8988_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8988_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -964,7 +964,7 @@ static struct i2c_driver wm8988_i2c_driver = {
 static int __init wm8988_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8988_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n",
@@ -984,7 +984,7 @@ module_init(wm8988_modinit);
 
 static void __exit wm8988_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8988_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 253c88bb7a4cbdb06d3d1df2862f10e80095aaa8..0ccd4d8d043bbcf0d0f689bc947c93545d88b16b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 /* codec private data */
 struct wm8990_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        unsigned int sysclk;
        unsigned int pcmclk;
 };
 
-static int wm8990_volatile_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool wm8990_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8990_RESET:
@@ -46,71 +46,69 @@ static int wm8990_volatile_register(struct snd_soc_codec *codec,
        }
 }
 
-static const u16 wm8990_reg[] = {
-       0x8990,     /* R0  - Reset */
-       0x0000,     /* R1  - Power Management (1) */
-       0x6000,     /* R2  - Power Management (2) */
-       0x0000,     /* R3  - Power Management (3) */
-       0x4050,     /* R4  - Audio Interface (1) */
-       0x4000,     /* R5  - Audio Interface (2) */
-       0x01C8,     /* R6  - Clocking (1) */
-       0x0000,     /* R7  - Clocking (2) */
-       0x0040,     /* R8  - Audio Interface (3) */
-       0x0040,     /* R9  - Audio Interface (4) */
-       0x0004,     /* R10 - DAC CTRL */
-       0x00C0,     /* R11 - Left DAC Digital Volume */
-       0x00C0,     /* R12 - Right DAC Digital Volume */
-       0x0000,     /* R13 - Digital Side Tone */
-       0x0100,     /* R14 - ADC CTRL */
-       0x00C0,     /* R15 - Left ADC Digital Volume */
-       0x00C0,     /* R16 - Right ADC Digital Volume */
-       0x0000,     /* R17 */
-       0x0000,     /* R18 - GPIO CTRL 1 */
-       0x1000,     /* R19 - GPIO1 & GPIO2 */
-       0x1010,     /* R20 - GPIO3 & GPIO4 */
-       0x1010,     /* R21 - GPIO5 & GPIO6 */
-       0x8000,     /* R22 - GPIOCTRL 2 */
-       0x0800,     /* R23 - GPIO_POL */
-       0x008B,     /* R24 - Left Line Input 1&2 Volume */
-       0x008B,     /* R25 - Left Line Input 3&4 Volume */
-       0x008B,     /* R26 - Right Line Input 1&2 Volume */
-       0x008B,     /* R27 - Right Line Input 3&4 Volume */
-       0x0000,     /* R28 - Left Output Volume */
-       0x0000,     /* R29 - Right Output Volume */
-       0x0066,     /* R30 - Line Outputs Volume */
-       0x0022,     /* R31 - Out3/4 Volume */
-       0x0079,     /* R32 - Left OPGA Volume */
-       0x0079,     /* R33 - Right OPGA Volume */
-       0x0003,     /* R34 - Speaker Volume */
-       0x0003,     /* R35 - ClassD1 */
-       0x0000,     /* R36 */
-       0x0100,     /* R37 - ClassD3 */
-       0x0079,     /* R38 - ClassD4 */
-       0x0000,     /* R39 - Input Mixer1 */
-       0x0000,     /* R40 - Input Mixer2 */
-       0x0000,     /* R41 - Input Mixer3 */
-       0x0000,     /* R42 - Input Mixer4 */
-       0x0000,     /* R43 - Input Mixer5 */
-       0x0000,     /* R44 - Input Mixer6 */
-       0x0000,     /* R45 - Output Mixer1 */
-       0x0000,     /* R46 - Output Mixer2 */
-       0x0000,     /* R47 - Output Mixer3 */
-       0x0000,     /* R48 - Output Mixer4 */
-       0x0000,     /* R49 - Output Mixer5 */
-       0x0000,     /* R50 - Output Mixer6 */
-       0x0180,     /* R51 - Out3/4 Mixer */
-       0x0000,     /* R52 - Line Mixer1 */
-       0x0000,     /* R53 - Line Mixer2 */
-       0x0000,     /* R54 - Speaker Mixer */
-       0x0000,     /* R55 - Additional Control */
-       0x0000,     /* R56 - AntiPOP1 */
-       0x0000,     /* R57 - AntiPOP2 */
-       0x0000,     /* R58 - MICBIAS */
-       0x0000,     /* R59 */
-       0x0008,     /* R60 - PLL1 */
-       0x0031,     /* R61 - PLL2 */
-       0x0026,     /* R62 - PLL3 */
-       0x0000,     /* R63 - Driver internal */
+static const struct reg_default wm8990_reg_defaults[] = {
+       {  1, 0x0000 },     /* R1  - Power Management (1) */
+       {  2, 0x6000 },     /* R2  - Power Management (2) */
+       {  3, 0x0000 },     /* R3  - Power Management (3) */
+       {  4, 0x4050 },     /* R4  - Audio Interface (1) */
+       {  5, 0x4000 },     /* R5  - Audio Interface (2) */
+       {  6, 0x01C8 },     /* R6  - Clocking (1) */
+       {  7, 0x0000 },     /* R7  - Clocking (2) */
+       {  8, 0x0040 },     /* R8  - Audio Interface (3) */
+       {  9, 0x0040 },     /* R9  - Audio Interface (4) */
+       { 10, 0x0004 },     /* R10 - DAC CTRL */
+       { 11, 0x00C0 },     /* R11 - Left DAC Digital Volume */
+       { 12, 0x00C0 },     /* R12 - Right DAC Digital Volume */
+       { 13, 0x0000 },     /* R13 - Digital Side Tone */
+       { 14, 0x0100 },     /* R14 - ADC CTRL */
+       { 15, 0x00C0 },     /* R15 - Left ADC Digital Volume */
+       { 16, 0x00C0 },     /* R16 - Right ADC Digital Volume */
+
+       { 18, 0x0000 },     /* R18 - GPIO CTRL 1 */
+       { 19, 0x1000 },     /* R19 - GPIO1 & GPIO2 */
+       { 20, 0x1010 },     /* R20 - GPIO3 & GPIO4 */
+       { 21, 0x1010 },     /* R21 - GPIO5 & GPIO6 */
+       { 22, 0x8000 },     /* R22 - GPIOCTRL 2 */
+       { 23, 0x0800 },     /* R23 - GPIO_POL */
+       { 24, 0x008B },     /* R24 - Left Line Input 1&2 Volume */
+       { 25, 0x008B },     /* R25 - Left Line Input 3&4 Volume */
+       { 26, 0x008B },     /* R26 - Right Line Input 1&2 Volume */
+       { 27, 0x008B },     /* R27 - Right Line Input 3&4 Volume */
+       { 28, 0x0000 },     /* R28 - Left Output Volume */
+       { 29, 0x0000 },     /* R29 - Right Output Volume */
+       { 30, 0x0066 },     /* R30 - Line Outputs Volume */
+       { 31, 0x0022 },     /* R31 - Out3/4 Volume */
+       { 32, 0x0079 },     /* R32 - Left OPGA Volume */
+       { 33, 0x0079 },     /* R33 - Right OPGA Volume */
+       { 34, 0x0003 },     /* R34 - Speaker Volume */
+       { 35, 0x0003 },     /* R35 - ClassD1 */
+
+       { 37, 0x0100 },     /* R37 - ClassD3 */
+       { 38, 0x0079 },     /* R38 - ClassD4 */
+       { 39, 0x0000 },     /* R39 - Input Mixer1 */
+       { 40, 0x0000 },     /* R40 - Input Mixer2 */
+       { 41, 0x0000 },     /* R41 - Input Mixer3 */
+       { 42, 0x0000 },     /* R42 - Input Mixer4 */
+       { 43, 0x0000 },     /* R43 - Input Mixer5 */
+       { 44, 0x0000 },     /* R44 - Input Mixer6 */
+       { 45, 0x0000 },     /* R45 - Output Mixer1 */
+       { 46, 0x0000 },     /* R46 - Output Mixer2 */
+       { 47, 0x0000 },     /* R47 - Output Mixer3 */
+       { 48, 0x0000 },     /* R48 - Output Mixer4 */
+       { 49, 0x0000 },     /* R49 - Output Mixer5 */
+       { 50, 0x0000 },     /* R50 - Output Mixer6 */
+       { 51, 0x0180 },     /* R51 - Out3/4 Mixer */
+       { 52, 0x0000 },     /* R52 - Line Mixer1 */
+       { 53, 0x0000 },     /* R53 - Line Mixer2 */
+       { 54, 0x0000 },     /* R54 - Speaker Mixer */
+       { 55, 0x0000 },     /* R55 - Additional Control */
+       { 56, 0x0000 },     /* R56 - AntiPOP1 */
+       { 57, 0x0000 },     /* R57 - AntiPOP2 */
+       { 58, 0x0000 },     /* R58 - MICBIAS */
+
+       { 60, 0x0008 },     /* R60 - PLL1 */
+       { 61, 0x0031 },     /* R61 - PLL2 */
+       { 62, 0x0026 },     /* R62 - PLL3 */
 };
 
 #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
@@ -376,32 +374,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
  * _DAPM_ Controls
  */
 
-static int inmixer_event(struct snd_soc_dapm_widget *w,
-       struct snd_kcontrol *kcontrol, int event)
-{
-       u16 reg, fakepower;
-
-       reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2);
-       fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS);
-
-       if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
-               (1 << WM8990_AINLMUX_PWR_BIT))) {
-               reg |= WM8990_AINL_ENA;
-       } else {
-               reg &= ~WM8990_AINL_ENA;
-       }
-
-       if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) |
-               (1 << WM8990_AINRMUX_PWR_BIT))) {
-               reg |= WM8990_AINR_ENA;
-       } else {
-               reg &= ~WM8990_AINR_ENA;
-       }
-       snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
-
-       return 0;
-}
-
 static int outmixer_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
@@ -656,6 +628,11 @@ SND_SOC_DAPM_INPUT("RIN1"),
 SND_SOC_DAPM_INPUT("RIN2"),
 SND_SOC_DAPM_INPUT("Internal ADC Source"),
 
+SND_SOC_DAPM_SUPPLY("INL", WM8990_POWER_MANAGEMENT_2, WM8990_AINL_ENA_BIT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("INR", WM8990_POWER_MANAGEMENT_2, WM8990_AINR_ENA_BIT, 0,
+                   NULL, 0),
+
 /* DACs */
 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2,
        WM8990_ADCL_ENA_BIT, 0),
@@ -677,26 +654,20 @@ SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT,
        ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)),
 
 /* INMIXL */
-SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
+SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
        &wm8990_dapm_inmixl_controls[0],
-       ARRAY_SIZE(wm8990_dapm_inmixl_controls),
-       inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       ARRAY_SIZE(wm8990_dapm_inmixl_controls)),
 
 /* AINLMUX */
-SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
-       &wm8990_dapm_ainlmux_controls, inmixer_event,
-       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0, &wm8990_dapm_ainlmux_controls),
 
 /* INMIXR */
-SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
+SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
        &wm8990_dapm_inmixr_controls[0],
-       ARRAY_SIZE(wm8990_dapm_inmixr_controls),
-       inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       ARRAY_SIZE(wm8990_dapm_inmixr_controls)),
 
 /* AINRMUX */
-SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
-       &wm8990_dapm_ainrmux_controls, inmixer_event,
-       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0, &wm8990_dapm_ainrmux_controls),
 
 /* Output Side */
 /* DACs */
@@ -787,7 +758,7 @@ SND_SOC_DAPM_OUTPUT("RON"),
 SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8990_dapm_routes[] = {
        /* Make DACs turn on when playing even if not mixed into any outputs */
        {"Internal DAC Sink", NULL, "Left DAC"},
        {"Internal DAC Sink", NULL, "Right DAC"},
@@ -796,6 +767,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Left ADC", NULL, "Internal ADC Source"},
        {"Right ADC", NULL, "Internal ADC Source"},
 
+       {"AINLMUX", NULL, "INL"},
+       {"INMIXL", NULL, "INL"},
+       {"AINRMUX", NULL, "INR"},
+       {"INMIXR", NULL, "INR"},
+
        /* Input Side */
        /* LIN12 PGA */
        {"LIN12 PGA", "LIN1 Switch", "LIN1"},
@@ -912,18 +888,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"RON", NULL, "RONMIX"},
 };
 
-static int wm8990_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8990_dapm_widgets,
-                                 ARRAY_SIZE(wm8990_dapm_widgets));
-       /* set up the WM8990 audio map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 /* PLL divisors */
 struct _pll_div {
        u32 div2;
@@ -1148,6 +1112,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
 static int wm8990_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
        switch (level) {
@@ -1162,7 +1127,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = snd_soc_cache_sync(codec);
+                       ret = regcache_sync(wm8990->regmap);
                        if (ret < 0) {
                                dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
                                return ret;
@@ -1259,6 +1224,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
                snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
+
+               regcache_mark_dirty(wm8990->regmap);
                break;
        }
 
@@ -1327,7 +1294,7 @@ static int wm8990_probe(struct snd_soc_codec *codec)
 {
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -1350,10 +1317,6 @@ static int wm8990_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-       snd_soc_add_codec_controls(codec, wm8990_snd_controls,
-                               ARRAY_SIZE(wm8990_snd_controls));
-       wm8990_add_widgets(codec);
-
        return 0;
 }
 
@@ -1370,13 +1333,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
        .suspend =      wm8990_suspend,
        .resume =       wm8990_resume,
        .set_bias_level = wm8990_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8990_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8990_reg,
-       .volatile_register = wm8990_volatile_register,
+       .controls =     wm8990_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8990_snd_controls),
+       .dapm_widgets = wm8990_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets),
+       .dapm_routes =  wm8990_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes),
+};
+
+static const struct regmap_config wm8990_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8990_PLL3,
+       .volatile_reg = wm8990_volatile_register,
+       .reg_defaults = wm8990_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8990_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int wm8990_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1418,29 +1393,8 @@ static struct i2c_driver wm8990_i2c_driver = {
        .remove =   wm8990_i2c_remove,
        .id_table = wm8990_i2c_id,
 };
-#endif
 
-static int __init wm8990_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&wm8990_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n",
-                      ret);
-       }
-#endif
-       return ret;
-}
-module_init(wm8990_modinit);
-
-static void __exit wm8990_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&wm8990_i2c_driver);
-#endif
-}
-module_exit(wm8990_exit);
+module_i2c_driver(wm8990_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8990 driver");
 MODULE_AUTHOR("Liam Girdwood");
index 77c98a4bfe9cdf34876e30866e73046d50748c85..0e9c78040c4c5cbfd1c7c6d5cc9cf844e5d95333 100644 (file)
@@ -78,7 +78,6 @@
 #define WM8990_PLL1                             0x3C
 #define WM8990_PLL2                             0x3D
 #define WM8990_PLL3                             0x3E
-#define WM8990_INTDRIVBITS                     0x3F
 
 #define WM8990_EXT_ACCESS_ENA                  0x75
 #define WM8990_EXT_CTL1                                0x7a
  */
 #define WM8990_PLLK2_MASK                       0x00FF  /* PLLK2 - [7:0] */
 
-/*
- * R63 (0x3F) - Internal Driver Bits
- */
-#define WM8990_INMIXL_PWR_BIT                  0
-#define WM8990_AINLMUX_PWR_BIT                 1
-#define WM8990_INMIXR_PWR_BIT                  2
-#define WM8990_AINRMUX_PWR_BIT                 3
-
 #define WM8990_MCLK_DIV 0
 #define WM8990_DACCLK_DIV 1
 #define WM8990_ADCCLK_DIV 2
index 3a39df7a38295a36a28d7865405cb7c0096089d1..dba0306c42a5c54aa459cc4fe1593b08c92a5abf 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include "wm8991.h"
 
 struct wm8991_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        unsigned int pcmclk;
 };
 
-static const u16 wm8991_reg_defs[] = {
-       0x8991,     /* R0  - Reset */
-       0x0000,     /* R1  - Power Management (1) */
-       0x6000,     /* R2  - Power Management (2) */
-       0x0000,     /* R3  - Power Management (3) */
-       0x4050,     /* R4  - Audio Interface (1) */
-       0x4000,     /* R5  - Audio Interface (2) */
-       0x01C8,     /* R6  - Clocking (1) */
-       0x0000,     /* R7  - Clocking (2) */
-       0x0040,     /* R8  - Audio Interface (3) */
-       0x0040,     /* R9  - Audio Interface (4) */
-       0x0004,     /* R10 - DAC CTRL */
-       0x00C0,     /* R11 - Left DAC Digital Volume */
-       0x00C0,     /* R12 - Right DAC Digital Volume */
-       0x0000,     /* R13 - Digital Side Tone */
-       0x0100,     /* R14 - ADC CTRL */
-       0x00C0,     /* R15 - Left ADC Digital Volume */
-       0x00C0,     /* R16 - Right ADC Digital Volume */
-       0x0000,     /* R17 */
-       0x0000,     /* R18 - GPIO CTRL 1 */
-       0x1000,     /* R19 - GPIO1 & GPIO2 */
-       0x1010,     /* R20 - GPIO3 & GPIO4 */
-       0x1010,     /* R21 - GPIO5 & GPIO6 */
-       0x8000,     /* R22 - GPIOCTRL 2 */
-       0x0800,     /* R23 - GPIO_POL */
-       0x008B,     /* R24 - Left Line Input 1&2 Volume */
-       0x008B,     /* R25 - Left Line Input 3&4 Volume */
-       0x008B,     /* R26 - Right Line Input 1&2 Volume */
-       0x008B,     /* R27 - Right Line Input 3&4 Volume */
-       0x0000,     /* R28 - Left Output Volume */
-       0x0000,     /* R29 - Right Output Volume */
-       0x0066,     /* R30 - Line Outputs Volume */
-       0x0022,     /* R31 - Out3/4 Volume */
-       0x0079,     /* R32 - Left OPGA Volume */
-       0x0079,     /* R33 - Right OPGA Volume */
-       0x0003,     /* R34 - Speaker Volume */
-       0x0003,     /* R35 - ClassD1 */
-       0x0000,     /* R36 */
-       0x0100,     /* R37 - ClassD3 */
-       0x0000,     /* R38 */
-       0x0000,     /* R39 - Input Mixer1 */
-       0x0000,     /* R40 - Input Mixer2 */
-       0x0000,     /* R41 - Input Mixer3 */
-       0x0000,     /* R42 - Input Mixer4 */
-       0x0000,     /* R43 - Input Mixer5 */
-       0x0000,     /* R44 - Input Mixer6 */
-       0x0000,     /* R45 - Output Mixer1 */
-       0x0000,     /* R46 - Output Mixer2 */
-       0x0000,     /* R47 - Output Mixer3 */
-       0x0000,     /* R48 - Output Mixer4 */
-       0x0000,     /* R49 - Output Mixer5 */
-       0x0000,     /* R50 - Output Mixer6 */
-       0x0180,     /* R51 - Out3/4 Mixer */
-       0x0000,     /* R52 - Line Mixer1 */
-       0x0000,     /* R53 - Line Mixer2 */
-       0x0000,     /* R54 - Speaker Mixer */
-       0x0000,     /* R55 - Additional Control */
-       0x0000,     /* R56 - AntiPOP1 */
-       0x0000,     /* R57 - AntiPOP2 */
-       0x0000,     /* R58 - MICBIAS */
-       0x0000,     /* R59 */
-       0x0008,     /* R60 - PLL1 */
-       0x0031,     /* R61 - PLL2 */
-       0x0026,     /* R62 - PLL3 */
+static const struct reg_default wm8991_reg_defaults[] = {
+       {  1, 0x0000 },     /* R1  - Power Management (1) */
+       {  2, 0x6000 },     /* R2  - Power Management (2) */
+       {  3, 0x0000 },     /* R3  - Power Management (3) */
+       {  4, 0x4050 },     /* R4  - Audio Interface (1) */
+       {  5, 0x4000 },     /* R5  - Audio Interface (2) */
+       {  6, 0x01C8 },     /* R6  - Clocking (1) */
+       {  7, 0x0000 },     /* R7  - Clocking (2) */
+       {  8, 0x0040 },     /* R8  - Audio Interface (3) */
+       {  9, 0x0040 },     /* R9  - Audio Interface (4) */
+       { 10, 0x0004 },     /* R10 - DAC CTRL */
+       { 11, 0x00C0 },     /* R11 - Left DAC Digital Volume */
+       { 12, 0x00C0 },     /* R12 - Right DAC Digital Volume */
+       { 13, 0x0000 },     /* R13 - Digital Side Tone */
+       { 14, 0x0100 },     /* R14 - ADC CTRL */
+       { 15, 0x00C0 },     /* R15 - Left ADC Digital Volume */
+       { 16, 0x00C0 },     /* R16 - Right ADC Digital Volume */
+
+       { 18, 0x0000 },     /* R18 - GPIO CTRL 1 */
+       { 19, 0x1000 },     /* R19 - GPIO1 & GPIO2 */
+       { 20, 0x1010 },     /* R20 - GPIO3 & GPIO4 */
+       { 21, 0x1010 },     /* R21 - GPIO5 & GPIO6 */
+       { 22, 0x8000 },     /* R22 - GPIOCTRL 2 */
+       { 23, 0x0800 },     /* R23 - GPIO_POL */
+       { 24, 0x008B },     /* R24 - Left Line Input 1&2 Volume */
+       { 25, 0x008B },     /* R25 - Left Line Input 3&4 Volume */
+       { 26, 0x008B },     /* R26 - Right Line Input 1&2 Volume */
+       { 27, 0x008B },     /* R27 - Right Line Input 3&4 Volume */
+       { 28, 0x0000 },     /* R28 - Left Output Volume */
+       { 29, 0x0000 },     /* R29 - Right Output Volume */
+       { 30, 0x0066 },     /* R30 - Line Outputs Volume */
+       { 31, 0x0022 },     /* R31 - Out3/4 Volume */
+       { 32, 0x0079 },     /* R32 - Left OPGA Volume */
+       { 33, 0x0079 },     /* R33 - Right OPGA Volume */
+       { 34, 0x0003 },     /* R34 - Speaker Volume */
+       { 35, 0x0003 },     /* R35 - ClassD1 */
+
+       { 37, 0x0100 },     /* R37 - ClassD3 */
+
+       { 39, 0x0000 },     /* R39 - Input Mixer1 */
+       { 40, 0x0000 },     /* R40 - Input Mixer2 */
+       { 41, 0x0000 },     /* R41 - Input Mixer3 */
+       { 42, 0x0000 },     /* R42 - Input Mixer4 */
+       { 43, 0x0000 },     /* R43 - Input Mixer5 */
+       { 44, 0x0000 },     /* R44 - Input Mixer6 */
+       { 45, 0x0000 },     /* R45 - Output Mixer1 */
+       { 46, 0x0000 },     /* R46 - Output Mixer2 */
+       { 47, 0x0000 },     /* R47 - Output Mixer3 */
+       { 48, 0x0000 },     /* R48 - Output Mixer4 */
+       { 49, 0x0000 },     /* R49 - Output Mixer5 */
+       { 50, 0x0000 },     /* R50 - Output Mixer6 */
+       { 51, 0x0180 },     /* R51 - Out3/4 Mixer */
+       { 52, 0x0000 },     /* R52 - Line Mixer1 */
+       { 53, 0x0000 },     /* R53 - Line Mixer2 */
+       { 54, 0x0000 },     /* R54 - Speaker Mixer */
+       { 55, 0x0000 },     /* R55 - Additional Control */
+       { 56, 0x0000 },     /* R56 - AntiPOP1 */
+       { 57, 0x0000 },     /* R57 - AntiPOP2 */
+       { 58, 0x0000 },     /* R58 - MICBIAS */
+
+       { 60, 0x0008 },     /* R60 - PLL1 */
+       { 61, 0x0031 },     /* R61 - PLL2 */
+       { 62, 0x0026 },     /* R62 - PLL3 */
 };
 
-#define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0)
+static bool wm8991_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8991_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
 
 static const unsigned int rec_mix_tlv[] = {
        TLV_DB_RANGE_HEAD(1),
@@ -374,30 +382,6 @@ static const struct snd_kcontrol_new wm8991_snd_controls[] = {
 /*
  * _DAPM_ Controls
  */
-static int inmixer_event(struct snd_soc_dapm_widget *w,
-                        struct snd_kcontrol *kcontrol, int event)
-{
-       u16 reg, fakepower;
-
-       reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2);
-       fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS);
-
-       if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) |
-                        (1 << WM8991_AINLMUX_PWR_BIT)))
-               reg |= WM8991_AINL_ENA;
-       else
-               reg &= ~WM8991_AINL_ENA;
-
-       if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) |
-                        (1 << WM8991_AINRMUX_PWR_BIT)))
-               reg |= WM8991_AINR_ENA;
-       else
-               reg &= ~WM8991_AINR_ENA;
-
-       snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
-       return 0;
-}
-
 static int outmixer_event(struct snd_soc_dapm_widget *w,
                          struct snd_kcontrol *kcontrol, int event)
 {
@@ -655,6 +639,11 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("RIN2"),
        SND_SOC_DAPM_INPUT("Internal ADC Source"),
 
+       SND_SOC_DAPM_SUPPLY("INL", WM8991_POWER_MANAGEMENT_2,
+                           WM8991_AINL_ENA_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("INR", WM8991_POWER_MANAGEMENT_2,
+                           WM8991_AINR_ENA_BIT, 0, NULL, 0),
+
        /* DACs */
        SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2,
                WM8991_ADCL_ENA_BIT, 0),
@@ -676,26 +665,22 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
                ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)),
 
        /* INMIXL */
-       SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0,
+       SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
                &wm8991_dapm_inmixl_controls[0],
-               ARRAY_SIZE(wm8991_dapm_inmixl_controls),
-               inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+               ARRAY_SIZE(wm8991_dapm_inmixl_controls)),
 
        /* AINLMUX */
-       SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0,
-               &wm8991_dapm_ainlmux_controls, inmixer_event,
-               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0,
+               &wm8991_dapm_ainlmux_controls),
 
        /* INMIXR */
-       SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0,
+       SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
                &wm8991_dapm_inmixr_controls[0],
-               ARRAY_SIZE(wm8991_dapm_inmixr_controls),
-               inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+               ARRAY_SIZE(wm8991_dapm_inmixr_controls)),
 
        /* AINRMUX */
-       SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0,
-               &wm8991_dapm_ainrmux_controls, inmixer_event,
-               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0,
+               &wm8991_dapm_ainrmux_controls),
 
        /* Output Side */
        /* DACs */
@@ -787,7 +772,7 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8991_dapm_routes[] = {
        /* Make DACs turn on when playing even if not mixed into any outputs */
        {"Internal DAC Sink", NULL, "Left DAC"},
        {"Internal DAC Sink", NULL, "Right DAC"},
@@ -797,6 +782,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Right ADC", NULL, "Internal ADC Source"},
 
        /* Input Side */
+       {"INMIXL", NULL, "INL"},
+       {"AINLMUX", NULL, "INL"},
+       {"INMIXR", NULL, "INR"},
+       {"AINRMUX", NULL, "INR"},
        /* LIN12 PGA */
        {"LIN12 PGA", "LIN1 Switch", "LIN1"},
        {"LIN12 PGA", "LIN2 Switch", "LIN2"},
@@ -1129,6 +1118,7 @@ static int wm8991_mute(struct snd_soc_dai *dai, int mute)
 static int wm8991_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct wm8991_priv *wm8991 = snd_soc_codec_get_drvdata(codec);
        u16 val;
 
        switch (level) {
@@ -1144,7 +1134,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(wm8991->regmap);
                        /* Enable all output discharge bits */
                        snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE |
                                      WM8991_DIS_RLINE | WM8991_DIS_OUT3 |
@@ -1232,7 +1222,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec,
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
                snd_soc_write(codec, WM8991_ANTIPOP2, 0x0);
-               codec->cache_sync = 1;
+               regcache_mark_dirty(wm8991->regmap);
                break;
        }
 
@@ -1266,44 +1256,14 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 
        wm8991 = snd_soc_codec_get_drvdata(codec);
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
                return ret;
        }
 
-       ret = wm8991_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
-       }
-
        wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4,
-                           WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
-
-       snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2,
-                           WM8991_GPIO1_SEL_MASK, 1);
-
-       snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1,
-                           WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
-                           WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
-
-       snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2,
-                           WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
-
-       snd_soc_write(codec, WM8991_DAC_CTRL, 0);
-       snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
-       snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
-
-       snd_soc_add_codec_controls(codec, wm8991_snd_controls,
-                            ARRAY_SIZE(wm8991_snd_controls));
-
-       snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
-                                 ARRAY_SIZE(wm8991_dapm_widgets));
-       snd_soc_dapm_add_routes(&codec->dapm, audio_map,
-                               ARRAY_SIZE(audio_map));
        return 0;
 }
 
@@ -1352,24 +1312,77 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
        .suspend = wm8991_suspend,
        .resume = wm8991_resume,
        .set_bias_level = wm8991_set_bias_level,
-       .reg_cache_size = WM8991_MAX_REGISTER + 1,
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8991_reg_defs
+       .controls = wm8991_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8991_snd_controls),
+       .dapm_widgets = wm8991_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets),
+       .dapm_routes = wm8991_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes),
+};
+
+static const struct regmap_config wm8991_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8991_PLL3,
+       .volatile_reg = wm8991_volatile,
+       .reg_defaults = wm8991_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8991_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
 };
 
 static int wm8991_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm8991_priv *wm8991;
+       unsigned int val;
        int ret;
 
        wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL);
        if (!wm8991)
                return -ENOMEM;
 
-       wm8991->control_type = SND_SOC_I2C;
+       wm8991->regmap = devm_regmap_init_i2c(i2c, &wm8991_regmap);
+       if (IS_ERR(wm8991->regmap))
+               return PTR_ERR(wm8991->regmap);
+
        i2c_set_clientdata(i2c, wm8991);
 
+       ret = regmap_read(wm8991->regmap, WM8991_RESET, &val);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to read device ID: %d\n", ret);
+               return ret;
+       }
+       if (val != 0x8991) {
+               dev_err(&i2c->dev, "Device with ID %x is not a WM8991\n", val);
+               return -EINVAL;
+       }
+
+       ret = regmap_write(wm8991->regmap, WM8991_RESET, 0);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+               return ret;
+       }
+
+       regmap_update_bits(wm8991->regmap, WM8991_AUDIO_INTERFACE_4,
+                          WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
+
+       regmap_update_bits(wm8991->regmap, WM8991_GPIO1_GPIO2,
+                          WM8991_GPIO1_SEL_MASK, 1);
+
+       regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_1,
+                          WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
+                          WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
+
+       regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_2,
+                          WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
+
+       regmap_write(wm8991->regmap, WM8991_DAC_CTRL, 0);
+       regmap_write(wm8991->regmap, WM8991_LEFT_OUTPUT_VOLUME,
+                    0x50 | (1<<8));
+       regmap_write(wm8991->regmap, WM8991_RIGHT_OUTPUT_VOLUME,
+                    0x50 | (1<<8));
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8991, &wm8991_dai, 1);
 
index 07707d8d7e20e8ef2625f4986c3b24f70285bc5a..08ed383303c02b94e13d62a4fd4a2aa782bf969a 100644 (file)
@@ -76,7 +76,6 @@
 #define WM8991_PLL1                             0x3C
 #define WM8991_PLL2                             0x3D
 #define WM8991_PLL3                             0x3E
-#define WM8991_INTDRIVBITS                     0x3F
 
 #define WM8991_REGISTER_COUNT                   60
 #define WM8991_MAX_REGISTER                     0x3F
  */
 #define WM8991_PLLK2_MASK                       0x00FF  /* PLLK2 - [7:0] */
 
-/*
- * R63 (0x3F) - Internal Driver Bits
- */
-#define WM8991_INMIXL_PWR_BIT                  0
-#define WM8991_AINLMUX_PWR_BIT                 1
-#define WM8991_INMIXR_PWR_BIT                  2
-#define WM8991_AINRMUX_PWR_BIT                 3
-
 #define WM8991_MCLK_DIV 0
 #define WM8991_DACCLK_DIV 1
 #define WM8991_ADCCLK_DIV 2
index 86426a117b07923dd4f89aa4811cb5d5dc21b907..b9be9cbc460391d4530e970e3c77a0521109c2a2 100644 (file)
@@ -4077,12 +4077,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT,
                           wm8994_temp_shut, "Thermal shutdown", codec);
 
-       ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
-                                wm_hubs_dcs_done, "DC servo done",
-                                &wm8994->hubs);
-       if (ret == 0)
-               wm8994->hubs.dcs_done_irq = true;
-
        switch (control->type) {
        case WM8994:
                if (wm8994->micdet_irq) {
@@ -4313,6 +4307,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        }
 
        wm_hubs_add_analogue_routes(codec, 0, 0);
+       ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
+                                wm_hubs_dcs_done, "DC servo done",
+                                &wm8994->hubs);
+       if (ret == 0)
+               wm8994->hubs.dcs_done_irq = true;
        snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
 
        switch (control->type) {
index da2899e6c4018fae6cd0a2411b58027f4048b6e4..4300caff17838b59d195ba629b1e0c94b3eb3574 100644 (file)
@@ -2293,7 +2293,7 @@ static struct spi_driver wm8995_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8995_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -2350,7 +2350,7 @@ static int __init wm8995_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8995_i2c_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8995 I2C driver: %d\n",
@@ -2371,7 +2371,7 @@ module_init(wm8995_modinit);
 
 static void __exit wm8995_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8995_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 1392bb3c92540366c9a28817891567bfcfd45601..555115ee2159eadd3083f522d8cd682000216a48 100644 (file)
@@ -103,8 +103,8 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                if (patch)
                        for (i = 0; i < patch_size; i++)
-                               regmap_write(regmap, patch[i].reg,
-                                            patch[i].def);
+                               regmap_write_async(regmap, patch[i].reg,
+                                                  patch[i].def);
                break;
        default:
                break;
index 630b3d776ec27133cd54f2c3dd440ae304c83417..0982c1d38ec458205628b2fdd52ccc87a499db97 100644 (file)
@@ -1326,7 +1326,7 @@ static const struct regmap_config wm9081_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm9081_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
index 46ec0e9744d4b88b50cc922cfdc65a0b4247e567..444626fcab40d42aed3b6df03e9cf86f43dd3423 100644 (file)
@@ -1286,6 +1286,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                                        reg = wm_adsp_region_to_reg(mem,
                                                                    reg);
                                        reg += offset;
+                                       break;
                                }
                        }
 
@@ -1468,19 +1469,23 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
        unsigned int val;
        int ret, count;
 
-       ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
-                                ADSP2_SYS_ENA, ADSP2_SYS_ENA);
+       ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                      ADSP2_SYS_ENA, ADSP2_SYS_ENA);
        if (ret != 0)
                return ret;
 
        /* Wait for the RAM to start, should be near instantaneous */
-       count = 0;
-       do {
+       for (count = 0; count < 10; ++count) {
                ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
                                  &val);
                if (ret != 0)
                        return ret;
-       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+               if (val & ADSP2_RAM_RDY)
+                       break;
+
+               msleep(1);
+       }
 
        if (!(val & ADSP2_RAM_RDY)) {
                adsp_err(dsp, "Failed to start DSP RAM\n");
@@ -1488,112 +1493,153 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
        }
 
        adsp_dbg(dsp, "RAM ready after %d polls\n", count);
-       adsp_info(dsp, "RAM ready after %d polls\n", count);
 
        return 0;
 }
 
-int wm_adsp2_event(struct snd_soc_dapm_widget *w,
-                  struct snd_kcontrol *kcontrol, int event)
+static void wm_adsp2_boot_work(struct work_struct *work)
 {
-       struct snd_soc_codec *codec = w->codec;
-       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
-       struct wm_adsp *dsp = &dsps[w->shift];
-       struct wm_adsp_alg_region *alg_region;
-       struct wm_coeff_ctl *ctl;
-       unsigned int val;
+       struct wm_adsp *dsp = container_of(work,
+                                          struct wm_adsp,
+                                          boot_work);
        int ret;
+       unsigned int val;
 
-       dsp->card = codec->card;
+       /*
+        * For simplicity set the DSP clock rate to be the
+        * SYSCLK rate rather than making it configurable.
+        */
+       ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
+               return;
+       }
+       val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+               >> ARIZONA_SYSCLK_FREQ_SHIFT;
 
-       switch (event) {
-       case SND_SOC_DAPM_POST_PMU:
-               /*
-                * For simplicity set the DSP clock rate to be the
-                * SYSCLK rate rather than making it configurable.
-                */
-               ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
-               if (ret != 0) {
-                       adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
-                                ret);
-                       return ret;
-               }
-               val = (val & ARIZONA_SYSCLK_FREQ_MASK)
-                       >> ARIZONA_SYSCLK_FREQ_SHIFT;
+       ret = regmap_update_bits_async(dsp->regmap,
+                                      dsp->base + ADSP2_CLOCKING,
+                                      ADSP2_CLK_SEL_MASK, val);
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
+               return;
+       }
 
-               ret = regmap_update_bits(dsp->regmap,
-                                        dsp->base + ADSP2_CLOCKING,
-                                        ADSP2_CLK_SEL_MASK, val);
+       if (dsp->dvfs) {
+               ret = regmap_read(dsp->regmap,
+                                 dsp->base + ADSP2_CLOCKING, &val);
                if (ret != 0) {
-                       adsp_err(dsp, "Failed to set clock rate: %d\n",
-                                ret);
-                       return ret;
+                       dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
+                       return;
                }
 
-               if (dsp->dvfs) {
-                       ret = regmap_read(dsp->regmap,
-                                         dsp->base + ADSP2_CLOCKING, &val);
+               if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+                       ret = regulator_enable(dsp->dvfs);
                        if (ret != 0) {
                                dev_err(dsp->dev,
-                                       "Failed to read clocking: %d\n", ret);
-                               return ret;
+                                       "Failed to enable supply: %d\n",
+                                       ret);
+                               return;
                        }
 
-                       if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
-                               ret = regulator_enable(dsp->dvfs);
-                               if (ret != 0) {
-                                       dev_err(dsp->dev,
-                                               "Failed to enable supply: %d\n",
-                                               ret);
-                                       return ret;
-                               }
-
-                               ret = regulator_set_voltage(dsp->dvfs,
-                                                           1800000,
-                                                           1800000);
-                               if (ret != 0) {
-                                       dev_err(dsp->dev,
-                                               "Failed to raise supply: %d\n",
-                                               ret);
-                                       return ret;
-                               }
+                       ret = regulator_set_voltage(dsp->dvfs,
+                                                   1800000,
+                                                   1800000);
+                       if (ret != 0) {
+                               dev_err(dsp->dev,
+                                       "Failed to raise supply: %d\n",
+                                       ret);
+                               return;
                        }
                }
+       }
 
-               ret = wm_adsp2_ena(dsp);
-               if (ret != 0)
-                       return ret;
+       ret = wm_adsp2_ena(dsp);
+       if (ret != 0)
+               return;
 
-               ret = wm_adsp_load(dsp);
-               if (ret != 0)
-                       goto err;
+       ret = wm_adsp_load(dsp);
+       if (ret != 0)
+               goto err;
 
-               ret = wm_adsp_setup_algs(dsp);
-               if (ret != 0)
-                       goto err;
+       ret = wm_adsp_setup_algs(dsp);
+       if (ret != 0)
+               goto err;
 
-               ret = wm_adsp_load_coeff(dsp);
-               if (ret != 0)
-                       goto err;
+       ret = wm_adsp_load_coeff(dsp);
+       if (ret != 0)
+               goto err;
 
-               /* Initialize caches for enabled and unset controls */
-               ret = wm_coeff_init_control_caches(dsp);
-               if (ret != 0)
-                       goto err;
+       /* Initialize caches for enabled and unset controls */
+       ret = wm_coeff_init_control_caches(dsp);
+       if (ret != 0)
+               goto err;
 
-               /* Sync set controls */
-               ret = wm_coeff_sync_controls(dsp);
-               if (ret != 0)
-                       goto err;
+       /* Sync set controls */
+       ret = wm_coeff_sync_controls(dsp);
+       if (ret != 0)
+               goto err;
+
+       ret = regmap_update_bits_async(dsp->regmap,
+                                      dsp->base + ADSP2_CONTROL,
+                                      ADSP2_CORE_ENA,
+                                      ADSP2_CORE_ENA);
+       if (ret != 0)
+               goto err;
+
+       dsp->running = true;
+
+       return;
+
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                          ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+}
+
+int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+
+       dsp->card = codec->card;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               queue_work(system_unbound_wq, &dsp->boot_work);
+               break;
+       default:
+               break;
+       };
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
+
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       struct wm_adsp_alg_region *alg_region;
+       struct wm_coeff_ctl *ctl;
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               flush_work(&dsp->boot_work);
+
+               if (!dsp->running)
+                       return -EIO;
 
                ret = regmap_update_bits(dsp->regmap,
                                         dsp->base + ADSP2_CONTROL,
-                                        ADSP2_CORE_ENA | ADSP2_START,
-                                        ADSP2_CORE_ENA | ADSP2_START);
+                                        ADSP2_START,
+                                        ADSP2_START);
                if (ret != 0)
                        goto err;
-
-               dsp->running = true;
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
@@ -1664,6 +1710,7 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
 
        INIT_LIST_HEAD(&adsp->alg_regions);
        INIT_LIST_HEAD(&adsp->ctl_list);
+       INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work);
 
        if (dvfs) {
                adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
index d018dea6254de44c5997813fcb9b958eeca09706..a4f6b64deb61bcec9729d5d8355b135b647774c8 100644 (file)
@@ -59,6 +59,8 @@ struct wm_adsp {
        struct regulator *dvfs;
 
        struct list_head ctl_list;
+
+       struct work_struct boot_work;
 };
 
 #define WM_ADSP1(wname, num) \
@@ -66,8 +68,12 @@ struct wm_adsp {
                wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
 
 #define WM_ADSP2(wname, num) \
-       SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
-               wm_adsp2_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
+{      .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
+       .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_early_event, \
+       .event_flags = SND_SOC_DAPM_PRE_PMU }, \
+{      .id = snd_soc_dapm_out_drv, .name = wname, \
+       .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
 
 extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
 extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
@@ -76,6 +82,8 @@ int wm_adsp1_init(struct wm_adsp *adsp);
 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol, int event);
 int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
 
index 95970f5db3eca228df66a55f5e357f14b26209c9..a8ec1fc3e4d09a72ad1e36dca4859208d56e5e7e 100644 (file)
@@ -1,11 +1,6 @@
 config SND_DAVINCI_SOC
-       tristate "SoC Audio for the TI DAVINCI or AM33XX chip"
-       depends on ARCH_DAVINCI || SOC_AM33XX
-       help
-         Platform driver for daVinci or AM33xx
-         Say Y or M if you want to add support for codecs attached to
-         the DAVINCI AC97, I2S, or McASP interface. You will also need
-         to select the audio interfaces to support below.
+       tristate "SoC Audio for TI DAVINCI or AM33XX/AM43XX chips"
+       depends on ARCH_DAVINCI || SOC_AM33XX || SOC_AM43XX
 
 config SND_DAVINCI_SOC_I2S
        tristate
@@ -16,11 +11,15 @@ config SND_DAVINCI_SOC_MCASP
 config SND_DAVINCI_SOC_VCIF
        tristate
 
+config SND_DAVINCI_SOC_GENERIC_EVM
+       tristate
+       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_MCASP
+
 config SND_AM33XX_SOC_EVM
        tristate "SoC Audio for the AM33XX chip based boards"
        depends on SND_DAVINCI_SOC && SOC_AM33XX
-       select SND_SOC_TLV320AIC3X
-       select SND_DAVINCI_SOC_MCASP
+       select SND_DAVINCI_SOC_GENERIC_EVM
        help
          Say Y or M if you want to add support for SoC audio on AM33XX
          boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
@@ -31,8 +30,7 @@ config SND_DAVINCI_SOC_EVM
        tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
        depends on SND_DAVINCI_SOC
        depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
-       select SND_DAVINCI_SOC_I2S
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
        help
          Say Y if you want to add support for SoC audio on TI
          DaVinci DM6446, DM355 or DM365 EVM platforms.
@@ -59,8 +57,7 @@ endchoice
 config  SND_DM6467_SOC_EVM
        tristate "SoC Audio support for DaVinci DM6467 EVM"
        depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM
-       select SND_DAVINCI_SOC_MCASP
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
        select SND_SOC_SPDIF
 
        help
@@ -69,8 +66,7 @@ config  SND_DM6467_SOC_EVM
 config  SND_DA830_SOC_EVM
        tristate "SoC Audio support for DA830/OMAP-L137 EVM"
        depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM
-       select SND_DAVINCI_SOC_MCASP
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
 
        help
          Say Y if you want to add support for SoC audio on TI
@@ -79,8 +75,7 @@ config  SND_DA830_SOC_EVM
 config  SND_DA850_SOC_EVM
        tristate "SoC Audio support for DA850/OMAP-L138 EVM"
        depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM
-       select SND_DAVINCI_SOC_MCASP
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
        help
          Say Y if you want to add support for SoC audio on TI
          DA850/OMAP-L138 EVM
index bc81e79fc301b8357cddd5edf7e707beb33a0723..744d4d9a018466c77709a0d18e40afdb26aac063 100644 (file)
@@ -9,11 +9,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
 obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
 obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
 
-# DAVINCI Machine Support
+# Generic DAVINCI/AM33xx Machine Support
 snd-soc-evm-objs := davinci-evm.o
 
-obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DAVINCI_SOC_GENERIC_EVM) += snd-soc-evm.o
index 623eb5e7c08981c08f31f2d51863c0426c1a7416..70ff3772079f2186cdf2967c1c050ff95f37350b 100644 (file)
 
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
-#include "davinci-mcasp.h"
 
 struct snd_soc_card_drvdata_davinci {
        unsigned sysclk;
 };
 
-#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
-               SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
 static int evm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *params)
 {
@@ -48,16 +45,6 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
                           snd_soc_card_get_drvdata(soc_card))->sysclk;
 
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
-       if (ret < 0)
-               return ret;
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
-       if (ret < 0)
-               return ret;
-
        /* set the codec system clock */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
        if (ret < 0)
@@ -71,24 +58,10 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int evm_spdif_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
-       /* set cpu DAI configuration */
-       return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
-}
-
 static struct snd_soc_ops evm_ops = {
        .hw_params = evm_hw_params,
 };
 
-static struct snd_soc_ops evm_spdif_ops = {
-       .hw_params = evm_spdif_hw_params,
-};
-
 /* davinci-evm machine dapm widgets */
 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -165,6 +138,8 @@ static struct snd_soc_dai_link dm6446_evm_dai = {
        .platform_name = "davinci-mcbsp",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static struct snd_soc_dai_link dm355_evm_dai = {
@@ -176,6 +151,8 @@ static struct snd_soc_dai_link dm355_evm_dai = {
        .platform_name = "davinci-mcbsp.1",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static struct snd_soc_dai_link dm365_evm_dai = {
@@ -184,10 +161,12 @@ static struct snd_soc_dai_link dm365_evm_dai = {
        .stream_name = "AIC3X",
        .cpu_dai_name = "davinci-mcbsp",
        .codec_dai_name = "tlv320aic3x-hifi",
-       .init = evm_aic3x_init,
        .codec_name = "tlv320aic3x-codec.1-0018",
-       .ops = &evm_ops,
        .platform_name = "davinci-mcbsp",
+       .init = evm_aic3x_init,
+       .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
        .name = "Voice Codec - CQ93VC",
        .stream_name = "CQ93",
@@ -208,6 +187,8 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
                .codec_name = "tlv320aic3x-codec.0-001a",
                .init = evm_aic3x_init,
                .ops = &evm_ops,
+               .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                          SND_SOC_DAIFMT_IB_NF,
        },
        {
                .name = "McASP",
@@ -216,7 +197,8 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
                .codec_dai_name = "dit-hifi",
                .codec_name = "spdif_dit",
                .platform_name = "davinci-mcasp.1",
-               .ops = &evm_spdif_ops,
+               .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                          SND_SOC_DAIFMT_IB_NF,
        },
 };
 
@@ -229,6 +211,8 @@ static struct snd_soc_dai_link da830_evm_dai = {
        .platform_name = "davinci-mcasp.1",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static struct snd_soc_dai_link da850_evm_dai = {
@@ -240,6 +224,8 @@ static struct snd_soc_dai_link da850_evm_dai = {
        .platform_name = "davinci-mcasp.0",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 /* davinci dm6446 evm audio machine driver */
@@ -336,6 +322,8 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
        .codec_dai_name = "tlv320aic3x-hifi",
        .ops            = &evm_ops,
        .init           = evm_aic3x_init,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static const struct of_device_id davinci_evm_dt_ids[] = {
index 71e14bb3a8cd11b4465567d088a05820e0ecdb74..b7858bfa0295357bc5d3ca6d1328932595167b9e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "davinci-pcm.h"
 #include "davinci-mcasp.h"
 
-/*
- * McASP register definitions
- */
-#define DAVINCI_MCASP_PID_REG          0x00
-#define DAVINCI_MCASP_PWREMUMGT_REG    0x04
-
-#define DAVINCI_MCASP_PFUNC_REG                0x10
-#define DAVINCI_MCASP_PDIR_REG         0x14
-#define DAVINCI_MCASP_PDOUT_REG                0x18
-#define DAVINCI_MCASP_PDSET_REG                0x1c
-
-#define DAVINCI_MCASP_PDCLR_REG                0x20
-
-#define DAVINCI_MCASP_TLGC_REG         0x30
-#define DAVINCI_MCASP_TLMR_REG         0x34
-
-#define DAVINCI_MCASP_GBLCTL_REG       0x44
-#define DAVINCI_MCASP_AMUTE_REG                0x48
-#define DAVINCI_MCASP_LBCTL_REG                0x4c
-
-#define DAVINCI_MCASP_TXDITCTL_REG     0x50
-
-#define DAVINCI_MCASP_GBLCTLR_REG      0x60
-#define DAVINCI_MCASP_RXMASK_REG       0x64
-#define DAVINCI_MCASP_RXFMT_REG                0x68
-#define DAVINCI_MCASP_RXFMCTL_REG      0x6c
-
-#define DAVINCI_MCASP_ACLKRCTL_REG     0x70
-#define DAVINCI_MCASP_AHCLKRCTL_REG    0x74
-#define DAVINCI_MCASP_RXTDM_REG                0x78
-#define DAVINCI_MCASP_EVTCTLR_REG      0x7c
-
-#define DAVINCI_MCASP_RXSTAT_REG       0x80
-#define DAVINCI_MCASP_RXTDMSLOT_REG    0x84
-#define DAVINCI_MCASP_RXCLKCHK_REG     0x88
-#define DAVINCI_MCASP_REVTCTL_REG      0x8c
-
-#define DAVINCI_MCASP_GBLCTLX_REG      0xa0
-#define DAVINCI_MCASP_TXMASK_REG       0xa4
-#define DAVINCI_MCASP_TXFMT_REG                0xa8
-#define DAVINCI_MCASP_TXFMCTL_REG      0xac
-
-#define DAVINCI_MCASP_ACLKXCTL_REG     0xb0
-#define DAVINCI_MCASP_AHCLKXCTL_REG    0xb4
-#define DAVINCI_MCASP_TXTDM_REG                0xb8
-#define DAVINCI_MCASP_EVTCTLX_REG      0xbc
-
-#define DAVINCI_MCASP_TXSTAT_REG       0xc0
-#define DAVINCI_MCASP_TXTDMSLOT_REG    0xc4
-#define DAVINCI_MCASP_TXCLKCHK_REG     0xc8
-#define DAVINCI_MCASP_XEVTCTL_REG      0xcc
-
-/* Left(even TDM Slot) Channel Status Register File */
-#define DAVINCI_MCASP_DITCSRA_REG      0x100
-/* Right(odd TDM slot) Channel Status Register File */
-#define DAVINCI_MCASP_DITCSRB_REG      0x118
-/* Left(even TDM slot) User Data Register File */
-#define DAVINCI_MCASP_DITUDRA_REG      0x130
-/* Right(odd TDM Slot) User Data Register File */
-#define DAVINCI_MCASP_DITUDRB_REG      0x148
-
-/* Serializer n Control Register */
-#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
-#define DAVINCI_MCASP_XRSRCTL_REG(n)   (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
-                                               (n << 2))
-
-/* Transmit Buffer for Serializer n */
-#define DAVINCI_MCASP_TXBUF_REG                0x200
-/* Receive Buffer for Serializer n */
-#define DAVINCI_MCASP_RXBUF_REG                0x280
-
-/* McASP FIFO Registers */
-#define DAVINCI_MCASP_WFIFOCTL         (0x1010)
-#define DAVINCI_MCASP_WFIFOSTS         (0x1014)
-#define DAVINCI_MCASP_RFIFOCTL         (0x1018)
-#define DAVINCI_MCASP_RFIFOSTS         (0x101C)
-#define MCASP_VER3_WFIFOCTL            (0x1000)
-#define MCASP_VER3_WFIFOSTS            (0x1004)
-#define MCASP_VER3_RFIFOCTL            (0x1008)
-#define MCASP_VER3_RFIFOSTS            (0x100C)
-
-/*
- * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
- *     Register Bits
- */
-#define MCASP_FREE     BIT(0)
-#define MCASP_SOFT     BIT(1)
-
-/*
- * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
- */
-#define AXR(n)         (1<<n)
-#define PFUNC_AMUTE    BIT(25)
-#define ACLKX          BIT(26)
-#define AHCLKX         BIT(27)
-#define AFSX           BIT(28)
-#define ACLKR          BIT(29)
-#define AHCLKR         BIT(30)
-#define AFSR           BIT(31)
-
-/*
- * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
- */
-#define AXR(n)         (1<<n)
-#define PDIR_AMUTE     BIT(25)
-#define ACLKX          BIT(26)
-#define AHCLKX         BIT(27)
-#define AFSX           BIT(28)
-#define ACLKR          BIT(29)
-#define AHCLKR         BIT(30)
-#define AFSR           BIT(31)
-
-/*
- * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
- */
-#define DITEN  BIT(0)  /* Transmit DIT mode enable/disable */
-#define VA     BIT(2)
-#define VB     BIT(3)
-
-/*
- * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
- */
-#define TXROT(val)     (val)
-#define TXSEL          BIT(3)
-#define TXSSZ(val)     (val<<4)
-#define TXPBIT(val)    (val<<8)
-#define TXPAD(val)     (val<<13)
-#define TXORD          BIT(15)
-#define FSXDLY(val)    (val<<16)
-
-/*
- * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
- */
-#define RXROT(val)     (val)
-#define RXSEL          BIT(3)
-#define RXSSZ(val)     (val<<4)
-#define RXPBIT(val)    (val<<8)
-#define RXPAD(val)     (val<<13)
-#define RXORD          BIT(15)
-#define FSRDLY(val)    (val<<16)
-
-/*
- * DAVINCI_MCASP_TXFMCTL_REG -  Transmit Frame Control Register Bits
- */
-#define FSXPOL         BIT(0)
-#define AFSXE          BIT(1)
-#define FSXDUR         BIT(4)
-#define FSXMOD(val)    (val<<7)
-
-/*
- * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
- */
-#define FSRPOL         BIT(0)
-#define AFSRE          BIT(1)
-#define FSRDUR         BIT(4)
-#define FSRMOD(val)    (val<<7)
-
-/*
- * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
- */
-#define ACLKXDIV(val)  (val)
-#define ACLKXE         BIT(5)
-#define TX_ASYNC       BIT(6)
-#define ACLKXPOL       BIT(7)
-#define ACLKXDIV_MASK  0x1f
-
-/*
- * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
- */
-#define ACLKRDIV(val)  (val)
-#define ACLKRE         BIT(5)
-#define RX_ASYNC       BIT(6)
-#define ACLKRPOL       BIT(7)
-#define ACLKRDIV_MASK  0x1f
-
-/*
- * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
- *     Register Bits
- */
-#define AHCLKXDIV(val) (val)
-#define AHCLKXPOL      BIT(14)
-#define AHCLKXE                BIT(15)
-#define AHCLKXDIV_MASK 0xfff
+struct davinci_mcasp {
+       struct davinci_pcm_dma_params dma_params[2];
+       struct snd_dmaengine_dai_dma_data dma_data[2];
+       void __iomem *base;
+       u32 fifo_base;
+       struct device *dev;
 
-/*
- * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
- *     Register Bits
- */
-#define AHCLKRDIV(val) (val)
-#define AHCLKRPOL      BIT(14)
-#define AHCLKRE                BIT(15)
-#define AHCLKRDIV_MASK 0xfff
+       /* McASP specific data */
+       int     tdm_slots;
+       u8      op_mode;
+       u8      num_serializer;
+       u8      *serial_dir;
+       u8      version;
+       u16     bclk_lrclk_ratio;
+       int     streams;
 
-/*
- * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
- */
-#define MODE(val)      (val)
-#define DISMOD         (val)(val<<2)
-#define TXSTATE                BIT(4)
-#define RXSTATE                BIT(5)
-#define SRMOD_MASK     3
-#define SRMOD_INACTIVE 0
-
-/*
- * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
- */
-#define LBEN           BIT(0)
-#define LBORD          BIT(1)
-#define LBGENMODE(val) (val<<2)
+       /* McASP FIFO related */
+       u8      txnumevt;
+       u8      rxnumevt;
 
-/*
- * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
- */
-#define TXTDMS(n)      (1<<n)
-
-/*
- * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
- */
-#define RXTDMS(n)      (1<<n)
-
-/*
- * DAVINCI_MCASP_GBLCTL_REG -  Global Control Register Bits
- */
-#define RXCLKRST       BIT(0)  /* Receiver Clock Divider Reset */
-#define RXHCLKRST      BIT(1)  /* Receiver High Frequency Clock Divider */
-#define RXSERCLR       BIT(2)  /* Receiver Serializer Clear */
-#define RXSMRST                BIT(3)  /* Receiver State Machine Reset */
-#define RXFSRST                BIT(4)  /* Frame Sync Generator Reset */
-#define TXCLKRST       BIT(8)  /* Transmitter Clock Divider Reset */
-#define TXHCLKRST      BIT(9)  /* Transmitter High Frequency Clock Divider*/
-#define TXSERCLR       BIT(10) /* Transmit Serializer Clear */
-#define TXSMRST                BIT(11) /* Transmitter State Machine Reset */
-#define TXFSRST                BIT(12) /* Frame Sync Generator Reset */
+       bool    dat_port;
 
-/*
- * DAVINCI_MCASP_AMUTE_REG -  Mute Control Register Bits
- */
-#define MUTENA(val)    (val)
-#define MUTEINPOL      BIT(2)
-#define MUTEINENA      BIT(3)
-#define MUTEIN         BIT(4)
-#define MUTER          BIT(5)
-#define MUTEX          BIT(6)
-#define MUTEFSR                BIT(7)
-#define MUTEFSX                BIT(8)
-#define MUTEBADCLKR    BIT(9)
-#define MUTEBADCLKX    BIT(10)
-#define MUTERXDMAERR   BIT(11)
-#define MUTETXDMAERR   BIT(12)
-
-/*
- * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
- */
-#define RXDATADMADIS   BIT(0)
-
-/*
- * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
- */
-#define TXDATADMADIS   BIT(0)
-
-/*
- * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
- */
-#define FIFO_ENABLE    BIT(16)
-#define NUMEVT_MASK    (0xFF << 8)
-#define NUMDMA_MASK    (0xFF)
-
-#define DAVINCI_MCASP_NUM_SERIALIZER   16
+#ifdef CONFIG_PM_SLEEP
+       struct {
+               u32     txfmtctl;
+               u32     rxfmtctl;
+               u32     txfmt;
+               u32     rxfmt;
+               u32     aclkxctl;
+               u32     aclkrctl;
+               u32     pdir;
+       } context;
+#endif
+};
 
-static inline void mcasp_set_bits(void __iomem *reg, u32 val)
+static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset,
+                                 u32 val)
 {
+       void __iomem *reg = mcasp->base + offset;
        __raw_writel(__raw_readl(reg) | val, reg);
 }
 
-static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
+static inline void mcasp_clr_bits(struct davinci_mcasp *mcasp, u32 offset,
+                                 u32 val)
 {
+       void __iomem *reg = mcasp->base + offset;
        __raw_writel((__raw_readl(reg) & ~(val)), reg);
 }
 
-static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
+static inline void mcasp_mod_bits(struct davinci_mcasp *mcasp, u32 offset,
+                                 u32 val, u32 mask)
 {
+       void __iomem *reg = mcasp->base + offset;
        __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
 }
 
-static inline void mcasp_set_reg(void __iomem *reg, u32 val)
+static inline void mcasp_set_reg(struct davinci_mcasp *mcasp, u32 offset,
+                                u32 val)
 {
-       __raw_writel(val, reg);
+       __raw_writel(val, mcasp->base + offset);
 }
 
-static inline u32 mcasp_get_reg(void __iomem *reg)
+static inline u32 mcasp_get_reg(struct davinci_mcasp *mcasp, u32 offset)
 {
-       return (unsigned int)__raw_readl(reg);
+       return (u32)__raw_readl(mcasp->base + offset);
 }
 
-static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
+static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val)
 {
        int i = 0;
 
-       mcasp_set_bits(regs, val);
+       mcasp_set_bits(mcasp, ctl_reg, val);
 
        /* programming GBLCTL needs to read back from GBLCTL and verfiy */
        /* loop count is to avoid the lock-up */
        for (i = 0; i < 1000; i++) {
-               if ((mcasp_get_reg(regs) & val) == val)
+               if ((mcasp_get_reg(mcasp, ctl_reg) & val) == val)
                        break;
        }
 
-       if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
+       if (i == 1000 && ((mcasp_get_reg(mcasp, ctl_reg) & val) != val))
                printk(KERN_ERR "GBLCTL write error\n");
 }
 
-static void mcasp_start_rx(struct davinci_audio_dev *dev)
+static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
 {
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+       u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
+       u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+       return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
+}
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+static void mcasp_start_rx(struct davinci_mcasp *mcasp)
+{
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
+
+       /*
+        * When ASYNC == 0 the transmit and receive sections operate
+        * synchronously from the transmit clock and frame sync. We need to make
+        * sure that the TX signlas are enabled when starting reception.
+        */
+       if (mcasp_is_synchronous(mcasp)) {
+               mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
+               mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+       }
+
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+
+       if (mcasp_is_synchronous(mcasp))
+               mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
 }
 
-static void mcasp_start_tx(struct davinci_audio_dev *dev)
+static void mcasp_start_tx(struct davinci_mcasp *mcasp)
 {
        u8 offset = 0, i;
        u32 cnt;
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
-       for (i = 0; i < dev->num_serializer; i++) {
-               if (dev->serial_dir[i] == TX_MODE) {
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
+       for (i = 0; i < mcasp->num_serializer; i++) {
+               if (mcasp->serial_dir[i] == TX_MODE) {
                        offset = i;
                        break;
                }
@@ -383,156 +180,140 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)
 
        /* wait for TX ready */
        cnt = 0;
-       while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
+       while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(offset)) &
                 TXSTATE) && (cnt < 100000))
                cnt++;
 
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
 }
 
-static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
+static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
 {
+       u32 reg;
+
+       mcasp->streams++;
+
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (dev->txnumevt) {    /* enable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                                                               FIFO_ENABLE);
-                               mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                                                               FIFO_ENABLE);
-                               break;
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
-                               mcasp_set_bits(dev->base +
-                                       DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->txnumevt) {  /* enable FIFO */
+                       reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
+                       mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_start_tx(dev);
+               mcasp_start_tx(mcasp);
        } else {
-               if (dev->rxnumevt) {    /* enable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                                                               FIFO_ENABLE);
-                               mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                                                               FIFO_ENABLE);
-                               break;
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
-                               mcasp_set_bits(dev->base +
-                                       DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->rxnumevt) {  /* enable FIFO */
+                       reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
+                       mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_start_rx(dev);
+               mcasp_start_rx(mcasp);
        }
 }
 
-static void mcasp_stop_rx(struct davinci_audio_dev *dev)
+static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
 {
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+       /*
+        * In synchronous mode stop the TX clocks if no other stream is
+        * running
+        */
+       if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
 }
 
-static void mcasp_stop_tx(struct davinci_audio_dev *dev)
+static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
 {
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+       u32 val = 0;
+
+       /*
+        * In synchronous mode keep TX clocks running if the capture stream is
+        * still running.
+        */
+       if (mcasp_is_synchronous(mcasp) && mcasp->streams)
+               val =  TXHCLKRST | TXCLKRST | TXFSRST;
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
 }
 
-static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
+static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
 {
+       u32 reg;
+
+       mcasp->streams--;
+
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (dev->txnumevt) {    /* disable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                                                               FIFO_ENABLE);
-                               break;
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->txnumevt) {  /* disable FIFO */
+                       reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_stop_tx(dev);
+               mcasp_stop_tx(mcasp);
        } else {
-               if (dev->rxnumevt) {    /* disable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                                                               FIFO_ENABLE);
-                       break;
-
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->rxnumevt) {  /* disable FIFO */
+                       reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_stop_rx(dev);
+               mcasp_stop_rx(mcasp);
        }
 }
 
 static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                         unsigned int fmt)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-       void __iomem *base = dev->base;
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
        case SND_SOC_DAIFMT_AC97:
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
                break;
        default:
                /* configure a full-word SYNC pulse (LRCLK) */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
 
                /* make 1st data bit occur one ACLK cycle after the frame sync */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
                break;
        }
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* codec is clock and frame slave */
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | ACLKR);
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               AFSX | AFSR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | ACLKR);
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               AFSX | AFSR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                /* codec is clock and frame master */
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
+                              ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
                break;
 
        default:
@@ -541,35 +322,35 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_IB_NF:
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        case SND_SOC_DAIFMT_NB_IF:
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        case SND_SOC_DAIFMT_IB_IF:
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        case SND_SOC_DAIFMT_NB_NF:
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        default:
@@ -581,25 +362,25 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
 static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
        switch (div_id) {
        case 0:         /* MCLK divider */
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
                               AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
                               AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
                break;
 
        case 1:         /* BCLK divider */
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,
                               ACLKXDIV(div - 1), ACLKXDIV_MASK);
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
                               ACLKRDIV(div - 1), ACLKRDIV_MASK);
                break;
 
        case 2:         /* BCLK/LRCLK ratio */
-               dev->bclk_lrclk_ratio = div;
+               mcasp->bclk_lrclk_ratio = div;
                break;
 
        default:
@@ -612,22 +393,22 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div
 static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                                    unsigned int freq, int dir)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
        if (dir == SND_SOC_CLOCK_OUT) {
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
        } else {
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
        }
 
        return 0;
 }
 
-static int davinci_config_channel_size(struct davinci_audio_dev *dev,
+static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
                                       int word_length)
 {
        u32 fmt;
@@ -644,71 +425,68 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
         * both left and right channels), so it has to be divided by number of
         * tdm-slots (for I2S - divided by 2).
         */
-       if (dev->bclk_lrclk_ratio)
-               word_length = dev->bclk_lrclk_ratio / dev->tdm_slots;
+       if (mcasp->bclk_lrclk_ratio)
+               word_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots;
 
        /* mapping of the XSSZ bit-field as described in the datasheet */
        fmt = (word_length >> 1) - 1;
 
-       if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) {
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
-                               RXSSZ(fmt), RXSSZ(0x0F));
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                               TXSSZ(fmt), TXSSZ(0x0F));
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                               TXROT(tx_rotate), TXROT(7));
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
-                               RXROT(rx_rotate), RXROT(7));
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
-                               mask);
+       if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),
+                              RXSSZ(0x0F));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
+                              TXSSZ(0x0F));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
+                              TXROT(7));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
+                              RXROT(7));
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
        }
 
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
 
        return 0;
 }
 
-static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
+static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
                                    int channels)
 {
        int i;
        u8 tx_ser = 0;
        u8 rx_ser = 0;
        u8 ser;
-       u8 slots = dev->tdm_slots;
+       u8 slots = mcasp->tdm_slots;
        u8 max_active_serializers = (channels + slots - 1) / slots;
+       u32 reg;
        /* Default configuration */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
+       if (mcasp->version != MCASP_VERSION_4)
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
 
        /* All PINS as McASP */
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000);
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
-                               TXDATADMADIS);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
        } else {
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
-                               RXDATADMADIS);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS);
        }
 
-       for (i = 0; i < dev->num_serializer; i++) {
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
-                                       dev->serial_dir[i]);
-               if (dev->serial_dir[i] == TX_MODE &&
+       for (i = 0; i < mcasp->num_serializer; i++) {
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                              mcasp->serial_dir[i]);
+               if (mcasp->serial_dir[i] == TX_MODE &&
                                        tx_ser < max_active_serializers) {
-                       mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
-                                       AXR(i));
+                       mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
                        tx_ser++;
-               } else if (dev->serial_dir[i] == RX_MODE &&
+               } else if (mcasp->serial_dir[i] == RX_MODE &&
                                        rx_ser < max_active_serializers) {
-                       mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
-                                       AXR(i));
+                       mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
                        rx_ser++;
                } else {
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
-                                       SRMOD_INACTIVE, SRMOD_MASK);
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                                      SRMOD_INACTIVE, SRMOD_MASK);
                }
        }
 
@@ -718,127 +496,113 @@ static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
                ser = rx_ser;
 
        if (ser < max_active_serializers) {
-               dev_warn(dev->dev, "stream has more channels (%d) than are "
+               dev_warn(mcasp->dev, "stream has more channels (%d) than are "
                        "enabled in mcasp (%d)\n", channels, ser * slots);
                return -EINVAL;
        }
 
-       if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (dev->txnumevt * tx_ser > 64)
-                       dev->txnumevt = 1;
+       if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (mcasp->txnumevt * tx_ser > 64)
+                       mcasp->txnumevt = 1;
 
-               switch (dev->version) {
-               case MCASP_VERSION_3:
-                       mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser,
-                                                               NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                               ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
-                       break;
-               default:
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
-                                                       tx_ser, NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
-                               ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
-               }
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK);
+               mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8),
+                              NUMEVT_MASK);
        }
 
-       if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
-               if (dev->rxnumevt * rx_ser > 64)
-                       dev->rxnumevt = 1;
-               switch (dev->version) {
-               case MCASP_VERSION_3:
-                       mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser,
-                                                               NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                               ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
-                       break;
-               default:
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
-                                                       rx_ser, NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
-                               ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
-               }
+       if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
+               if (mcasp->rxnumevt * rx_ser > 64)
+                       mcasp->rxnumevt = 1;
+
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK);
+               mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8),
+                              NUMEVT_MASK);
        }
 
        return 0;
 }
 
-static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
 {
        int i, active_slots;
        u32 mask = 0;
+       u32 busel = 0;
 
-       active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
+       active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots;
        for (i = 0; i < active_slots; i++)
                mask |= (1 << i);
 
-       mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+       mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+
+       if (!mcasp->dat_port)
+               busel = TXSEL;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* bit stream is MSB first  with no delay */
                /* DSP_B mode */
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
 
-               if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
-                                       FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
+               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
+                                      FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
                else
                        printk(KERN_ERR "playback tdm slot %d not supported\n",
-                               dev->tdm_slots);
+                               mcasp->tdm_slots);
        } else {
                /* bit stream is MSB first with no delay */
                /* DSP_B mode */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
 
-               if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
-                                       FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
+               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
+                                      FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
                else
                        printk(KERN_ERR "capture tdm slot %d not supported\n",
-                               dev->tdm_slots);
+                               mcasp->tdm_slots);
        }
 }
 
 /* S/PDIF */
-static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
+static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
 {
        /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
           and LSB first */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                                               TXROT(6) | TXSSZ(15));
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
 
        /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
-                                               AFSXE | FSXMOD(0x180));
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180));
 
        /* Set the TX tdm : for all the slots */
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
 
        /* Set the TX clock controls : div = 1 and internal */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
-                                               ACLKXE | TX_ASYNC);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | TX_ASYNC);
 
-       mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
+       mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
 
        /* Only 44100 and 48000 are valid, both have the same setting */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
 
        /* Enable the DIT */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
 }
 
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *params,
                                        struct snd_soc_dai *cpu_dai)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
        struct davinci_pcm_dma_params *dma_params =
-                                       &dev->dma_params[substream->stream];
+                                       &mcasp->dma_params[substream->stream];
+       struct snd_dmaengine_dai_dma_data *dma_data =
+                                       &mcasp->dma_data[substream->stream];
        int word_length;
        u8 fifo_level;
-       u8 slots = dev->tdm_slots;
+       u8 slots = mcasp->tdm_slots;
        u8 active_serializers;
        int channels;
        struct snd_interval *pcm_channels = hw_param_interval(params,
@@ -847,17 +611,17 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 
        active_serializers = (channels + slots - 1) / slots;
 
-       if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL)
+       if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL)
                return -EINVAL;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               fifo_level = dev->txnumevt * active_serializers;
+               fifo_level = mcasp->txnumevt * active_serializers;
        else
-               fifo_level = dev->rxnumevt * active_serializers;
+               fifo_level = mcasp->rxnumevt * active_serializers;
 
-       if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
-               davinci_hw_dit_param(dev);
+       if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+               davinci_hw_dit_param(mcasp);
        else
-               davinci_hw_param(dev, substream->stream);
+               davinci_hw_param(mcasp, substream->stream);
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_U8:
@@ -891,13 +655,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if (dev->version == MCASP_VERSION_2 && !fifo_level)
+       if (mcasp->version == MCASP_VERSION_2 && !fifo_level)
                dma_params->acnt = 4;
        else
                dma_params->acnt = dma_params->data_type;
 
        dma_params->fifo_level = fifo_level;
-       davinci_config_channel_size(dev, word_length);
+       dma_data->maxburst = fifo_level;
+
+       davinci_config_channel_size(mcasp, word_length);
 
        return 0;
 }
@@ -905,29 +671,29 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
                                     int cmd, struct snd_soc_dai *cpu_dai)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
        int ret = 0;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ret = pm_runtime_get_sync(dev->dev);
+               ret = pm_runtime_get_sync(mcasp->dev);
                if (IS_ERR_VALUE(ret))
-                       dev_err(dev->dev, "pm_runtime_get_sync() failed\n");
-               davinci_mcasp_start(dev, substream->stream);
+                       dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n");
+               davinci_mcasp_start(mcasp, substream->stream);
                break;
 
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               davinci_mcasp_stop(dev, substream->stream);
-               ret = pm_runtime_put_sync(dev->dev);
+               davinci_mcasp_stop(mcasp, substream->stream);
+               ret = pm_runtime_put_sync(mcasp->dev);
                if (IS_ERR_VALUE(ret))
-                       dev_err(dev->dev, "pm_runtime_put_sync() failed\n");
+                       dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n");
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               davinci_mcasp_stop(dev, substream->stream);
+               davinci_mcasp_stop(mcasp, substream->stream);
                break;
 
        default:
@@ -940,9 +706,14 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
 static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *dai)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+
+       if (mcasp->version == MCASP_VERSION_4)
+               snd_soc_dai_set_dma_data(dai, substream,
+                                       &mcasp->dma_data[substream->stream]);
+       else
+               snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params);
 
-       snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
        return 0;
 }
 
@@ -955,6 +726,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .set_sysclk     = davinci_mcasp_set_sysclk,
 };
 
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
+
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                                SNDRV_PCM_FMTBIT_U8 | \
                                SNDRV_PCM_FMTBIT_S16_LE | \
@@ -985,7 +758,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 
        },
        {
-               "davinci-mcasp.1",
+               .name           = "davinci-mcasp.1",
                .playback       = {
                        .channels_min   = 1,
                        .channels_max   = 384,
@@ -1016,13 +789,20 @@ static struct snd_platform_data da830_mcasp_pdata = {
        .version = MCASP_VERSION_2,
 };
 
-static struct snd_platform_data omap2_mcasp_pdata = {
+static struct snd_platform_data am33xx_mcasp_pdata = {
        .tx_dma_offset = 0,
        .rx_dma_offset = 0,
        .asp_chan_q = EVENTQ_0,
        .version = MCASP_VERSION_3,
 };
 
+static struct snd_platform_data dra7_mcasp_pdata = {
+       .tx_dma_offset = 0x200,
+       .rx_dma_offset = 0x284,
+       .asp_chan_q = EVENTQ_0,
+       .version = MCASP_VERSION_4,
+};
+
 static const struct of_device_id mcasp_dt_ids[] = {
        {
                .compatible = "ti,dm646x-mcasp-audio",
@@ -1034,12 +814,56 @@ static const struct of_device_id mcasp_dt_ids[] = {
        },
        {
                .compatible = "ti,am33xx-mcasp-audio",
-               .data = &omap2_mcasp_pdata,
+               .data = &am33xx_mcasp_pdata,
+       },
+       {
+               .compatible = "ti,dra7-mcasp-audio",
+               .data = &dra7_mcasp_pdata,
        },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
 
+static int mcasp_reparent_fck(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct clk *gfclk, *parent_clk;
+       const char *parent_name;
+       int ret;
+
+       if (!node)
+               return 0;
+
+       parent_name = of_get_property(node, "fck_parent", NULL);
+       if (!parent_name)
+               return 0;
+
+       gfclk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(gfclk)) {
+               dev_err(&pdev->dev, "failed to get fck\n");
+               return PTR_ERR(gfclk);
+       }
+
+       parent_clk = clk_get(NULL, parent_name);
+       if (IS_ERR(parent_clk)) {
+               dev_err(&pdev->dev, "failed to get parent clock\n");
+               ret = PTR_ERR(parent_clk);
+               goto err1;
+       }
+
+       ret = clk_set_parent(gfclk, parent_clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to reparent fck\n");
+               goto err2;
+       }
+
+err2:
+       clk_put(parent_clk);
+err1:
+       clk_put(gfclk);
+       return ret;
+}
+
 static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
                                                struct platform_device *pdev)
 {
@@ -1152,7 +976,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        struct davinci_pcm_dma_params *dma_data;
        struct resource *mem, *ioarea, *res, *dat;
        struct snd_platform_data *pdata;
-       struct davinci_audio_dev *dev;
+       struct davinci_mcasp *mcasp;
        int ret;
 
        if (!pdev->dev.platform_data && !pdev->dev.of_node) {
@@ -1160,9 +984,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev),
+       mcasp = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcasp),
                           GFP_KERNEL);
-       if (!dev)
+       if (!mcasp)
                return  -ENOMEM;
 
        pdata = davinci_mcasp_set_pdata_from_of(pdev);
@@ -1173,7 +997,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
        if (!mem) {
-               dev_warn(dev->dev,
+               dev_warn(mcasp->dev,
                         "\"mpu\" mem resource not found, using index 0\n");
                mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                if (!mem) {
@@ -1197,32 +1021,39 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                return ret;
        }
 
-       dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
-       if (!dev->base) {
+       mcasp->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+       if (!mcasp->base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENOMEM;
                goto err_release_clk;
        }
 
-       dev->op_mode = pdata->op_mode;
-       dev->tdm_slots = pdata->tdm_slots;
-       dev->num_serializer = pdata->num_serializer;
-       dev->serial_dir = pdata->serial_dir;
-       dev->version = pdata->version;
-       dev->txnumevt = pdata->txnumevt;
-       dev->rxnumevt = pdata->rxnumevt;
-       dev->dev = &pdev->dev;
+       mcasp->op_mode = pdata->op_mode;
+       mcasp->tdm_slots = pdata->tdm_slots;
+       mcasp->num_serializer = pdata->num_serializer;
+       mcasp->serial_dir = pdata->serial_dir;
+       mcasp->version = pdata->version;
+       mcasp->txnumevt = pdata->txnumevt;
+       mcasp->rxnumevt = pdata->rxnumevt;
+
+       mcasp->dev = &pdev->dev;
 
        dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
-       if (!dat)
-               dat = mem;
+       if (dat)
+               mcasp->dat_port = true;
 
-       dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
+       dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
        dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
-       dma_data->dma_addr = dat->start + pdata->tx_dma_offset;
+       if (dat)
+               dma_data->dma_addr = dat->start;
+       else
+               dma_data->dma_addr = mem->start + pdata->tx_dma_offset;
+
+       /* Unconditional dmaengine stuff */
+       mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr;
 
        res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
        if (res)
@@ -1230,12 +1061,26 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        else
                dma_data->channel = pdata->tx_dma_channel;
 
-       dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
+       dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
        dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
-       dma_data->dma_addr = dat->start + pdata->rx_dma_offset;
+       if (dat)
+               dma_data->dma_addr = dat->start;
+       else
+               dma_data->dma_addr = mem->start + pdata->rx_dma_offset;
+
+       /* Unconditional dmaengine stuff */
+       mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr;
+
+       if (mcasp->version < MCASP_VERSION_3) {
+               mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE;
+               /* dma_data->dma_addr is pointing to the data port address */
+               mcasp->dat_port = true;
+       } else {
+               mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
        if (res)
@@ -1243,17 +1088,26 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        else
                dma_data->channel = pdata->rx_dma_channel;
 
-       dev_set_drvdata(&pdev->dev, dev);
+       /* Unconditional dmaengine stuff */
+       mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx";
+       mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx";
+
+       dev_set_drvdata(&pdev->dev, mcasp);
+
+       mcasp_reparent_fck(pdev);
+
        ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
                                         &davinci_mcasp_dai[pdata->op_mode], 1);
 
        if (ret != 0)
                goto err_release_clk;
 
-       ret = davinci_soc_platform_register(&pdev->dev);
-       if (ret) {
-               dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
-               goto err_unregister_component;
+       if (mcasp->version != MCASP_VERSION_4) {
+               ret = davinci_soc_platform_register(&pdev->dev);
+               if (ret) {
+                       dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
+                       goto err_unregister_component;
+               }
        }
 
        return 0;
@@ -1268,9 +1122,11 @@ err_release_clk:
 
 static int davinci_mcasp_remove(struct platform_device *pdev)
 {
+       struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev);
 
        snd_soc_unregister_component(&pdev->dev);
-       davinci_soc_platform_unregister(&pdev->dev);
+       if (mcasp->version != MCASP_VERSION_4)
+               davinci_soc_platform_unregister(&pdev->dev);
 
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -1281,32 +1137,30 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int davinci_mcasp_suspend(struct device *dev)
 {
-       struct davinci_audio_dev *a = dev_get_drvdata(dev);
-       void __iomem *base = a->base;
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
 
-       a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG);
-       a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG);
-       a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG);
-       a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG);
-       a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG);
-       a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG);
-       a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG);
+       mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG);
+       mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
+       mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG);
+       mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG);
+       mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
+       mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG);
+       mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG);
 
        return 0;
 }
 
 static int davinci_mcasp_resume(struct device *dev)
 {
-       struct davinci_audio_dev *a = dev_get_drvdata(dev);
-       void __iomem *base = a->base;
-
-       mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt);
-       mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt);
-       mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir);
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir);
 
        return 0;
 }
index a2e27e1c32f3b28a8600ea0bb5325a35f7fe9741..8fed757d60876310ea4138e69a5575feed7cea60 100644 (file)
 #ifndef DAVINCI_MCASP_H
 #define DAVINCI_MCASP_H
 
-#include <linux/io.h>
-#include <linux/platform_data/davinci_asp.h>
-
-#include "davinci-pcm.h"
-
-#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
-#define DAVINCI_MCASP_I2S_DAI  0
-#define DAVINCI_MCASP_DIT_DAI  1
-
-struct davinci_audio_dev {
-       struct davinci_pcm_dma_params dma_params[2];
-       void __iomem *base;
-       struct device *dev;
-
-       /* McASP specific data */
-       int     tdm_slots;
-       u8      op_mode;
-       u8      num_serializer;
-       u8      *serial_dir;
-       u8      version;
-       u16     bclk_lrclk_ratio;
-
-       /* McASP FIFO related */
-       u8      txnumevt;
-       u8      rxnumevt;
-
-#ifdef CONFIG_PM_SLEEP
-       struct {
-               u32     txfmtctl;
-               u32     rxfmtctl;
-               u32     txfmt;
-               u32     rxfmt;
-               u32     aclkxctl;
-               u32     aclkrctl;
-               u32     pdir;
-       } context;
-#endif
-};
+/*
+ * McASP register definitions
+ */
+#define DAVINCI_MCASP_PID_REG          0x00
+#define DAVINCI_MCASP_PWREMUMGT_REG    0x04
+
+#define DAVINCI_MCASP_PFUNC_REG                0x10
+#define DAVINCI_MCASP_PDIR_REG         0x14
+#define DAVINCI_MCASP_PDOUT_REG                0x18
+#define DAVINCI_MCASP_PDSET_REG                0x1c
+
+#define DAVINCI_MCASP_PDCLR_REG                0x20
+
+#define DAVINCI_MCASP_TLGC_REG         0x30
+#define DAVINCI_MCASP_TLMR_REG         0x34
+
+#define DAVINCI_MCASP_GBLCTL_REG       0x44
+#define DAVINCI_MCASP_AMUTE_REG                0x48
+#define DAVINCI_MCASP_LBCTL_REG                0x4c
+
+#define DAVINCI_MCASP_TXDITCTL_REG     0x50
+
+#define DAVINCI_MCASP_GBLCTLR_REG      0x60
+#define DAVINCI_MCASP_RXMASK_REG       0x64
+#define DAVINCI_MCASP_RXFMT_REG                0x68
+#define DAVINCI_MCASP_RXFMCTL_REG      0x6c
+
+#define DAVINCI_MCASP_ACLKRCTL_REG     0x70
+#define DAVINCI_MCASP_AHCLKRCTL_REG    0x74
+#define DAVINCI_MCASP_RXTDM_REG                0x78
+#define DAVINCI_MCASP_EVTCTLR_REG      0x7c
+
+#define DAVINCI_MCASP_RXSTAT_REG       0x80
+#define DAVINCI_MCASP_RXTDMSLOT_REG    0x84
+#define DAVINCI_MCASP_RXCLKCHK_REG     0x88
+#define DAVINCI_MCASP_REVTCTL_REG      0x8c
+
+#define DAVINCI_MCASP_GBLCTLX_REG      0xa0
+#define DAVINCI_MCASP_TXMASK_REG       0xa4
+#define DAVINCI_MCASP_TXFMT_REG                0xa8
+#define DAVINCI_MCASP_TXFMCTL_REG      0xac
+
+#define DAVINCI_MCASP_ACLKXCTL_REG     0xb0
+#define DAVINCI_MCASP_AHCLKXCTL_REG    0xb4
+#define DAVINCI_MCASP_TXTDM_REG                0xb8
+#define DAVINCI_MCASP_EVTCTLX_REG      0xbc
+
+#define DAVINCI_MCASP_TXSTAT_REG       0xc0
+#define DAVINCI_MCASP_TXTDMSLOT_REG    0xc4
+#define DAVINCI_MCASP_TXCLKCHK_REG     0xc8
+#define DAVINCI_MCASP_XEVTCTL_REG      0xcc
+
+/* Left(even TDM Slot) Channel Status Register File */
+#define DAVINCI_MCASP_DITCSRA_REG      0x100
+/* Right(odd TDM slot) Channel Status Register File */
+#define DAVINCI_MCASP_DITCSRB_REG      0x118
+/* Left(even TDM slot) User Data Register File */
+#define DAVINCI_MCASP_DITUDRA_REG      0x130
+/* Right(odd TDM Slot) User Data Register File */
+#define DAVINCI_MCASP_DITUDRB_REG      0x148
+
+/* Serializer n Control Register */
+#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
+#define DAVINCI_MCASP_XRSRCTL_REG(n)   (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
+                                               (n << 2))
+
+/* Transmit Buffer for Serializer n */
+#define DAVINCI_MCASP_TXBUF_REG                0x200
+/* Receive Buffer for Serializer n */
+#define DAVINCI_MCASP_RXBUF_REG                0x280
+
+/* McASP FIFO Registers */
+#define DAVINCI_MCASP_V2_AFIFO_BASE    (0x1010)
+#define DAVINCI_MCASP_V3_AFIFO_BASE    (0x1000)
+
+/* FIFO register offsets from AFIFO base */
+#define MCASP_WFIFOCTL_OFFSET          (0x0)
+#define MCASP_WFIFOSTS_OFFSET          (0x4)
+#define MCASP_RFIFOCTL_OFFSET          (0x8)
+#define MCASP_RFIFOSTS_OFFSET          (0xc)
+
+/*
+ * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
+ *     Register Bits
+ */
+#define MCASP_FREE     BIT(0)
+#define MCASP_SOFT     BIT(1)
+
+/*
+ * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
+ */
+#define AXR(n)         (1<<n)
+#define PFUNC_AMUTE    BIT(25)
+#define ACLKX          BIT(26)
+#define AHCLKX         BIT(27)
+#define AFSX           BIT(28)
+#define ACLKR          BIT(29)
+#define AHCLKR         BIT(30)
+#define AFSR           BIT(31)
+
+/*
+ * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
+ */
+#define AXR(n)         (1<<n)
+#define PDIR_AMUTE     BIT(25)
+#define ACLKX          BIT(26)
+#define AHCLKX         BIT(27)
+#define AFSX           BIT(28)
+#define ACLKR          BIT(29)
+#define AHCLKR         BIT(30)
+#define AFSR           BIT(31)
+
+/*
+ * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
+ */
+#define DITEN  BIT(0)  /* Transmit DIT mode enable/disable */
+#define VA     BIT(2)
+#define VB     BIT(3)
+
+/*
+ * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
+ */
+#define TXROT(val)     (val)
+#define TXSEL          BIT(3)
+#define TXSSZ(val)     (val<<4)
+#define TXPBIT(val)    (val<<8)
+#define TXPAD(val)     (val<<13)
+#define TXORD          BIT(15)
+#define FSXDLY(val)    (val<<16)
+
+/*
+ * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
+ */
+#define RXROT(val)     (val)
+#define RXSEL          BIT(3)
+#define RXSSZ(val)     (val<<4)
+#define RXPBIT(val)    (val<<8)
+#define RXPAD(val)     (val<<13)
+#define RXORD          BIT(15)
+#define FSRDLY(val)    (val<<16)
+
+/*
+ * DAVINCI_MCASP_TXFMCTL_REG -  Transmit Frame Control Register Bits
+ */
+#define FSXPOL         BIT(0)
+#define AFSXE          BIT(1)
+#define FSXDUR         BIT(4)
+#define FSXMOD(val)    (val<<7)
+
+/*
+ * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
+ */
+#define FSRPOL         BIT(0)
+#define AFSRE          BIT(1)
+#define FSRDUR         BIT(4)
+#define FSRMOD(val)    (val<<7)
+
+/*
+ * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
+ */
+#define ACLKXDIV(val)  (val)
+#define ACLKXE         BIT(5)
+#define TX_ASYNC       BIT(6)
+#define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
+
+/*
+ * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
+ */
+#define ACLKRDIV(val)  (val)
+#define ACLKRE         BIT(5)
+#define RX_ASYNC       BIT(6)
+#define ACLKRPOL       BIT(7)
+#define ACLKRDIV_MASK  0x1f
+
+/*
+ * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
+ *     Register Bits
+ */
+#define AHCLKXDIV(val) (val)
+#define AHCLKXPOL      BIT(14)
+#define AHCLKXE                BIT(15)
+#define AHCLKXDIV_MASK 0xfff
+
+/*
+ * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
+ *     Register Bits
+ */
+#define AHCLKRDIV(val) (val)
+#define AHCLKRPOL      BIT(14)
+#define AHCLKRE                BIT(15)
+#define AHCLKRDIV_MASK 0xfff
+
+/*
+ * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
+ */
+#define MODE(val)      (val)
+#define DISMOD         (val)(val<<2)
+#define TXSTATE                BIT(4)
+#define RXSTATE                BIT(5)
+#define SRMOD_MASK     3
+#define SRMOD_INACTIVE 0
+
+/*
+ * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
+ */
+#define LBEN           BIT(0)
+#define LBORD          BIT(1)
+#define LBGENMODE(val) (val<<2)
+
+/*
+ * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
+ */
+#define TXTDMS(n)      (1<<n)
+
+/*
+ * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
+ */
+#define RXTDMS(n)      (1<<n)
+
+/*
+ * DAVINCI_MCASP_GBLCTL_REG -  Global Control Register Bits
+ */
+#define RXCLKRST       BIT(0)  /* Receiver Clock Divider Reset */
+#define RXHCLKRST      BIT(1)  /* Receiver High Frequency Clock Divider */
+#define RXSERCLR       BIT(2)  /* Receiver Serializer Clear */
+#define RXSMRST                BIT(3)  /* Receiver State Machine Reset */
+#define RXFSRST                BIT(4)  /* Frame Sync Generator Reset */
+#define TXCLKRST       BIT(8)  /* Transmitter Clock Divider Reset */
+#define TXHCLKRST      BIT(9)  /* Transmitter High Frequency Clock Divider*/
+#define TXSERCLR       BIT(10) /* Transmit Serializer Clear */
+#define TXSMRST                BIT(11) /* Transmitter State Machine Reset */
+#define TXFSRST                BIT(12) /* Frame Sync Generator Reset */
+
+/*
+ * DAVINCI_MCASP_AMUTE_REG -  Mute Control Register Bits
+ */
+#define MUTENA(val)    (val)
+#define MUTEINPOL      BIT(2)
+#define MUTEINENA      BIT(3)
+#define MUTEIN         BIT(4)
+#define MUTER          BIT(5)
+#define MUTEX          BIT(6)
+#define MUTEFSR                BIT(7)
+#define MUTEFSX                BIT(8)
+#define MUTEBADCLKR    BIT(9)
+#define MUTEBADCLKX    BIT(10)
+#define MUTERXDMAERR   BIT(11)
+#define MUTETXDMAERR   BIT(12)
+
+/*
+ * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
+ */
+#define RXDATADMADIS   BIT(0)
+
+/*
+ * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
+ */
+#define TXDATADMADIS   BIT(0)
+
+/*
+ * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
+ */
+#define FIFO_ENABLE    BIT(16)
+#define NUMEVT_MASK    (0xFF << 8)
+#define NUMDMA_MASK    (0xFF)
 
 #endif /* DAVINCI_MCASP_H */
index fb5d107f56034eebec7003878eceded711a51769..14145cdf8a11397494af3ac9d09454b88e774163 100644 (file)
@@ -46,33 +46,11 @@ static void print_buf_info(int slot, char *name)
 }
 #endif
 
-#define DAVINCI_PCM_FMTBITS    (\
-                               SNDRV_PCM_FMTBIT_S8     |\
-                               SNDRV_PCM_FMTBIT_U8     |\
-                               SNDRV_PCM_FMTBIT_S16_LE |\
-                               SNDRV_PCM_FMTBIT_S16_BE |\
-                               SNDRV_PCM_FMTBIT_U16_LE |\
-                               SNDRV_PCM_FMTBIT_U16_BE |\
-                               SNDRV_PCM_FMTBIT_S24_LE |\
-                               SNDRV_PCM_FMTBIT_S24_BE |\
-                               SNDRV_PCM_FMTBIT_U24_LE |\
-                               SNDRV_PCM_FMTBIT_U24_BE |\
-                               SNDRV_PCM_FMTBIT_S32_LE |\
-                               SNDRV_PCM_FMTBIT_S32_BE |\
-                               SNDRV_PCM_FMTBIT_U32_LE |\
-                               SNDRV_PCM_FMTBIT_U32_BE)
-
 static struct snd_pcm_hardware pcm_hardware_playback = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
                 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
                 SNDRV_PCM_INFO_BATCH),
-       .formats = DAVINCI_PCM_FMTBITS,
-       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
-       .rate_min = 8000,
-       .rate_max = 192000,
-       .channels_min = 2,
-       .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
        .period_bytes_min = 32,
        .period_bytes_max = 8 * 1024,
@@ -86,12 +64,6 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
                 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
                 SNDRV_PCM_INFO_PAUSE |
                 SNDRV_PCM_INFO_BATCH),
-       .formats = DAVINCI_PCM_FMTBITS,
-       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
-       .rate_min = 8000,
-       .rate_max = 192000,
-       .channels_min = 2,
-       .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
        .period_bytes_min = 32,
        .period_bytes_max = 8 * 1024,
index b7ab71f2ccc1676ec690427ef712c3785ccf80dd..324988dea4bd31bd8ad8f6d416c701c2f874966f 100644 (file)
@@ -1,9 +1,16 @@
+config SND_SOC_FSL_SAI
+       tristate
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+
 config SND_SOC_FSL_SSI
        tristate
 
 config SND_SOC_FSL_SPDIF
        tristate
 
+config SND_SOC_FSL_ESAI
+       tristate
+
 config SND_SOC_FSL_UTILS
        tristate
 
@@ -197,7 +204,6 @@ config SND_SOC_IMX_SPDIF
        tristate "SoC Audio support for i.MX boards with S/PDIF"
        select SND_SOC_IMX_PCM_DMA
        select SND_SOC_FSL_SPDIF
-       select SND_SOC_SPDIF
        select REGMAP_MMIO
        help
          SoC Audio support for i.MX boards with S/PDIF
index 8db705b0fdf9dc08d7ef793da25492bb71ce7049..b12ad4b9b4daa56599cc7cd92b1a861a3b7ce785 100644 (file)
@@ -10,13 +10,17 @@ obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
 snd-soc-p1022-rdk-objs := p1022_rdk.o
 obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
 
-# Freescale PowerPC SSI/DMA Platform Support
+# Freescale SSI/DMA/SAI/SPDIF Support
+snd-soc-fsl-sai-objs := fsl_sai.o
 snd-soc-fsl-ssi-objs := fsl_ssi.o
 snd-soc-fsl-spdif-objs := fsl_spdif.o
+snd-soc-fsl-esai-objs := fsl_esai.o
 snd-soc-fsl-utils-objs := fsl_utils.o
 snd-soc-fsl-dma-objs := fsl_dma.o
+obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
 obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
 obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
+obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o
 obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 
index fb9bb9eb5ca38f56d7359b6c57af772ee941675c..6bb0ea59284f0b4fab317f1b8ee263f7d1f7c341 100644 (file)
                            SNDRV_PCM_FMTBIT_S32_BE     | \
                            SNDRV_PCM_FMTBIT_U32_LE     | \
                            SNDRV_PCM_FMTBIT_U32_BE)
-
-#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
-                         SNDRV_PCM_RATE_CONTINUOUS)
-
 struct dma_object {
        struct snd_soc_platform_driver dai;
        dma_addr_t ssi_stx_phys;
@@ -140,9 +136,6 @@ static const struct snd_pcm_hardware fsl_dma_hardware = {
                                  SNDRV_PCM_INFO_JOINT_DUPLEX |
                                  SNDRV_PCM_INFO_PAUSE,
        .formats                = FSLDMA_PCM_FORMATS,
-       .rates                  = FSLDMA_PCM_RATES,
-       .rate_min               = 5512,
-       .rate_max               = 192000,
        .period_bytes_min       = 512,          /* A reasonable limit */
        .period_bytes_max       = (u32) -1,
        .periods_min            = NUM_DMA_LINKS,
@@ -852,7 +845,7 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
 }
 
 /**
- * find_ssi_node -- returns the SSI node that points to his DMA channel node
+ * find_ssi_node -- returns the SSI node that points to its DMA channel node
  *
  * Although this DMA driver attempts to operate independently of the other
  * devices, it still needs to determine some information about the SSI device
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
new file mode 100644 (file)
index 0000000..d0c72ed
--- /dev/null
@@ -0,0 +1,815 @@
+/*
+ * Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver
+ *
+ * Copyright (C) 2014 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 <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_esai.h"
+#include "imx-pcm.h"
+
+#define FSL_ESAI_RATES         SNDRV_PCM_RATE_8000_192000
+#define FSL_ESAI_FORMATS       (SNDRV_PCM_FMTBIT_S8 | \
+                               SNDRV_PCM_FMTBIT_S16_LE | \
+                               SNDRV_PCM_FMTBIT_S20_3LE | \
+                               SNDRV_PCM_FMTBIT_S24_LE)
+
+/**
+ * fsl_esai: ESAI private data
+ *
+ * @dma_params_rx: DMA parameters for receive channel
+ * @dma_params_tx: DMA parameters for transmit channel
+ * @pdev: platform device pointer
+ * @regmap: regmap handler
+ * @coreclk: clock source to access register
+ * @extalclk: esai clock source to derive HCK, SCK and FS
+ * @fsysclk: system clock source to derive HCK, SCK and FS
+ * @fifo_depth: depth of tx/rx FIFO
+ * @slot_width: width of each DAI slot
+ * @hck_rate: clock rate of desired HCKx clock
+ * @sck_div: if using PSR/PM dividers for SCKx clock
+ * @slave_mode: if fully using DAI slave mode
+ * @synchronous: if using tx/rx synchronous mode
+ * @name: driver name
+ */
+struct fsl_esai {
+       struct snd_dmaengine_dai_dma_data dma_params_rx;
+       struct snd_dmaengine_dai_dma_data dma_params_tx;
+       struct platform_device *pdev;
+       struct regmap *regmap;
+       struct clk *coreclk;
+       struct clk *extalclk;
+       struct clk *fsysclk;
+       u32 fifo_depth;
+       u32 slot_width;
+       u32 hck_rate[2];
+       bool sck_div[2];
+       bool slave_mode;
+       bool synchronous;
+       char name[32];
+};
+
+static irqreturn_t esai_isr(int irq, void *devid)
+{
+       struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
+       struct platform_device *pdev = esai_priv->pdev;
+       u32 esr;
+
+       regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr);
+
+       if (esr & ESAI_ESR_TINIT_MASK)
+               dev_dbg(&pdev->dev, "isr: Transmition Initialized\n");
+
+       if (esr & ESAI_ESR_RFF_MASK)
+               dev_warn(&pdev->dev, "isr: Receiving overrun\n");
+
+       if (esr & ESAI_ESR_TFE_MASK)
+               dev_warn(&pdev->dev, "isr: Transmition underrun\n");
+
+       if (esr & ESAI_ESR_TLS_MASK)
+               dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n");
+
+       if (esr & ESAI_ESR_TDE_MASK)
+               dev_dbg(&pdev->dev, "isr: Transmition data exception\n");
+
+       if (esr & ESAI_ESR_TED_MASK)
+               dev_dbg(&pdev->dev, "isr: Transmitting even slots\n");
+
+       if (esr & ESAI_ESR_TD_MASK)
+               dev_dbg(&pdev->dev, "isr: Transmitting data\n");
+
+       if (esr & ESAI_ESR_RLS_MASK)
+               dev_dbg(&pdev->dev, "isr: Just received the last slot\n");
+
+       if (esr & ESAI_ESR_RDE_MASK)
+               dev_dbg(&pdev->dev, "isr: Receiving data exception\n");
+
+       if (esr & ESAI_ESR_RED_MASK)
+               dev_dbg(&pdev->dev, "isr: Receiving even slots\n");
+
+       if (esr & ESAI_ESR_RD_MASK)
+               dev_dbg(&pdev->dev, "isr: Receiving data\n");
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * This function is used to calculate the divisors of psr, pm, fp and it is
+ * supposed to be called in set_dai_sysclk() and set_bclk().
+ *
+ * @ratio: desired overall ratio for the paticipating dividers
+ * @usefp: for HCK setting, there is no need to set fp divider
+ * @fp: bypass other dividers by setting fp directly if fp != 0
+ * @tx: current setting is for playback or capture
+ */
+static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
+                               bool usefp, u32 fp)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+       u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;
+
+       maxfp = usefp ? 16 : 1;
+
+       if (usefp && fp)
+               goto out_fp;
+
+       if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
+               dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
+                               2 * 8 * 256 * maxfp);
+               return -EINVAL;
+       } else if (ratio % 2) {
+               dev_err(dai->dev, "the raio must be even if using upper divider\n");
+               return -EINVAL;
+       }
+
+       ratio /= 2;
+
+       psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
+
+       /* Set the max fluctuation -- 0.1% of the max devisor */
+       savesub = (psr ? 1 : 8)  * 256 * maxfp / 1000;
+
+       /* Find the best value for PM */
+       for (i = 1; i <= 256; i++) {
+               for (j = 1; j <= maxfp; j++) {
+                       /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
+                       prod = (psr ? 1 : 8) * i * j;
+
+                       if (prod == ratio)
+                               sub = 0;
+                       else if (prod / ratio == 1)
+                               sub = prod - ratio;
+                       else if (ratio / prod == 1)
+                               sub = ratio - prod;
+                       else
+                               continue;
+
+                       /* Calculate the fraction */
+                       sub = sub * 1000 / ratio;
+                       if (sub < savesub) {
+                               savesub = sub;
+                               pm = i;
+                               fp = j;
+                       }
+
+                       /* We are lucky */
+                       if (savesub == 0)
+                               goto out;
+               }
+       }
+
+       if (pm == 999) {
+               dev_err(dai->dev, "failed to calculate proper divisors\n");
+               return -EINVAL;
+       }
+
+out:
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
+                          ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
+                          psr | ESAI_xCCR_xPM(pm));
+
+out_fp:
+       /* Bypass fp if not being required */
+       if (maxfp <= 1)
+               return 0;
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
+                          ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));
+
+       return 0;
+}
+
+/**
+ * This function mainly configures the clock frequency of MCLK (HCKT/HCKR)
+ *
+ * @Parameters:
+ * clk_id: The clock source of HCKT/HCKR
+ *       (Input from outside; output from inside, FSYS or EXTAL)
+ * freq: The required clock rate of HCKT/HCKR
+ * dir: The clock direction of HCKT/HCKR
+ *
+ * Note: If the direction is input, we do not care about clk_id.
+ */
+static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                  unsigned int freq, int dir)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+       struct clk *clksrc = esai_priv->extalclk;
+       bool tx = clk_id <= ESAI_HCKT_EXTAL;
+       bool in = dir == SND_SOC_CLOCK_IN;
+       u32 ret, ratio, ecr = 0;
+       unsigned long clk_rate;
+
+       /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
+       esai_priv->sck_div[tx] = true;
+
+       /* Set the direction of HCKT/HCKR pins */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
+                          ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);
+
+       if (in)
+               goto out;
+
+       switch (clk_id) {
+       case ESAI_HCKT_FSYS:
+       case ESAI_HCKR_FSYS:
+               clksrc = esai_priv->fsysclk;
+               break;
+       case ESAI_HCKT_EXTAL:
+               ecr |= ESAI_ECR_ETI;
+       case ESAI_HCKR_EXTAL:
+               ecr |= ESAI_ECR_ERI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (IS_ERR(clksrc)) {
+               dev_err(dai->dev, "no assigned %s clock\n",
+                               clk_id % 2 ? "extal" : "fsys");
+               return PTR_ERR(clksrc);
+       }
+       clk_rate = clk_get_rate(clksrc);
+
+       ratio = clk_rate / freq;
+       if (ratio * freq > clk_rate)
+               ret = ratio * freq - clk_rate;
+       else if (ratio * freq < clk_rate)
+               ret = clk_rate - ratio * freq;
+       else
+               ret = 0;
+
+       /* Block if clock source can not be divided into the required rate */
+       if (ret != 0 && clk_rate / ret < 1000) {
+               dev_err(dai->dev, "failed to derive required HCK%c rate\n",
+                               tx ? 'T' : 'R');
+               return -EINVAL;
+       }
+
+       if (ratio == 1) {
+               /* Bypass all the dividers if not being needed */
+               ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
+               goto out;
+       }
+
+       ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
+       if (ret)
+               return ret;
+
+       esai_priv->sck_div[tx] = false;
+
+out:
+       esai_priv->hck_rate[tx] = freq;
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
+                          tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
+                          ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);
+
+       return 0;
+}
+
+/**
+ * This function configures the related dividers according to the bclk rate
+ */
+static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+       u32 hck_rate = esai_priv->hck_rate[tx];
+       u32 sub, ratio = hck_rate / freq;
+
+       /* Don't apply for fully slave mode*/
+       if (esai_priv->slave_mode)
+               return 0;
+
+       if (ratio * freq > hck_rate)
+               sub = ratio * freq - hck_rate;
+       else if (ratio * freq < hck_rate)
+               sub = hck_rate - ratio * freq;
+       else
+               sub = 0;
+
+       /* Block if clock source can not be divided into the required rate */
+       if (sub != 0 && hck_rate / sub < 1000) {
+               dev_err(dai->dev, "failed to derive required SCK%c rate\n",
+                               tx ? 'T' : 'R');
+               return -EINVAL;
+       }
+
+       if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
+               dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
+               return -EINVAL;
+       }
+
+       return fsl_esai_divisor_cal(dai, tx, ratio, true,
+                       esai_priv->sck_div[tx] ? 0 : ratio);
+}
+
+static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
+                                    u32 rx_mask, int slots, int slot_width)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
+                          ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
+                          ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
+                          ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask));
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
+                          ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
+                          ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
+                          ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask));
+
+       esai_priv->slot_width = slot_width;
+
+       return 0;
+}
+
+static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+       u32 xcr = 0, xccr = 0, mask;
+
+       /* DAI mode */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               /* Data on rising edge of bclk, frame low, 1clk before data */
+               xcr |= ESAI_xCR_xFSR;
+               xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               /* Data on rising edge of bclk, frame high */
+               xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               /* Data on rising edge of bclk, frame high, right aligned */
+               xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               /* Data on rising edge of bclk, frame high, 1clk before data */
+               xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
+               xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               /* Data on rising edge of bclk, frame high */
+               xcr |= ESAI_xCR_xFSL;
+               xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* DAI clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               /* Nothing to do for both normal cases */
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               /* Invert bit clock */
+               xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               /* Invert frame clock */
+               xccr ^= ESAI_xCCR_xFSP;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               /* Invert both clocks */
+               xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       esai_priv->slave_mode = false;
+
+       /* DAI clock master masks */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               esai_priv->slave_mode = true;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               xccr |= ESAI_xCCR_xCKD;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               xccr |= ESAI_xCCR_xFSD;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR;
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);
+
+       mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
+               ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA;
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);
+
+       return 0;
+}
+
+static int fsl_esai_startup(struct snd_pcm_substream *substream,
+                           struct snd_soc_dai *dai)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+
+       /*
+        * Some platforms might use the same bit to gate all three or two of
+        * clocks, so keep all clocks open/close at the same time for safety
+        */
+       clk_prepare_enable(esai_priv->coreclk);
+       if (!IS_ERR(esai_priv->extalclk))
+               clk_prepare_enable(esai_priv->extalclk);
+       if (!IS_ERR(esai_priv->fsysclk))
+               clk_prepare_enable(esai_priv->fsysclk);
+
+       if (!dai->active) {
+               /* Reset Port C */
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
+                                  ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
+                                  ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
+
+               /* Set synchronous mode */
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
+                                  ESAI_SAICR_SYNC, esai_priv->synchronous ?
+                                  ESAI_SAICR_SYNC : 0);
+
+               /* Set a default slot number -- 2 */
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
+                                  ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
+                                  ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
+       }
+
+       return 0;
+}
+
+static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params,
+                             struct snd_soc_dai *dai)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       u32 width = snd_pcm_format_width(params_format(params));
+       u32 channels = params_channels(params);
+       u32 bclk, mask, val, ret;
+
+       bclk = params_rate(params) * esai_priv->slot_width * 2;
+
+       ret = fsl_esai_set_bclk(dai, tx, bclk);
+       if (ret)
+               return ret;
+
+       /* Use Normal mode to support monaural audio */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+                          ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
+                          ESAI_xCR_xMOD_NETWORK : 0);
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                          ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR);
+
+       mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK |
+             (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK);
+       val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) |
+            (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels));
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
+
+       mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0);
+       val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0);
+
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
+
+       return 0;
+}
+
+static void fsl_esai_shutdown(struct snd_pcm_substream *substream,
+                             struct snd_soc_dai *dai)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+
+       if (!IS_ERR(esai_priv->fsysclk))
+               clk_disable_unprepare(esai_priv->fsysclk);
+       if (!IS_ERR(esai_priv->extalclk))
+               clk_disable_unprepare(esai_priv->extalclk);
+       clk_disable_unprepare(esai_priv->coreclk);
+}
+
+static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
+                           struct snd_soc_dai *dai)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       u8 i, channels = substream->runtime->channels;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                                  ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN);
+
+               /* Write initial words reqiured by ESAI as normal procedure */
+               for (i = 0; tx && i < channels; i++)
+                       regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
+
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+                                  tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
+                                  tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels));
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+                                  tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
+
+               /* Disable and reset FIFO */
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                                  ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR);
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+                                  ESAI_xFCR_xFR, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_dai_ops fsl_esai_dai_ops = {
+       .startup = fsl_esai_startup,
+       .shutdown = fsl_esai_shutdown,
+       .trigger = fsl_esai_trigger,
+       .hw_params = fsl_esai_hw_params,
+       .set_sysclk = fsl_esai_set_dai_sysclk,
+       .set_fmt = fsl_esai_set_dai_fmt,
+       .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
+};
+
+static int fsl_esai_dai_probe(struct snd_soc_dai *dai)
+{
+       struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx,
+                                 &esai_priv->dma_params_rx);
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver fsl_esai_dai = {
+       .probe = fsl_esai_dai_probe,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 12,
+               .rates = FSL_ESAI_RATES,
+               .formats = FSL_ESAI_FORMATS,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 8,
+               .rates = FSL_ESAI_RATES,
+               .formats = FSL_ESAI_FORMATS,
+       },
+       .ops = &fsl_esai_dai_ops,
+};
+
+static const struct snd_soc_component_driver fsl_esai_component = {
+       .name           = "fsl-esai",
+};
+
+static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case REG_ESAI_ERDR:
+       case REG_ESAI_ECR:
+       case REG_ESAI_ESR:
+       case REG_ESAI_TFCR:
+       case REG_ESAI_TFSR:
+       case REG_ESAI_RFCR:
+       case REG_ESAI_RFSR:
+       case REG_ESAI_RX0:
+       case REG_ESAI_RX1:
+       case REG_ESAI_RX2:
+       case REG_ESAI_RX3:
+       case REG_ESAI_SAISR:
+       case REG_ESAI_SAICR:
+       case REG_ESAI_TCR:
+       case REG_ESAI_TCCR:
+       case REG_ESAI_RCR:
+       case REG_ESAI_RCCR:
+       case REG_ESAI_TSMA:
+       case REG_ESAI_TSMB:
+       case REG_ESAI_RSMA:
+       case REG_ESAI_RSMB:
+       case REG_ESAI_PRRC:
+       case REG_ESAI_PCRC:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case REG_ESAI_ETDR:
+       case REG_ESAI_ECR:
+       case REG_ESAI_TFCR:
+       case REG_ESAI_RFCR:
+       case REG_ESAI_TX0:
+       case REG_ESAI_TX1:
+       case REG_ESAI_TX2:
+       case REG_ESAI_TX3:
+       case REG_ESAI_TX4:
+       case REG_ESAI_TX5:
+       case REG_ESAI_TSR:
+       case REG_ESAI_SAICR:
+       case REG_ESAI_TCR:
+       case REG_ESAI_TCCR:
+       case REG_ESAI_RCR:
+       case REG_ESAI_RCCR:
+       case REG_ESAI_TSMA:
+       case REG_ESAI_TSMB:
+       case REG_ESAI_RSMA:
+       case REG_ESAI_RSMB:
+       case REG_ESAI_PRRC:
+       case REG_ESAI_PCRC:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct regmap_config fsl_esai_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+
+       .max_register = REG_ESAI_PCRC,
+       .readable_reg = fsl_esai_readable_reg,
+       .writeable_reg = fsl_esai_writeable_reg,
+};
+
+static int fsl_esai_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct fsl_esai *esai_priv;
+       struct resource *res;
+       const uint32_t *iprop;
+       void __iomem *regs;
+       int irq, ret;
+
+       esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL);
+       if (!esai_priv)
+               return -ENOMEM;
+
+       esai_priv->pdev = pdev;
+       strcpy(esai_priv->name, np->name);
+
+       /* Get the addresses and IRQ */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+                       "core", regs, &fsl_esai_regmap_config);
+       if (IS_ERR(esai_priv->regmap)) {
+               dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+                               PTR_ERR(esai_priv->regmap));
+               return PTR_ERR(esai_priv->regmap);
+       }
+
+       esai_priv->coreclk = devm_clk_get(&pdev->dev, "core");
+       if (IS_ERR(esai_priv->coreclk)) {
+               dev_err(&pdev->dev, "failed to get core clock: %ld\n",
+                               PTR_ERR(esai_priv->coreclk));
+               return PTR_ERR(esai_priv->coreclk);
+       }
+
+       esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal");
+       if (IS_ERR(esai_priv->extalclk))
+               dev_warn(&pdev->dev, "failed to get extal clock: %ld\n",
+                               PTR_ERR(esai_priv->extalclk));
+
+       esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys");
+       if (IS_ERR(esai_priv->fsysclk))
+               dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n",
+                               PTR_ERR(esai_priv->fsysclk));
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
+               return irq;
+       }
+
+       ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0,
+                              esai_priv->name, esai_priv);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
+               return ret;
+       }
+
+       /* Set a default slot size */
+       esai_priv->slot_width = 32;
+
+       /* Set a default master/slave state */
+       esai_priv->slave_mode = true;
+
+       /* Determine the FIFO depth */
+       iprop = of_get_property(np, "fsl,fifo-depth", NULL);
+       if (iprop)
+               esai_priv->fifo_depth = be32_to_cpup(iprop);
+       else
+               esai_priv->fifo_depth = 64;
+
+       esai_priv->dma_params_tx.maxburst = 16;
+       esai_priv->dma_params_rx.maxburst = 16;
+       esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR;
+       esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR;
+
+       esai_priv->synchronous =
+               of_property_read_bool(np, "fsl,esai-synchronous");
+
+       /* Implement full symmetry for synchronous mode */
+       if (esai_priv->synchronous) {
+               fsl_esai_dai.symmetric_rates = 1;
+               fsl_esai_dai.symmetric_channels = 1;
+               fsl_esai_dai.symmetric_samplebits = 1;
+       }
+
+       dev_set_drvdata(&pdev->dev, esai_priv);
+
+       /* Reset ESAI unit */
+       ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * We need to enable ESAI so as to access some of its registers.
+        * Otherwise, we would fail to dump regmap from user space.
+        */
+       ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret);
+               return ret;
+       }
+
+       ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
+                                             &fsl_esai_dai, 1);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
+               return ret;
+       }
+
+       ret = imx_pcm_dma_init(pdev);
+       if (ret)
+               dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
+
+       return ret;
+}
+
+static const struct of_device_id fsl_esai_dt_ids[] = {
+       { .compatible = "fsl,imx35-esai", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
+
+static struct platform_driver fsl_esai_driver = {
+       .probe = fsl_esai_probe,
+       .driver = {
+               .name = "fsl-esai-dai",
+               .owner = THIS_MODULE,
+               .of_match_table = fsl_esai_dt_ids,
+       },
+};
+
+module_platform_driver(fsl_esai_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:fsl-esai-dai");
diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h
new file mode 100644 (file)
index 0000000..9c9f957
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * fsl_esai.h - ALSA ESAI interface for the Freescale i.MX SoC
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Nicolin Chen <Guangyu.Chen@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_ESAI_DAI_H
+#define _FSL_ESAI_DAI_H
+
+/* ESAI Register Map */
+#define REG_ESAI_ETDR          0x00
+#define REG_ESAI_ERDR          0x04
+#define REG_ESAI_ECR           0x08
+#define REG_ESAI_ESR           0x0C
+#define REG_ESAI_TFCR          0x10
+#define REG_ESAI_TFSR          0x14
+#define REG_ESAI_RFCR          0x18
+#define REG_ESAI_RFSR          0x1C
+#define REG_ESAI_xFCR(tx)      (tx ? REG_ESAI_TFCR : REG_ESAI_RFCR)
+#define REG_ESAI_xFSR(tx)      (tx ? REG_ESAI_TFSR : REG_ESAI_RFSR)
+#define REG_ESAI_TX0           0x80
+#define REG_ESAI_TX1           0x84
+#define REG_ESAI_TX2           0x88
+#define REG_ESAI_TX3           0x8C
+#define REG_ESAI_TX4           0x90
+#define REG_ESAI_TX5           0x94
+#define REG_ESAI_TSR           0x98
+#define REG_ESAI_RX0           0xA0
+#define REG_ESAI_RX1           0xA4
+#define REG_ESAI_RX2           0xA8
+#define REG_ESAI_RX3           0xAC
+#define REG_ESAI_SAISR         0xCC
+#define REG_ESAI_SAICR         0xD0
+#define REG_ESAI_TCR           0xD4
+#define REG_ESAI_TCCR          0xD8
+#define REG_ESAI_RCR           0xDC
+#define REG_ESAI_RCCR          0xE0
+#define REG_ESAI_xCR(tx)       (tx ? REG_ESAI_TCR : REG_ESAI_RCR)
+#define REG_ESAI_xCCR(tx)      (tx ? REG_ESAI_TCCR : REG_ESAI_RCCR)
+#define REG_ESAI_TSMA          0xE4
+#define REG_ESAI_TSMB          0xE8
+#define REG_ESAI_RSMA          0xEC
+#define REG_ESAI_RSMB          0xF0
+#define REG_ESAI_xSMA(tx)      (tx ? REG_ESAI_TSMA : REG_ESAI_RSMA)
+#define REG_ESAI_xSMB(tx)      (tx ? REG_ESAI_TSMB : REG_ESAI_RSMB)
+#define REG_ESAI_PRRC          0xF8
+#define REG_ESAI_PCRC          0xFC
+
+/* ESAI Control Register -- REG_ESAI_ECR 0x8 */
+#define ESAI_ECR_ETI_SHIFT     19
+#define ESAI_ECR_ETI_MASK      (1 << ESAI_ECR_ETI_SHIFT)
+#define ESAI_ECR_ETI           (1 << ESAI_ECR_ETI_SHIFT)
+#define ESAI_ECR_ETO_SHIFT     18
+#define ESAI_ECR_ETO_MASK      (1 << ESAI_ECR_ETO_SHIFT)
+#define ESAI_ECR_ETO           (1 << ESAI_ECR_ETO_SHIFT)
+#define ESAI_ECR_ERI_SHIFT     17
+#define ESAI_ECR_ERI_MASK      (1 << ESAI_ECR_ERI_SHIFT)
+#define ESAI_ECR_ERI           (1 << ESAI_ECR_ERI_SHIFT)
+#define ESAI_ECR_ERO_SHIFT     16
+#define ESAI_ECR_ERO_MASK      (1 << ESAI_ECR_ERO_SHIFT)
+#define ESAI_ECR_ERO           (1 << ESAI_ECR_ERO_SHIFT)
+#define ESAI_ECR_ERST_SHIFT    1
+#define ESAI_ECR_ERST_MASK     (1 << ESAI_ECR_ERST_SHIFT)
+#define ESAI_ECR_ERST          (1 << ESAI_ECR_ERST_SHIFT)
+#define ESAI_ECR_ESAIEN_SHIFT  0
+#define ESAI_ECR_ESAIEN_MASK   (1 << ESAI_ECR_ESAIEN_SHIFT)
+#define ESAI_ECR_ESAIEN                (1 << ESAI_ECR_ESAIEN_SHIFT)
+
+/* ESAI Status Register -- REG_ESAI_ESR 0xC */
+#define ESAI_ESR_TINIT_SHIFT   10
+#define ESAI_ESR_TINIT_MASK    (1 << ESAI_ESR_TINIT_SHIFT)
+#define ESAI_ESR_TINIT         (1 << ESAI_ESR_TINIT_SHIFT)
+#define ESAI_ESR_RFF_SHIFT     9
+#define ESAI_ESR_RFF_MASK      (1 << ESAI_ESR_RFF_SHIFT)
+#define ESAI_ESR_RFF           (1 << ESAI_ESR_RFF_SHIFT)
+#define ESAI_ESR_TFE_SHIFT     8
+#define ESAI_ESR_TFE_MASK      (1 << ESAI_ESR_TFE_SHIFT)
+#define ESAI_ESR_TFE           (1 << ESAI_ESR_TFE_SHIFT)
+#define ESAI_ESR_TLS_SHIFT     7
+#define ESAI_ESR_TLS_MASK      (1 << ESAI_ESR_TLS_SHIFT)
+#define ESAI_ESR_TLS           (1 << ESAI_ESR_TLS_SHIFT)
+#define ESAI_ESR_TDE_SHIFT     6
+#define ESAI_ESR_TDE_MASK      (1 << ESAI_ESR_TDE_SHIFT)
+#define ESAI_ESR_TDE           (1 << ESAI_ESR_TDE_SHIFT)
+#define ESAI_ESR_TED_SHIFT     5
+#define ESAI_ESR_TED_MASK      (1 << ESAI_ESR_TED_SHIFT)
+#define ESAI_ESR_TED           (1 << ESAI_ESR_TED_SHIFT)
+#define ESAI_ESR_TD_SHIFT      4
+#define ESAI_ESR_TD_MASK       (1 << ESAI_ESR_TD_SHIFT)
+#define ESAI_ESR_TD            (1 << ESAI_ESR_TD_SHIFT)
+#define ESAI_ESR_RLS_SHIFT     3
+#define ESAI_ESR_RLS_MASK      (1 << ESAI_ESR_RLS_SHIFT)
+#define ESAI_ESR_RLS           (1 << ESAI_ESR_RLS_SHIFT)
+#define ESAI_ESR_RDE_SHIFT     2
+#define ESAI_ESR_RDE_MASK      (1 << ESAI_ESR_RDE_SHIFT)
+#define ESAI_ESR_RDE           (1 << ESAI_ESR_RDE_SHIFT)
+#define ESAI_ESR_RED_SHIFT     1
+#define ESAI_ESR_RED_MASK      (1 << ESAI_ESR_RED_SHIFT)
+#define ESAI_ESR_RED           (1 << ESAI_ESR_RED_SHIFT)
+#define ESAI_ESR_RD_SHIFT      0
+#define ESAI_ESR_RD_MASK       (1 << ESAI_ESR_RD_SHIFT)
+#define ESAI_ESR_RD            (1 << ESAI_ESR_RD_SHIFT)
+
+/*
+ * Transmit FIFO Configuration Register -- REG_ESAI_TFCR 0x10
+ * Receive FIFO Configuration Register -- REG_ESAI_RFCR 0x18
+ */
+#define ESAI_xFCR_TIEN_SHIFT   19
+#define ESAI_xFCR_TIEN_MASK    (1 << ESAI_xFCR_TIEN_SHIFT)
+#define ESAI_xFCR_TIEN         (1 << ESAI_xFCR_TIEN_SHIFT)
+#define ESAI_xFCR_REXT_SHIFT   19
+#define ESAI_xFCR_REXT_MASK    (1 << ESAI_xFCR_REXT_SHIFT)
+#define ESAI_xFCR_REXT         (1 << ESAI_xFCR_REXT_SHIFT)
+#define ESAI_xFCR_xWA_SHIFT    16
+#define ESAI_xFCR_xWA_WIDTH    3
+#define ESAI_xFCR_xWA_MASK     (((1 << ESAI_xFCR_xWA_WIDTH) - 1) << ESAI_xFCR_xWA_SHIFT)
+#define ESAI_xFCR_xWA(v)       (((8 - ((v) >> 2)) << ESAI_xFCR_xWA_SHIFT) & ESAI_xFCR_xWA_MASK)
+#define ESAI_xFCR_xFWM_SHIFT   8
+#define ESAI_xFCR_xFWM_WIDTH   8
+#define ESAI_xFCR_xFWM_MASK    (((1 << ESAI_xFCR_xFWM_WIDTH) - 1) << ESAI_xFCR_xFWM_SHIFT)
+#define ESAI_xFCR_xFWM(v)      ((((v) - 1) << ESAI_xFCR_xFWM_SHIFT) & ESAI_xFCR_xFWM_MASK)
+#define ESAI_xFCR_xE_SHIFT     2
+#define ESAI_xFCR_TE_WIDTH     6
+#define ESAI_xFCR_RE_WIDTH     4
+#define ESAI_xFCR_TE_MASK      (((1 << ESAI_xFCR_TE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT)
+#define ESAI_xFCR_RE_MASK      (((1 << ESAI_xFCR_RE_WIDTH) - 1) << ESAI_xFCR_xE_SHIFT)
+#define ESAI_xFCR_TE(x)        ((ESAI_xFCR_TE_MASK >> (ESAI_xFCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_TE_MASK)
+#define ESAI_xFCR_RE(x)        ((ESAI_xFCR_RE_MASK >> (ESAI_xFCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xFCR_RE_MASK)
+#define ESAI_xFCR_xFR_SHIFT    1
+#define ESAI_xFCR_xFR_MASK     (1 << ESAI_xFCR_xFR_SHIFT)
+#define ESAI_xFCR_xFR          (1 << ESAI_xFCR_xFR_SHIFT)
+#define ESAI_xFCR_xFEN_SHIFT   0
+#define ESAI_xFCR_xFEN_MASK    (1 << ESAI_xFCR_xFEN_SHIFT)
+#define ESAI_xFCR_xFEN         (1 << ESAI_xFCR_xFEN_SHIFT)
+
+/*
+ * Transmit FIFO Status Register -- REG_ESAI_TFSR 0x14
+ * Receive FIFO Status Register --REG_ESAI_RFSR 0x1C
+ */
+#define ESAI_xFSR_NTFO_SHIFT   12
+#define ESAI_xFSR_NRFI_SHIFT   12
+#define ESAI_xFSR_NTFI_SHIFT   8
+#define ESAI_xFSR_NRFO_SHIFT   8
+#define ESAI_xFSR_NTFx_WIDTH   3
+#define ESAI_xFSR_NRFx_WIDTH   2
+#define ESAI_xFSR_NTFO_MASK    (((1 << ESAI_xFSR_NTFx_WIDTH) - 1) << ESAI_xFSR_NTFO_SHIFT)
+#define ESAI_xFSR_NTFI_MASK    (((1 << ESAI_xFSR_NTFx_WIDTH) - 1) << ESAI_xFSR_NTFI_SHIFT)
+#define ESAI_xFSR_NRFO_MASK    (((1 << ESAI_xFSR_NRFx_WIDTH) - 1) << ESAI_xFSR_NRFO_SHIFT)
+#define ESAI_xFSR_NRFI_MASK    (((1 << ESAI_xFSR_NRFx_WIDTH) - 1) << ESAI_xFSR_NRFI_SHIFT)
+#define ESAI_xFSR_xFCNT_SHIFT  0
+#define ESAI_xFSR_xFCNT_WIDTH  8
+#define ESAI_xFSR_xFCNT_MASK   (((1 << ESAI_xFSR_xFCNT_WIDTH) - 1) << ESAI_xFSR_xFCNT_SHIFT)
+
+/* ESAI Transmit Slot Register -- REG_ESAI_TSR 0x98 */
+#define ESAI_TSR_SHIFT         0
+#define ESAI_TSR_WIDTH         24
+#define ESAI_TSR_MASK          (((1 << ESAI_TSR_WIDTH) - 1) << ESAI_TSR_SHIFT)
+
+/* Serial Audio Interface Status Register -- REG_ESAI_SAISR 0xCC */
+#define ESAI_SAISR_TODFE_SHIFT 17
+#define ESAI_SAISR_TODFE_MASK  (1 << ESAI_SAISR_TODFE_SHIFT)
+#define ESAI_SAISR_TODFE       (1 << ESAI_SAISR_TODFE_SHIFT)
+#define ESAI_SAISR_TEDE_SHIFT  16
+#define ESAI_SAISR_TEDE_MASK   (1 << ESAI_SAISR_TEDE_SHIFT)
+#define ESAI_SAISR_TEDE                (1 << ESAI_SAISR_TEDE_SHIFT)
+#define ESAI_SAISR_TDE_SHIFT   15
+#define ESAI_SAISR_TDE_MASK    (1 << ESAI_SAISR_TDE_SHIFT)
+#define ESAI_SAISR_TDE         (1 << ESAI_SAISR_TDE_SHIFT)
+#define ESAI_SAISR_TUE_SHIFT   14
+#define ESAI_SAISR_TUE_MASK    (1 << ESAI_SAISR_TUE_SHIFT)
+#define ESAI_SAISR_TUE         (1 << ESAI_SAISR_TUE_SHIFT)
+#define ESAI_SAISR_TFS_SHIFT   13
+#define ESAI_SAISR_TFS_MASK    (1 << ESAI_SAISR_TFS_SHIFT)
+#define ESAI_SAISR_TFS         (1 << ESAI_SAISR_TFS_SHIFT)
+#define ESAI_SAISR_RODF_SHIFT  10
+#define ESAI_SAISR_RODF_MASK   (1 << ESAI_SAISR_RODF_SHIFT)
+#define ESAI_SAISR_RODF                (1 << ESAI_SAISR_RODF_SHIFT)
+#define ESAI_SAISR_REDF_SHIFT  9
+#define ESAI_SAISR_REDF_MASK   (1 << ESAI_SAISR_REDF_SHIFT)
+#define ESAI_SAISR_REDF                (1 << ESAI_SAISR_REDF_SHIFT)
+#define ESAI_SAISR_RDF_SHIFT   8
+#define ESAI_SAISR_RDF_MASK    (1 << ESAI_SAISR_RDF_SHIFT)
+#define ESAI_SAISR_RDF         (1 << ESAI_SAISR_RDF_SHIFT)
+#define ESAI_SAISR_ROE_SHIFT   7
+#define ESAI_SAISR_ROE_MASK    (1 << ESAI_SAISR_ROE_SHIFT)
+#define ESAI_SAISR_ROE         (1 << ESAI_SAISR_ROE_SHIFT)
+#define ESAI_SAISR_RFS_SHIFT   6
+#define ESAI_SAISR_RFS_MASK    (1 << ESAI_SAISR_RFS_SHIFT)
+#define ESAI_SAISR_RFS         (1 << ESAI_SAISR_RFS_SHIFT)
+#define ESAI_SAISR_IF2_SHIFT   2
+#define ESAI_SAISR_IF2_MASK    (1 << ESAI_SAISR_IF2_SHIFT)
+#define ESAI_SAISR_IF2         (1 << ESAI_SAISR_IF2_SHIFT)
+#define ESAI_SAISR_IF1_SHIFT   1
+#define ESAI_SAISR_IF1_MASK    (1 << ESAI_SAISR_IF1_SHIFT)
+#define ESAI_SAISR_IF1         (1 << ESAI_SAISR_IF1_SHIFT)
+#define ESAI_SAISR_IF0_SHIFT   0
+#define ESAI_SAISR_IF0_MASK    (1 << ESAI_SAISR_IF0_SHIFT)
+#define ESAI_SAISR_IF0         (1 << ESAI_SAISR_IF0_SHIFT)
+
+/* Serial Audio Interface Control Register -- REG_ESAI_SAICR 0xD0 */
+#define ESAI_SAICR_ALC_SHIFT   8
+#define ESAI_SAICR_ALC_MASK    (1 << ESAI_SAICR_ALC_SHIFT)
+#define ESAI_SAICR_ALC         (1 << ESAI_SAICR_ALC_SHIFT)
+#define ESAI_SAICR_TEBE_SHIFT  7
+#define ESAI_SAICR_TEBE_MASK   (1 << ESAI_SAICR_TEBE_SHIFT)
+#define ESAI_SAICR_TEBE                (1 << ESAI_SAICR_TEBE_SHIFT)
+#define ESAI_SAICR_SYNC_SHIFT  6
+#define ESAI_SAICR_SYNC_MASK   (1 << ESAI_SAICR_SYNC_SHIFT)
+#define ESAI_SAICR_SYNC                (1 << ESAI_SAICR_SYNC_SHIFT)
+#define ESAI_SAICR_OF2_SHIFT   2
+#define ESAI_SAICR_OF2_MASK    (1 << ESAI_SAICR_OF2_SHIFT)
+#define ESAI_SAICR_OF2         (1 << ESAI_SAICR_OF2_SHIFT)
+#define ESAI_SAICR_OF1_SHIFT   1
+#define ESAI_SAICR_OF1_MASK    (1 << ESAI_SAICR_OF1_SHIFT)
+#define ESAI_SAICR_OF1         (1 << ESAI_SAICR_OF1_SHIFT)
+#define ESAI_SAICR_OF0_SHIFT   0
+#define ESAI_SAICR_OF0_MASK    (1 << ESAI_SAICR_OF0_SHIFT)
+#define ESAI_SAICR_OF0         (1 << ESAI_SAICR_OF0_SHIFT)
+
+/*
+ * Transmit Control Register -- REG_ESAI_TCR 0xD4
+ * Receive Control Register -- REG_ESAI_RCR 0xDC
+ */
+#define ESAI_xCR_xLIE_SHIFT    23
+#define ESAI_xCR_xLIE_MASK     (1 << ESAI_xCR_xLIE_SHIFT)
+#define ESAI_xCR_xLIE          (1 << ESAI_xCR_xLIE_SHIFT)
+#define ESAI_xCR_xIE_SHIFT     22
+#define ESAI_xCR_xIE_MASK      (1 << ESAI_xCR_xIE_SHIFT)
+#define ESAI_xCR_xIE           (1 << ESAI_xCR_xIE_SHIFT)
+#define ESAI_xCR_xEDIE_SHIFT   21
+#define ESAI_xCR_xEDIE_MASK    (1 << ESAI_xCR_xEDIE_SHIFT)
+#define ESAI_xCR_xEDIE         (1 << ESAI_xCR_xEDIE_SHIFT)
+#define ESAI_xCR_xEIE_SHIFT    20
+#define ESAI_xCR_xEIE_MASK     (1 << ESAI_xCR_xEIE_SHIFT)
+#define ESAI_xCR_xEIE          (1 << ESAI_xCR_xEIE_SHIFT)
+#define ESAI_xCR_xPR_SHIFT     19
+#define ESAI_xCR_xPR_MASK      (1 << ESAI_xCR_xPR_SHIFT)
+#define ESAI_xCR_xPR           (1 << ESAI_xCR_xPR_SHIFT)
+#define ESAI_xCR_PADC_SHIFT    17
+#define ESAI_xCR_PADC_MASK     (1 << ESAI_xCR_PADC_SHIFT)
+#define ESAI_xCR_PADC          (1 << ESAI_xCR_PADC_SHIFT)
+#define ESAI_xCR_xFSR_SHIFT    16
+#define ESAI_xCR_xFSR_MASK     (1 << ESAI_xCR_xFSR_SHIFT)
+#define ESAI_xCR_xFSR          (1 << ESAI_xCR_xFSR_SHIFT)
+#define ESAI_xCR_xFSL_SHIFT    15
+#define ESAI_xCR_xFSL_MASK     (1 << ESAI_xCR_xFSL_SHIFT)
+#define ESAI_xCR_xFSL          (1 << ESAI_xCR_xFSL_SHIFT)
+#define ESAI_xCR_xSWS_SHIFT    10
+#define ESAI_xCR_xSWS_WIDTH    5
+#define ESAI_xCR_xSWS_MASK     (((1 << ESAI_xCR_xSWS_WIDTH) - 1) << ESAI_xCR_xSWS_SHIFT)
+#define ESAI_xCR_xSWS(s, w)    ((w < 24 ? (s - w + ((w - 8) >> 2)) : (s < 32 ? 0x1e : 0x1f)) << ESAI_xCR_xSWS_SHIFT)
+#define ESAI_xCR_xMOD_SHIFT    8
+#define ESAI_xCR_xMOD_WIDTH    2
+#define ESAI_xCR_xMOD_MASK     (((1 << ESAI_xCR_xMOD_WIDTH) - 1) << ESAI_xCR_xMOD_SHIFT)
+#define ESAI_xCR_xMOD_ONDEMAND (0x1 << ESAI_xCR_xMOD_SHIFT)
+#define ESAI_xCR_xMOD_NETWORK  (0x1 << ESAI_xCR_xMOD_SHIFT)
+#define ESAI_xCR_xMOD_AC97     (0x3 << ESAI_xCR_xMOD_SHIFT)
+#define ESAI_xCR_xWA_SHIFT     7
+#define ESAI_xCR_xWA_MASK      (1 << ESAI_xCR_xWA_SHIFT)
+#define ESAI_xCR_xWA           (1 << ESAI_xCR_xWA_SHIFT)
+#define ESAI_xCR_xSHFD_SHIFT   6
+#define ESAI_xCR_xSHFD_MASK    (1 << ESAI_xCR_xSHFD_SHIFT)
+#define ESAI_xCR_xSHFD         (1 << ESAI_xCR_xSHFD_SHIFT)
+#define ESAI_xCR_xE_SHIFT      0
+#define ESAI_xCR_TE_WIDTH      6
+#define ESAI_xCR_RE_WIDTH      4
+#define ESAI_xCR_TE_MASK       (((1 << ESAI_xCR_TE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT)
+#define ESAI_xCR_RE_MASK       (((1 << ESAI_xCR_RE_WIDTH) - 1) << ESAI_xCR_xE_SHIFT)
+#define ESAI_xCR_TE(x)                 ((ESAI_xCR_TE_MASK >> (ESAI_xCR_TE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_TE_MASK)
+#define ESAI_xCR_RE(x)                 ((ESAI_xCR_RE_MASK >> (ESAI_xCR_RE_WIDTH - ((x + 1) >> 1))) & ESAI_xCR_RE_MASK)
+
+/*
+ * Transmit Clock Control Register -- REG_ESAI_TCCR 0xD8
+ * Receive Clock Control Register -- REG_ESAI_RCCR 0xE0
+ */
+#define ESAI_xCCR_xHCKD_SHIFT  23
+#define ESAI_xCCR_xHCKD_MASK   (1 << ESAI_xCCR_xHCKD_SHIFT)
+#define ESAI_xCCR_xHCKD                (1 << ESAI_xCCR_xHCKD_SHIFT)
+#define ESAI_xCCR_xFSD_SHIFT   22
+#define ESAI_xCCR_xFSD_MASK    (1 << ESAI_xCCR_xFSD_SHIFT)
+#define ESAI_xCCR_xFSD         (1 << ESAI_xCCR_xFSD_SHIFT)
+#define ESAI_xCCR_xCKD_SHIFT   21
+#define ESAI_xCCR_xCKD_MASK    (1 << ESAI_xCCR_xCKD_SHIFT)
+#define ESAI_xCCR_xCKD         (1 << ESAI_xCCR_xCKD_SHIFT)
+#define ESAI_xCCR_xHCKP_SHIFT  20
+#define ESAI_xCCR_xHCKP_MASK   (1 << ESAI_xCCR_xHCKP_SHIFT)
+#define ESAI_xCCR_xHCKP                (1 << ESAI_xCCR_xHCKP_SHIFT)
+#define ESAI_xCCR_xFSP_SHIFT   19
+#define ESAI_xCCR_xFSP_MASK    (1 << ESAI_xCCR_xFSP_SHIFT)
+#define ESAI_xCCR_xFSP         (1 << ESAI_xCCR_xFSP_SHIFT)
+#define ESAI_xCCR_xCKP_SHIFT   18
+#define ESAI_xCCR_xCKP_MASK    (1 << ESAI_xCCR_xCKP_SHIFT)
+#define ESAI_xCCR_xCKP         (1 << ESAI_xCCR_xCKP_SHIFT)
+#define ESAI_xCCR_xFP_SHIFT    14
+#define ESAI_xCCR_xFP_WIDTH    4
+#define ESAI_xCCR_xFP_MASK     (((1 << ESAI_xCCR_xFP_WIDTH) - 1) << ESAI_xCCR_xFP_SHIFT)
+#define ESAI_xCCR_xFP(v)       ((((v) - 1) << ESAI_xCCR_xFP_SHIFT) & ESAI_xCCR_xFP_MASK)
+#define ESAI_xCCR_xDC_SHIFT     9
+#define ESAI_xCCR_xDC_WIDTH    4
+#define ESAI_xCCR_xDC_MASK     (((1 << ESAI_xCCR_xDC_WIDTH) - 1) << ESAI_xCCR_xDC_SHIFT)
+#define ESAI_xCCR_xDC(v)       ((((v) - 1) << ESAI_xCCR_xDC_SHIFT) & ESAI_xCCR_xDC_MASK)
+#define ESAI_xCCR_xPSR_SHIFT   8
+#define ESAI_xCCR_xPSR_MASK    (1 << ESAI_xCCR_xPSR_SHIFT)
+#define ESAI_xCCR_xPSR_BYPASS  (1 << ESAI_xCCR_xPSR_SHIFT)
+#define ESAI_xCCR_xPSR_DIV8    (0 << ESAI_xCCR_xPSR_SHIFT)
+#define ESAI_xCCR_xPM_SHIFT     0
+#define ESAI_xCCR_xPM_WIDTH     8
+#define ESAI_xCCR_xPM_MASK     (((1 << ESAI_xCCR_xPM_WIDTH) - 1) << ESAI_xCCR_xPM_SHIFT)
+#define ESAI_xCCR_xPM(v)       ((((v) - 1) << ESAI_xCCR_xPM_SHIFT) & ESAI_xCCR_xPM_MASK)
+
+/* Transmit Slot Mask Register A/B -- REG_ESAI_TSMA/B 0xE4 ~ 0xF0 */
+#define ESAI_xSMA_xS_SHIFT     0
+#define ESAI_xSMA_xS_WIDTH     16
+#define ESAI_xSMA_xS_MASK      (((1 << ESAI_xSMA_xS_WIDTH) - 1) << ESAI_xSMA_xS_SHIFT)
+#define ESAI_xSMA_xS(v)                ((v) & ESAI_xSMA_xS_MASK)
+#define ESAI_xSMB_xS_SHIFT     0
+#define ESAI_xSMB_xS_WIDTH     16
+#define ESAI_xSMB_xS_MASK      (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT)
+#define ESAI_xSMB_xS(v)                (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK)
+
+/* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */
+#define ESAI_PRRC_PDC_SHIFT    0
+#define ESAI_PRRC_PDC_WIDTH    12
+#define ESAI_PRRC_PDC_MASK     (((1 << ESAI_PRRC_PDC_WIDTH) - 1) << ESAI_PRRC_PDC_SHIFT)
+#define ESAI_PRRC_PDC(v)       ((v) & ESAI_PRRC_PDC_MASK)
+
+/* Port C Control Register -- REG_ESAI_PCRC 0xFC */
+#define ESAI_PCRC_PC_SHIFT     0
+#define ESAI_PCRC_PC_WIDTH     12
+#define ESAI_PCRC_PC_MASK      (((1 << ESAI_PCRC_PC_WIDTH) - 1) << ESAI_PCRC_PC_SHIFT)
+#define ESAI_PCRC_PC(v)                ((v) & ESAI_PCRC_PC_MASK)
+
+#define ESAI_GPIO              0xfff
+
+/* ESAI clock source */
+#define ESAI_HCKT_FSYS         0
+#define ESAI_HCKT_EXTAL                1
+#define ESAI_HCKR_FSYS         2
+#define ESAI_HCKR_EXTAL                3
+
+/* ESAI clock divider */
+#define ESAI_TX_DIV_PSR                0
+#define ESAI_TX_DIV_PM         1
+#define ESAI_TX_DIV_FP         2
+#define ESAI_RX_DIV_PSR                3
+#define ESAI_RX_DIV_PM         4
+#define ESAI_RX_DIV_FP         5
+#endif /* _FSL_ESAI_DAI_H */
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
new file mode 100644 (file)
index 0000000..cdd3fa8
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * Freescale ALSA SoC Digital Audio Interface (SAI) driver.
+ *
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software, you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or(at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
+
+#include "fsl_sai.h"
+
+static inline u32 sai_readl(struct fsl_sai *sai,
+               const void __iomem *addr)
+{
+       u32 val;
+
+       val = __raw_readl(addr);
+
+       if (likely(sai->big_endian_regs))
+               val = be32_to_cpu(val);
+       else
+               val = le32_to_cpu(val);
+       rmb();
+
+       return val;
+}
+
+static inline void sai_writel(struct fsl_sai *sai,
+               u32 val, void __iomem *addr)
+{
+       wmb();
+       if (likely(sai->big_endian_regs))
+               val = cpu_to_be32(val);
+       else
+               val = cpu_to_le32(val);
+
+       __raw_writel(val, addr);
+}
+
+static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
+               int clk_id, unsigned int freq, int fsl_dir)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       u32 val_cr2, reg_cr2;
+
+       if (fsl_dir == FSL_FMT_TRANSMITTER)
+               reg_cr2 = FSL_SAI_TCR2;
+       else
+               reg_cr2 = FSL_SAI_RCR2;
+
+       val_cr2 = sai_readl(sai, sai->base + reg_cr2);
+       val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
+
+       switch (clk_id) {
+       case FSL_SAI_CLK_BUS:
+               val_cr2 |= FSL_SAI_CR2_MSEL_BUS;
+               break;
+       case FSL_SAI_CLK_MAST1:
+               val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1;
+               break;
+       case FSL_SAI_CLK_MAST2:
+               val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2;
+               break;
+       case FSL_SAI_CLK_MAST3:
+               val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       sai_writel(sai, val_cr2, sai->base + reg_cr2);
+
+       return 0;
+}
+
+static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret;
+
+       if (dir == SND_SOC_CLOCK_IN)
+               return 0;
+
+       ret = clk_prepare_enable(sai->clk);
+       if (ret)
+               return ret;
+
+       ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
+                                       FSL_FMT_TRANSMITTER);
+       if (ret) {
+               dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
+               goto err_clk;
+       }
+
+       ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
+                                       FSL_FMT_RECEIVER);
+       if (ret) {
+               dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret);
+               goto err_clk;
+       }
+
+err_clk:
+       clk_disable_unprepare(sai->clk);
+
+       return ret;
+}
+
+static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
+                               unsigned int fmt, int fsl_dir)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       u32 val_cr2, val_cr4, reg_cr2, reg_cr4;
+
+       if (fsl_dir == FSL_FMT_TRANSMITTER) {
+               reg_cr2 = FSL_SAI_TCR2;
+               reg_cr4 = FSL_SAI_TCR4;
+       } else {
+               reg_cr2 = FSL_SAI_RCR2;
+               reg_cr4 = FSL_SAI_RCR4;
+       }
+
+       val_cr2 = sai_readl(sai, sai->base + reg_cr2);
+       val_cr4 = sai_readl(sai, sai->base + reg_cr4);
+
+       if (sai->big_endian_data)
+               val_cr4 &= ~FSL_SAI_CR4_MF;
+       else
+               val_cr4 |= FSL_SAI_CR4_MF;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               val_cr4 |= FSL_SAI_CR4_FSE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               val_cr4 |= FSL_SAI_CR4_FSP;
+               val_cr2 &= ~FSL_SAI_CR2_BCP;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               val_cr4 &= ~FSL_SAI_CR4_FSP;
+               val_cr2 &= ~FSL_SAI_CR2_BCP;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               val_cr4 |= FSL_SAI_CR4_FSP;
+               val_cr2 |= FSL_SAI_CR2_BCP;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
+               val_cr4 &= ~FSL_SAI_CR4_FSP;
+               val_cr2 |= FSL_SAI_CR2_BCP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
+               val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
+               val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       sai_writel(sai, val_cr2, sai->base + reg_cr2);
+       sai_writel(sai, val_cr4, sai->base + reg_cr4);
+
+       return 0;
+}
+
+static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret;
+
+       ret = clk_prepare_enable(sai->clk);
+       if (ret)
+               return ret;
+
+       ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
+       if (ret) {
+               dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
+               goto err_clk;
+       }
+
+       ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
+       if (ret) {
+               dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
+               goto err_clk;
+       }
+
+err_clk:
+       clk_disable_unprepare(sai->clk);
+
+       return ret;
+}
+
+static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params,
+               struct snd_soc_dai *cpu_dai)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr;
+       unsigned int channels = params_channels(params);
+       u32 word_width = snd_pcm_format_width(params_format(params));
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               reg_cr4 = FSL_SAI_TCR4;
+               reg_cr5 = FSL_SAI_TCR5;
+               reg_mr = FSL_SAI_TMR;
+       } else {
+               reg_cr4 = FSL_SAI_RCR4;
+               reg_cr5 = FSL_SAI_RCR5;
+               reg_mr = FSL_SAI_RMR;
+       }
+
+       val_cr4 = sai_readl(sai, sai->base + reg_cr4);
+       val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
+       val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
+
+       val_cr5 = sai_readl(sai, sai->base + reg_cr5);
+       val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
+       val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
+       val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
+
+       val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
+       val_cr5 |= FSL_SAI_CR5_WNW(word_width);
+       val_cr5 |= FSL_SAI_CR5_W0W(word_width);
+
+       val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
+       if (sai->big_endian_data)
+               val_cr5 |= FSL_SAI_CR5_FBT(0);
+       else
+               val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
+
+       val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
+       val_mr = ~0UL - ((1 << channels) - 1);
+
+       sai_writel(sai, val_cr4, sai->base + reg_cr4);
+       sai_writel(sai, val_cr5, sai->base + reg_cr5);
+       sai_writel(sai, val_mr, sai->base + reg_mr);
+
+       return 0;
+}
+
+static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
+               struct snd_soc_dai *cpu_dai)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3;
+
+       val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2);
+       val_cr2 &= ~FSL_SAI_CR2_SYNC;
+       sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2);
+
+       val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2);
+       val_cr2 |= FSL_SAI_CR2_SYNC;
+       sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2);
+
+       tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR);
+       rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               tcsr |= FSL_SAI_CSR_FRDE;
+               rcsr &= ~FSL_SAI_CSR_FRDE;
+               reg_cr3 = FSL_SAI_TCR3;
+       } else {
+               rcsr |= FSL_SAI_CSR_FRDE;
+               tcsr &= ~FSL_SAI_CSR_FRDE;
+               reg_cr3 = FSL_SAI_RCR3;
+       }
+
+       val_cr3 = sai_readl(sai, sai->base + reg_cr3);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               tcsr |= FSL_SAI_CSR_TERE;
+               rcsr |= FSL_SAI_CSR_TERE;
+               val_cr3 |= FSL_SAI_CR3_TRCE;
+
+               sai_writel(sai, val_cr3, sai->base + reg_cr3);
+               sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR);
+               sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (!(cpu_dai->playback_active || cpu_dai->capture_active)) {
+                       tcsr &= ~FSL_SAI_CSR_TERE;
+                       rcsr &= ~FSL_SAI_CSR_TERE;
+               }
+
+               val_cr3 &= ~FSL_SAI_CR3_TRCE;
+
+               sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR);
+               sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR);
+               sai_writel(sai, val_cr3, sai->base + reg_cr3);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int fsl_sai_startup(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *cpu_dai)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+       return clk_prepare_enable(sai->clk);
+}
+
+static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *cpu_dai)
+{
+       struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+       clk_disable_unprepare(sai->clk);
+}
+
+static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
+       .set_sysclk     = fsl_sai_set_dai_sysclk,
+       .set_fmt        = fsl_sai_set_dai_fmt,
+       .hw_params      = fsl_sai_hw_params,
+       .trigger        = fsl_sai_trigger,
+       .startup        = fsl_sai_startup,
+       .shutdown       = fsl_sai_shutdown,
+};
+
+static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
+{
+       struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
+       int ret;
+
+       ret = clk_prepare_enable(sai->clk);
+       if (ret)
+               return ret;
+
+       sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR);
+       sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR);
+       sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1);
+       sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1);
+
+       clk_disable_unprepare(sai->clk);
+
+       snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
+                               &sai->dma_params_rx);
+
+       snd_soc_dai_set_drvdata(cpu_dai, sai);
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver fsl_sai_dai = {
+       .probe = fsl_sai_dai_probe,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = FSL_SAI_FORMATS,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = FSL_SAI_FORMATS,
+       },
+       .ops = &fsl_sai_pcm_dai_ops,
+};
+
+static const struct snd_soc_component_driver fsl_component = {
+       .name           = "fsl-sai",
+};
+
+static int fsl_sai_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct fsl_sai *sai;
+       struct resource *res;
+       int ret;
+
+       sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
+       if (!sai)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       sai->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(sai->base))
+               return PTR_ERR(sai->base);
+
+       sai->clk = devm_clk_get(&pdev->dev, "sai");
+       if (IS_ERR(sai->clk)) {
+               dev_err(&pdev->dev, "Cannot get SAI's clock\n");
+               return PTR_ERR(sai->clk);
+       }
+
+       sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
+       sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
+       sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
+       sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
+
+       sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
+       sai->big_endian_data = of_property_read_bool(np, "big-endian-data");
+
+       platform_set_drvdata(pdev, sai);
+
+       ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
+                       &fsl_sai_dai, 1);
+       if (ret)
+               return ret;
+
+       return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+                       SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
+}
+
+static const struct of_device_id fsl_sai_ids[] = {
+       { .compatible = "fsl,vf610-sai", },
+       { /* sentinel */ }
+};
+
+static struct platform_driver fsl_sai_driver = {
+       .probe = fsl_sai_probe,
+       .driver = {
+               .name = "fsl-sai",
+               .owner = THIS_MODULE,
+               .of_match_table = fsl_sai_ids,
+       },
+};
+module_platform_driver(fsl_sai_driver);
+
+MODULE_DESCRIPTION("Freescale Soc SAI Interface");
+MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
+MODULE_ALIAS("platform:fsl-sai");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
new file mode 100644 (file)
index 0000000..41bb62e
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __FSL_SAI_H
+#define __FSL_SAI_H
+
+#include <sound/dmaengine_pcm.h>
+
+#define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                        SNDRV_PCM_FMTBIT_S20_3LE |\
+                        SNDRV_PCM_FMTBIT_S24_LE)
+
+/* SAI Transmit/Recieve Control Register */
+#define FSL_SAI_TCSR           0x00
+#define FSL_SAI_RCSR           0x80
+#define FSL_SAI_CSR_TERE       BIT(31)
+#define FSL_SAI_CSR_FWF                BIT(17)
+#define FSL_SAI_CSR_FRIE       BIT(8)
+#define FSL_SAI_CSR_FRDE       BIT(0)
+
+/* SAI Transmit Data/FIFO/MASK Register */
+#define FSL_SAI_TDR            0x20
+#define FSL_SAI_TFR            0x40
+#define FSL_SAI_TMR            0x60
+
+/* SAI Recieve Data/FIFO/MASK Register */
+#define FSL_SAI_RDR            0xa0
+#define FSL_SAI_RFR            0xc0
+#define FSL_SAI_RMR            0xe0
+
+/* SAI Transmit and Recieve Configuration 1 Register */
+#define FSL_SAI_TCR1           0x04
+#define FSL_SAI_RCR1           0x84
+
+/* SAI Transmit and Recieve Configuration 2 Register */
+#define FSL_SAI_TCR2           0x08
+#define FSL_SAI_RCR2           0x88
+#define FSL_SAI_CR2_SYNC       BIT(30)
+#define FSL_SAI_CR2_MSEL_MASK  (0xff << 26)
+#define FSL_SAI_CR2_MSEL_BUS   0
+#define FSL_SAI_CR2_MSEL_MCLK1 BIT(26)
+#define FSL_SAI_CR2_MSEL_MCLK2 BIT(27)
+#define FSL_SAI_CR2_MSEL_MCLK3 (BIT(26) | BIT(27))
+#define FSL_SAI_CR2_BCP                BIT(25)
+#define FSL_SAI_CR2_BCD_MSTR   BIT(24)
+
+/* SAI Transmit and Recieve Configuration 3 Register */
+#define FSL_SAI_TCR3           0x0c
+#define FSL_SAI_RCR3           0x8c
+#define FSL_SAI_CR3_TRCE       BIT(16)
+#define FSL_SAI_CR3_WDFL(x)    (x)
+#define FSL_SAI_CR3_WDFL_MASK  0x1f
+
+/* SAI Transmit and Recieve Configuration 4 Register */
+#define FSL_SAI_TCR4           0x10
+#define FSL_SAI_RCR4           0x90
+#define FSL_SAI_CR4_FRSZ(x)    (((x) - 1) << 16)
+#define FSL_SAI_CR4_FRSZ_MASK  (0x1f << 16)
+#define FSL_SAI_CR4_SYWD(x)    (((x) - 1) << 8)
+#define FSL_SAI_CR4_SYWD_MASK  (0x1f << 8)
+#define FSL_SAI_CR4_MF         BIT(4)
+#define FSL_SAI_CR4_FSE                BIT(3)
+#define FSL_SAI_CR4_FSP                BIT(1)
+#define FSL_SAI_CR4_FSD_MSTR   BIT(0)
+
+/* SAI Transmit and Recieve Configuration 5 Register */
+#define FSL_SAI_TCR5           0x14
+#define FSL_SAI_RCR5           0x94
+#define FSL_SAI_CR5_WNW(x)     (((x) - 1) << 24)
+#define FSL_SAI_CR5_WNW_MASK   (0x1f << 24)
+#define FSL_SAI_CR5_W0W(x)     (((x) - 1) << 16)
+#define FSL_SAI_CR5_W0W_MASK   (0x1f << 16)
+#define FSL_SAI_CR5_FBT(x)     ((x) << 8)
+#define FSL_SAI_CR5_FBT_MASK   (0x1f << 8)
+
+/* SAI type */
+#define FSL_SAI_DMA            BIT(0)
+#define FSL_SAI_USE_AC97       BIT(1)
+#define FSL_SAI_NET            BIT(2)
+#define FSL_SAI_TRA_SYN                BIT(3)
+#define FSL_SAI_REC_SYN                BIT(4)
+#define FSL_SAI_USE_I2S_SLAVE  BIT(5)
+
+#define FSL_FMT_TRANSMITTER    0
+#define FSL_FMT_RECEIVER       1
+
+/* SAI clock sources */
+#define FSL_SAI_CLK_BUS                0
+#define FSL_SAI_CLK_MAST1      1
+#define FSL_SAI_CLK_MAST2      2
+#define FSL_SAI_CLK_MAST3      3
+
+/* SAI data transfer numbers per DMA request */
+#define FSL_SAI_MAXBURST_TX 6
+#define FSL_SAI_MAXBURST_RX 6
+
+struct fsl_sai {
+       struct clk *clk;
+
+       void __iomem *base;
+
+       bool big_endian_regs;
+       bool big_endian_data;
+
+       struct snd_dmaengine_dai_dma_data dma_params_rx;
+       struct snd_dmaengine_dai_dma_data dma_params_tx;
+};
+
+#endif /* __FSL_SAI_H */
index 55193a5596ca6fe4aa3b0c53170d71f4f1a6c355..4d075f1abe7803387bb01dbb39a2d66a0eac4c59 100644 (file)
@@ -1181,13 +1181,6 @@ static int fsl_spdif_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int fsl_spdif_remove(struct platform_device *pdev)
-{
-       imx_pcm_dma_exit(pdev);
-
-       return 0;
-}
-
 static const struct of_device_id fsl_spdif_dt_ids[] = {
        { .compatible = "fsl,imx35-spdif", },
        {}
@@ -1201,7 +1194,6 @@ static struct platform_driver fsl_spdif_driver = {
                .of_match_table = fsl_spdif_dt_ids,
        },
        .probe = fsl_spdif_probe,
-       .remove = fsl_spdif_remove,
 };
 
 module_platform_driver(fsl_spdif_driver);
index 35e277379b86ce80d56737e3e0c05a5b3772fb2c..f9090b167ad7c1ba2c3e91f1af2e042356c25841 100644 (file)
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
@@ -79,8 +81,7 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
  * ALSA that we support all rates and let the codec driver decide what rates
  * are really supported.
  */
-#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
-                         SNDRV_PCM_RATE_CONTINUOUS)
+#define FSLSSI_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
 
 /**
  * FSLSSI_I2S_FORMATS: audio formats supported by the SSI
@@ -106,12 +107,33 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
-/* SIER bitflag of interrupts to enable */
-#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
-                   CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
-                   CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
-                   CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
-                   CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
+#define FSLSSI_SIER_DBG_RX_FLAGS (CCSR_SSI_SIER_RFF0_EN | \
+               CCSR_SSI_SIER_RLS_EN | CCSR_SSI_SIER_RFS_EN | \
+               CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_RFRC_EN)
+#define FSLSSI_SIER_DBG_TX_FLAGS (CCSR_SSI_SIER_TFE0_EN | \
+               CCSR_SSI_SIER_TLS_EN | CCSR_SSI_SIER_TFS_EN | \
+               CCSR_SSI_SIER_TUE0_EN | CCSR_SSI_SIER_TFRC_EN)
+#define FSLSSI_SISR_MASK (FSLSSI_SIER_DBG_RX_FLAGS | FSLSSI_SIER_DBG_TX_FLAGS)
+
+
+enum fsl_ssi_type {
+       FSL_SSI_MCP8610,
+       FSL_SSI_MX21,
+       FSL_SSI_MX35,
+       FSL_SSI_MX51,
+};
+
+struct fsl_ssi_reg_val {
+       u32 sier;
+       u32 srcr;
+       u32 stcr;
+       u32 scr;
+};
+
+struct fsl_ssi_rxtx_reg_val {
+       struct fsl_ssi_reg_val rx;
+       struct fsl_ssi_reg_val tx;
+};
 
 /**
  * fsl_ssi_private: per-SSI private data
@@ -119,8 +141,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
  * @ssi: pointer to the SSI's registers
  * @ssi_phys: physical address of the SSI registers
  * @irq: IRQ of this SSI
- * @first_stream: pointer to the stream that was opened first
- * @second_stream: pointer to second stream
  * @playback: the number of playback streams opened
  * @capture: the number of capture streams opened
  * @cpu_dai: the CPU DAI for this device
@@ -132,23 +152,29 @@ struct fsl_ssi_private {
        struct ccsr_ssi __iomem *ssi;
        dma_addr_t ssi_phys;
        unsigned int irq;
-       struct snd_pcm_substream *first_stream;
-       struct snd_pcm_substream *second_stream;
        unsigned int fifo_depth;
        struct snd_soc_dai_driver cpu_dai_drv;
-       struct device_attribute dev_attr;
        struct platform_device *pdev;
 
+       enum fsl_ssi_type hw_type;
        bool new_binding;
        bool ssi_on_imx;
        bool imx_ac97;
        bool use_dma;
+       bool baudclk_locked;
+       bool irq_stats;
+       bool offline_config;
+       u8 i2s_mode;
+       spinlock_t baudclk_lock;
+       struct clk *baudclk;
        struct clk *clk;
        struct snd_dmaengine_dai_dma_data dma_params_tx;
        struct snd_dmaengine_dai_dma_data dma_params_rx;
        struct imx_dma_data filter_data_tx;
        struct imx_dma_data filter_data_rx;
        struct imx_pcm_fiq_params fiq_params;
+       /* Register values for rx/tx configuration */
+       struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
 
        struct {
                unsigned int rfrc;
@@ -173,10 +199,21 @@ struct fsl_ssi_private {
                unsigned int tfe1;
                unsigned int tfe0;
        } stats;
+       struct dentry *dbg_dir;
+       struct dentry *dbg_stats;
 
        char name[1];
 };
 
+static const struct of_device_id fsl_ssi_ids[] = {
+       { .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610},
+       { .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51},
+       { .compatible = "fsl,imx35-ssi", .data = (void *) FSL_SSI_MX35},
+       { .compatible = "fsl,imx21-ssi", .data = (void *) FSL_SSI_MX21},
+       {}
+};
+MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
+
 /**
  * fsl_ssi_isr: SSI interrupt handler
  *
@@ -195,23 +232,40 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
        irqreturn_t ret = IRQ_NONE;
        __be32 sisr;
-       __be32 sisr2 = 0;
+       __be32 sisr2;
+       __be32 sisr_write_mask = 0;
+
+       switch (ssi_private->hw_type) {
+       case FSL_SSI_MX21:
+               sisr_write_mask = 0;
+               break;
+
+       case FSL_SSI_MCP8610:
+       case FSL_SSI_MX35:
+               sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
+                       CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
+                       CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1;
+               break;
+
+       case FSL_SSI_MX51:
+               sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
+                       CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1;
+               break;
+       }
 
        /* We got an interrupt, so read the status register to see what we
           were interrupted for.  We mask it with the Interrupt Enable register
           so that we only check for events that we're interested in.
         */
-       sisr = read_ssi(&ssi->sisr) & SIER_FLAGS;
+       sisr = read_ssi(&ssi->sisr) & FSLSSI_SISR_MASK;
 
        if (sisr & CCSR_SSI_SISR_RFRC) {
                ssi_private->stats.rfrc++;
-               sisr2 |= CCSR_SSI_SISR_RFRC;
                ret = IRQ_HANDLED;
        }
 
        if (sisr & CCSR_SSI_SISR_TFRC) {
                ssi_private->stats.tfrc++;
-               sisr2 |= CCSR_SSI_SISR_TFRC;
                ret = IRQ_HANDLED;
        }
 
@@ -252,25 +306,21 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 
        if (sisr & CCSR_SSI_SISR_ROE1) {
                ssi_private->stats.roe1++;
-               sisr2 |= CCSR_SSI_SISR_ROE1;
                ret = IRQ_HANDLED;
        }
 
        if (sisr & CCSR_SSI_SISR_ROE0) {
                ssi_private->stats.roe0++;
-               sisr2 |= CCSR_SSI_SISR_ROE0;
                ret = IRQ_HANDLED;
        }
 
        if (sisr & CCSR_SSI_SISR_TUE1) {
                ssi_private->stats.tue1++;
-               sisr2 |= CCSR_SSI_SISR_TUE1;
                ret = IRQ_HANDLED;
        }
 
        if (sisr & CCSR_SSI_SISR_TUE0) {
                ssi_private->stats.tue0++;
-               sisr2 |= CCSR_SSI_SISR_TUE0;
                ret = IRQ_HANDLED;
        }
 
@@ -314,6 +364,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
                ret = IRQ_HANDLED;
        }
 
+       sisr2 = sisr & sisr_write_mask;
        /* Clear the bits that we set */
        if (sisr2)
                write_ssi(sisr2, &ssi->sisr);
@@ -321,17 +372,287 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
        return ret;
 }
 
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+/* Show the statistics of a flag only if its interrupt is enabled.  The
+ * compiler will optimze this code to a no-op if the interrupt is not
+ * enabled.
+ */
+#define SIER_SHOW(flag, name) \
+       do { \
+               if (FSLSSI_SISR_MASK & CCSR_SSI_SIER_##flag) \
+                       seq_printf(s, #name "=%u\n", ssi_private->stats.name); \
+       } while (0)
+
+
+/**
+ * fsl_sysfs_ssi_show: display SSI statistics
+ *
+ * Display the statistics for the current SSI device.  To avoid confusion,
+ * we only show those counts that are enabled.
+ */
+static int fsl_ssi_stats_show(struct seq_file *s, void *unused)
+{
+       struct fsl_ssi_private *ssi_private = s->private;
+
+       SIER_SHOW(RFRC_EN, rfrc);
+       SIER_SHOW(TFRC_EN, tfrc);
+       SIER_SHOW(CMDAU_EN, cmdau);
+       SIER_SHOW(CMDDU_EN, cmddu);
+       SIER_SHOW(RXT_EN, rxt);
+       SIER_SHOW(RDR1_EN, rdr1);
+       SIER_SHOW(RDR0_EN, rdr0);
+       SIER_SHOW(TDE1_EN, tde1);
+       SIER_SHOW(TDE0_EN, tde0);
+       SIER_SHOW(ROE1_EN, roe1);
+       SIER_SHOW(ROE0_EN, roe0);
+       SIER_SHOW(TUE1_EN, tue1);
+       SIER_SHOW(TUE0_EN, tue0);
+       SIER_SHOW(TFS_EN, tfs);
+       SIER_SHOW(RFS_EN, rfs);
+       SIER_SHOW(TLS_EN, tls);
+       SIER_SHOW(RLS_EN, rls);
+       SIER_SHOW(RFF1_EN, rff1);
+       SIER_SHOW(RFF0_EN, rff0);
+       SIER_SHOW(TFE1_EN, tfe1);
+       SIER_SHOW(TFE0_EN, tfe0);
+
+       return 0;
+}
+
+static int fsl_ssi_stats_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, fsl_ssi_stats_show, inode->i_private);
+}
+
+static const struct file_operations fsl_ssi_stats_ops = {
+       .open = fsl_ssi_stats_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private,
+               struct device *dev)
+{
+       ssi_private->dbg_dir = debugfs_create_dir(dev_name(dev), NULL);
+       if (!ssi_private->dbg_dir)
+               return -ENOMEM;
+
+       ssi_private->dbg_stats = debugfs_create_file("stats", S_IRUGO,
+                       ssi_private->dbg_dir, ssi_private, &fsl_ssi_stats_ops);
+       if (!ssi_private->dbg_stats) {
+               debugfs_remove(ssi_private->dbg_dir);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
+{
+       debugfs_remove(ssi_private->dbg_stats);
+       debugfs_remove(ssi_private->dbg_dir);
+}
+
+#else
+
+static int fsl_ssi_debugfs_create(struct fsl_ssi_private *ssi_private,
+               struct device *dev)
+{
+       return 0;
+}
+
+static void fsl_ssi_debugfs_remove(struct fsl_ssi_private *ssi_private)
+{
+}
+
+#endif /* IS_ENABLED(CONFIG_DEBUG_FS) */
+
+/*
+ * Enable/Disable all rx/tx config flags at once.
+ */
+static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
+               bool enable)
+{
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       struct fsl_ssi_rxtx_reg_val *vals = &ssi_private->rxtx_reg_val;
+
+       if (enable) {
+               write_ssi_mask(&ssi->sier, 0, vals->rx.sier | vals->tx.sier);
+               write_ssi_mask(&ssi->srcr, 0, vals->rx.srcr | vals->tx.srcr);
+               write_ssi_mask(&ssi->stcr, 0, vals->rx.stcr | vals->tx.stcr);
+       } else {
+               write_ssi_mask(&ssi->srcr, vals->rx.srcr | vals->tx.srcr, 0);
+               write_ssi_mask(&ssi->stcr, vals->rx.stcr | vals->tx.stcr, 0);
+               write_ssi_mask(&ssi->sier, vals->rx.sier | vals->tx.sier, 0);
+       }
+}
+
+/*
+ * Enable/Disable a ssi configuration. You have to pass either
+ * ssi_private->rxtx_reg_val.rx or tx as vals parameter.
+ */
+static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
+               struct fsl_ssi_reg_val *vals)
+{
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       struct fsl_ssi_reg_val *avals;
+       u32 scr_val = read_ssi(&ssi->scr);
+       int nr_active_streams = !!(scr_val & CCSR_SSI_SCR_TE) +
+                               !!(scr_val & CCSR_SSI_SCR_RE);
+
+       /* Find the other direction values rx or tx which we do not want to
+        * modify */
+       if (&ssi_private->rxtx_reg_val.rx == vals)
+               avals = &ssi_private->rxtx_reg_val.tx;
+       else
+               avals = &ssi_private->rxtx_reg_val.rx;
+
+       /* If vals should be disabled, start with disabling the unit */
+       if (!enable) {
+               u32 scr = vals->scr & (vals->scr ^ avals->scr);
+               write_ssi_mask(&ssi->scr, scr, 0);
+       }
+
+       /*
+        * We are running on a SoC which does not support online SSI
+        * reconfiguration, so we have to enable all necessary flags at once
+        * even if we do not use them later (capture and playback configuration)
+        */
+       if (ssi_private->offline_config) {
+               if ((enable && !nr_active_streams) ||
+                               (!enable && nr_active_streams == 1))
+                       fsl_ssi_rxtx_config(ssi_private, enable);
+
+               goto config_done;
+       }
+
+       /*
+        * Configure single direction units while the SSI unit is running
+        * (online configuration)
+        */
+       if (enable) {
+               write_ssi_mask(&ssi->sier, 0, vals->sier);
+               write_ssi_mask(&ssi->srcr, 0, vals->srcr);
+               write_ssi_mask(&ssi->stcr, 0, vals->stcr);
+       } else {
+               u32 sier;
+               u32 srcr;
+               u32 stcr;
+
+               /*
+                * Disabling the necessary flags for one of rx/tx while the
+                * other stream is active is a little bit more difficult. We
+                * have to disable only those flags that differ between both
+                * streams (rx XOR tx) and that are set in the stream that is
+                * disabled now. Otherwise we could alter flags of the other
+                * stream
+                */
+
+               /* These assignments are simply vals without bits set in avals*/
+               sier = vals->sier & (vals->sier ^ avals->sier);
+               srcr = vals->srcr & (vals->srcr ^ avals->srcr);
+               stcr = vals->stcr & (vals->stcr ^ avals->stcr);
+
+               write_ssi_mask(&ssi->srcr, srcr, 0);
+               write_ssi_mask(&ssi->stcr, stcr, 0);
+               write_ssi_mask(&ssi->sier, sier, 0);
+       }
+
+config_done:
+       /* Enabling of subunits is done after configuration */
+       if (enable)
+               write_ssi_mask(&ssi->scr, 0, vals->scr);
+}
+
+
+static void fsl_ssi_rx_config(struct fsl_ssi_private *ssi_private, bool enable)
+{
+       fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.rx);
+}
+
+static void fsl_ssi_tx_config(struct fsl_ssi_private *ssi_private, bool enable)
+{
+       fsl_ssi_config(ssi_private, enable, &ssi_private->rxtx_reg_val.tx);
+}
+
+/*
+ * Setup rx/tx register values used to enable/disable the streams. These will
+ * be used later in fsl_ssi_config to setup the streams without the need to
+ * check for all different SSI modes.
+ */
+static void fsl_ssi_setup_reg_vals(struct fsl_ssi_private *ssi_private)
+{
+       struct fsl_ssi_rxtx_reg_val *reg = &ssi_private->rxtx_reg_val;
+
+       reg->rx.sier = CCSR_SSI_SIER_RFF0_EN;
+       reg->rx.srcr = CCSR_SSI_SRCR_RFEN0;
+       reg->rx.scr = 0;
+       reg->tx.sier = CCSR_SSI_SIER_TFE0_EN;
+       reg->tx.stcr = CCSR_SSI_STCR_TFEN0;
+       reg->tx.scr = 0;
+
+       if (!ssi_private->imx_ac97) {
+               reg->rx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE;
+               reg->rx.sier |= CCSR_SSI_SIER_RFF0_EN;
+               reg->tx.scr = CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE;
+               reg->tx.sier |= CCSR_SSI_SIER_TFE0_EN;
+       }
+
+       if (ssi_private->use_dma) {
+               reg->rx.sier |= CCSR_SSI_SIER_RDMAE;
+               reg->tx.sier |= CCSR_SSI_SIER_TDMAE;
+       } else {
+               reg->rx.sier |= CCSR_SSI_SIER_RIE;
+               reg->tx.sier |= CCSR_SSI_SIER_TIE;
+       }
+
+       reg->rx.sier |= FSLSSI_SIER_DBG_RX_FLAGS;
+       reg->tx.sier |= FSLSSI_SIER_DBG_TX_FLAGS;
+}
+
+static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
+{
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+
+       /*
+        * Setup the clock control register
+        */
+       write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
+                       &ssi->stccr);
+       write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
+                       &ssi->srccr);
+
+       /*
+        * Enable AC97 mode and startup the SSI
+        */
+       write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
+                       &ssi->sacnt);
+       write_ssi(0xff, &ssi->saccdis);
+       write_ssi(0x300, &ssi->saccen);
+
+       /*
+        * Enable SSI, Transmit and Receive. AC97 has to communicate with the
+        * codec before a stream is started.
+        */
+       write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
+                       CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
+
+       write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
+}
+
 static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
 {
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-       u8 i2s_mode;
        u8 wm;
        int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
 
+       fsl_ssi_setup_reg_vals(ssi_private);
+
        if (ssi_private->imx_ac97)
-               i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
+               ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
        else
-               i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
+               ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
 
        /*
         * Section 16.5 of the MPC8610 reference manual says that the SSI needs
@@ -348,16 +669,15 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
        write_ssi_mask(&ssi->scr,
                CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
                CCSR_SSI_SCR_TFR_CLK_DIS |
-               i2s_mode |
+               ssi_private->i2s_mode |
                (synchronous ? CCSR_SSI_SCR_SYN : 0));
 
-       write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
-                CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS |
-                CCSR_SSI_STCR_TSCKP, &ssi->stcr);
+       write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFSI |
+                       CCSR_SSI_STCR_TEFS | CCSR_SSI_STCR_TSCKP, &ssi->stcr);
+
+       write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFSI |
+                       CCSR_SSI_SRCR_REFS | CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
 
-       write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 |
-                CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS |
-                CCSR_SSI_SRCR_RSCKP, &ssi->srcr);
        /*
         * The DC and PM bits are only used if the SSI is the clock master.
         */
@@ -387,30 +707,18 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
         * because it is also running without an active substream. Normally SSI
         * is only enabled when there is a substream.
         */
-       if (ssi_private->imx_ac97) {
-               /*
-                * Setup the clock control register
-                */
-               write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
-                               &ssi->stccr);
-               write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
-                               &ssi->srccr);
-
-               /*
-                * Enable AC97 mode and startup the SSI
-                */
-               write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
-                               &ssi->sacnt);
-               write_ssi(0xff, &ssi->saccdis);
-               write_ssi(0x300, &ssi->saccen);
-
-               /*
-                * Enable SSI, Transmit and Receive
-                */
-               write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
-                               CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
+       if (ssi_private->imx_ac97)
+               fsl_ssi_setup_ac97(ssi_private);
 
-               write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
+       /*
+        * Set a default slot number so that there is no need for those common
+        * cases like I2S mode to call the extra set_tdm_slot() any more.
+        */
+       if (!ssi_private->imx_ac97) {
+               write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
+                               CCSR_SSI_SxCCR_DC(2));
+               write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
+                               CCSR_SSI_SxCCR_DC(2));
        }
 
        return 0;
@@ -431,53 +739,17 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct fsl_ssi_private *ssi_private =
                snd_soc_dai_get_drvdata(rtd->cpu_dai);
-       int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
+       unsigned long flags;
 
-       /*
-        * If this is the first stream opened, then request the IRQ
-        * and initialize the SSI registers.
+       /* First, we only do fsl_ssi_setup() when SSI is going to be active.
+        * Second, fsl_ssi_setup was already called by ac97_init earlier if
+        * the driver is in ac97 mode.
         */
-       if (!ssi_private->first_stream) {
-               ssi_private->first_stream = substream;
-
-               /*
-                * fsl_ssi_setup was already called by ac97_init earlier if
-                * the driver is in ac97 mode.
-                */
-               if (!ssi_private->imx_ac97)
-                       fsl_ssi_setup(ssi_private);
-       } else {
-               if (synchronous) {
-                       struct snd_pcm_runtime *first_runtime =
-                               ssi_private->first_stream->runtime;
-                       /*
-                        * This is the second stream open, and we're in
-                        * synchronous mode, so we need to impose sample
-                        * sample size constraints. This is because STCCR is
-                        * used for playback and capture in synchronous mode,
-                        * so there's no way to specify different word
-                        * lengths.
-                        *
-                        * Note that this can cause a race condition if the
-                        * second stream is opened before the first stream is
-                        * fully initialized.  We provide some protection by
-                        * checking to make sure the first stream is
-                        * initialized, but it's not perfect.  ALSA sometimes
-                        * re-initializes the driver with a different sample
-                        * rate or size.  If the second stream is opened
-                        * before the first stream has received its final
-                        * parameters, then the second stream may be
-                        * constrained to the wrong sample rate or size.
-                        */
-                       if (first_runtime->sample_bits) {
-                               snd_pcm_hw_constraint_minmax(substream->runtime,
-                                               SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-                               first_runtime->sample_bits,
-                               first_runtime->sample_bits);
-                       }
-               }
-
-               ssi_private->second_stream = substream;
+       if (!dai->active && !ssi_private->imx_ac97) {
+               fsl_ssi_setup(ssi_private);
+               spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
+               ssi_private->baudclk_locked = false;
+               spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
        }
 
        return 0;
@@ -501,6 +773,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 {
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       unsigned int channels = params_channels(hw_params);
        unsigned int sample_size =
                snd_pcm_format_width(params_format(hw_params));
        u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
@@ -530,6 +803,248 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        else
                write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
 
+       if (!ssi_private->imx_ac97)
+               write_ssi_mask(&ssi->scr,
+                               CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
+                               channels == 1 ? 0 : ssi_private->i2s_mode);
+
+       return 0;
+}
+
+/**
+ * fsl_ssi_set_dai_fmt - configure Digital Audio Interface Format.
+ */
+static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       u32 strcr = 0, stcr, srcr, scr, mask;
+
+       scr = read_ssi(&ssi->scr) & ~(CCSR_SSI_SCR_SYN | CCSR_SSI_SCR_I2S_MODE_MASK);
+       scr |= CCSR_SSI_SCR_NET;
+
+       mask = CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR |
+               CCSR_SSI_STCR_TSCKP | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TFSL |
+               CCSR_SSI_STCR_TEFS;
+       stcr = read_ssi(&ssi->stcr) & ~mask;
+       srcr = read_ssi(&ssi->srcr) & ~mask;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+               case SND_SOC_DAIFMT_CBS_CFS:
+                       ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_MASTER;
+                       break;
+               case SND_SOC_DAIFMT_CBM_CFM:
+                       ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               scr |= ssi_private->i2s_mode;
+
+               /* Data on rising edge of bclk, frame low, 1clk before data */
+               strcr |= CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TSCKP |
+                       CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               /* Data on rising edge of bclk, frame high */
+               strcr |= CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TSCKP;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               /* Data on rising edge of bclk, frame high, 1clk before data */
+               strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
+                       CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TEFS;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               /* Data on rising edge of bclk, frame high */
+               strcr |= CCSR_SSI_STCR_TFSL | CCSR_SSI_STCR_TSCKP |
+                       CCSR_SSI_STCR_TXBIT0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* DAI clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               /* Nothing to do for both normal cases */
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               /* Invert bit clock */
+               strcr ^= CCSR_SSI_STCR_TSCKP;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               /* Invert frame clock */
+               strcr ^= CCSR_SSI_STCR_TFSI;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               /* Invert both clocks */
+               strcr ^= CCSR_SSI_STCR_TSCKP;
+               strcr ^= CCSR_SSI_STCR_TFSI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* DAI clock master masks */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               strcr |= CCSR_SSI_STCR_TFDIR | CCSR_SSI_STCR_TXDIR;
+               scr |= CCSR_SSI_SCR_SYS_CLK_EN;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               scr &= ~CCSR_SSI_SCR_SYS_CLK_EN;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       stcr |= strcr;
+       srcr |= strcr;
+
+       if (ssi_private->cpu_dai_drv.symmetric_rates) {
+               /* Need to clear RXDIR when using SYNC mode */
+               srcr &= ~CCSR_SSI_SRCR_RXDIR;
+               scr |= CCSR_SSI_SCR_SYN;
+       }
+
+       write_ssi(stcr, &ssi->stcr);
+       write_ssi(srcr, &ssi->srcr);
+       write_ssi(scr, &ssi->scr);
+
+       return 0;
+}
+
+/**
+ * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
+ *
+ * Note: This function can be only called when using SSI as DAI master
+ *
+ * Quick instruction for parameters:
+ * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
+ * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
+ */
+static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+                                 int clk_id, unsigned int freq, int dir)
+{
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
+       u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
+       unsigned long flags, clkrate, baudrate, tmprate;
+       u64 sub, savesub = 100000;
+
+       /* Don't apply it to any non-baudclk circumstance */
+       if (IS_ERR(ssi_private->baudclk))
+               return -EINVAL;
+
+       /* It should be already enough to divide clock by setting pm alone */
+       psr = 0;
+       div2 = 0;
+
+       factor = (div2 + 1) * (7 * psr + 1) * 2;
+
+       for (i = 0; i < 255; i++) {
+               /* The bclk rate must be smaller than 1/5 sysclk rate */
+               if (factor * (i + 1) < 5)
+                       continue;
+
+               tmprate = freq * factor * (i + 2);
+               clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
+
+               do_div(clkrate, factor);
+               afreq = (u32)clkrate / (i + 1);
+
+               if (freq == afreq)
+                       sub = 0;
+               else if (freq / afreq == 1)
+                       sub = freq - afreq;
+               else if (afreq / freq == 1)
+                       sub = afreq - freq;
+               else
+                       continue;
+
+               /* Calculate the fraction */
+               sub *= 100000;
+               do_div(sub, freq);
+
+               if (sub < savesub) {
+                       baudrate = tmprate;
+                       savesub = sub;
+                       pm = i;
+               }
+
+               /* We are lucky */
+               if (savesub == 0)
+                       break;
+       }
+
+       /* No proper pm found if it is still remaining the initial value */
+       if (pm == 999) {
+               dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
+               return -EINVAL;
+       }
+
+       stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
+               (psr ? CCSR_SSI_SxCCR_PSR : 0);
+       mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR;
+
+       if (dir == SND_SOC_CLOCK_OUT || synchronous)
+               write_ssi_mask(&ssi->stccr, mask, stccr);
+       else
+               write_ssi_mask(&ssi->srccr, mask, stccr);
+
+       spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
+       if (!ssi_private->baudclk_locked) {
+               ret = clk_set_rate(ssi_private->baudclk, baudrate);
+               if (ret) {
+                       spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
+                       dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
+                       return -EINVAL;
+               }
+               ssi_private->baudclk_locked = true;
+       }
+       spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
+
+       return 0;
+}
+
+/**
+ * fsl_ssi_set_dai_tdm_slot - set TDM slot number
+ *
+ * Note: This function can be only called when using SSI as DAI master
+ */
+static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
+                               u32 rx_mask, int slots, int slot_width)
+{
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       u32 val;
+
+       /* The slot number should be >= 2 if using Network mode or I2S mode */
+       val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET);
+       if (val && slots < 2) {
+               dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
+               return -EINVAL;
+       }
+
+       write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
+                       CCSR_SSI_SxCCR_DC(slots));
+       write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_DC_MASK,
+                       CCSR_SSI_SxCCR_DC(slots));
+
+       /* The register SxMSKs needs SSI to provide essential clock due to
+        * hardware design. So we here temporarily enable SSI to set them.
+        */
+       val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
+       write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN);
+
+       write_ssi(tx_mask, &ssi->stmsk);
+       write_ssi(rx_mask, &ssi->srmsk);
+
+       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val);
+
        return 0;
 }
 
@@ -548,77 +1063,46 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-       unsigned int sier_bits;
-
-       /*
-        *  Enable only the interrupts and DMA requests
-        *  that are needed for the channel. As the fiq
-        *  is polling for this bits, we have to ensure
-        *  that this are aligned with the preallocated
-        *  buffers
-        */
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (ssi_private->use_dma)
-                       sier_bits = SIER_FLAGS;
-               else
-                       sier_bits = CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TFE0_EN;
-       } else {
-               if (ssi_private->use_dma)
-                       sier_bits = SIER_FLAGS;
-               else
-                       sier_bits = CCSR_SSI_SIER_RIE | CCSR_SSI_SIER_RFF0_EN;
-       }
+       unsigned long flags;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       write_ssi_mask(&ssi->scr, 0,
-                               CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
+                       fsl_ssi_tx_config(ssi_private, true);
                else
-                       write_ssi_mask(&ssi->scr, 0,
-                               CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
+                       fsl_ssi_rx_config(ssi_private, true);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0);
+                       fsl_ssi_tx_config(ssi_private, false);
                else
-                       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0);
+                       fsl_ssi_rx_config(ssi_private, false);
 
                if (!ssi_private->imx_ac97 && (read_ssi(&ssi->scr) &
-                                       (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0)
-                       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
+                                       (CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE)) == 0) {
+                       spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
+                       ssi_private->baudclk_locked = false;
+                       spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
+               }
                break;
 
        default:
                return -EINVAL;
        }
 
-       write_ssi(sier_bits, &ssi->sier);
+       if (ssi_private->imx_ac97) {
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
+               else
+                       write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
+       }
 
        return 0;
 }
 
-/**
- * fsl_ssi_shutdown: shutdown the SSI
- *
- * Shutdown the SSI if there are no other substreams open.
- */
-static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
-                            struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-
-       if (ssi_private->first_stream == substream)
-               ssi_private->first_stream = ssi_private->second_stream;
-
-       ssi_private->second_stream = NULL;
-}
-
 static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
@@ -634,7 +1118,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
        .startup        = fsl_ssi_startup,
        .hw_params      = fsl_ssi_hw_params,
-       .shutdown       = fsl_ssi_shutdown,
+       .set_fmt        = fsl_ssi_set_dai_fmt,
+       .set_sysclk     = fsl_ssi_set_dai_sysclk,
+       .set_tdm_slot   = fsl_ssi_set_dai_tdm_slot,
        .trigger        = fsl_ssi_trigger,
 };
 
@@ -642,14 +1128,13 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
 static struct snd_soc_dai_driver fsl_ssi_dai_template = {
        .probe = fsl_ssi_dai_probe,
        .playback = {
-               /* The SSI does not support monaural audio. */
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = FSLSSI_I2S_RATES,
                .formats = FSLSSI_I2S_FORMATS,
        },
        .capture = {
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = FSLSSI_I2S_RATES,
                .formats = FSLSSI_I2S_FORMATS,
@@ -661,59 +1146,6 @@ static const struct snd_soc_component_driver fsl_ssi_component = {
        .name           = "fsl-ssi",
 };
 
-/**
- * fsl_ssi_ac97_trigger: start and stop the AC97 receive/transmit.
- *
- * This function is called by ALSA to start, stop, pause, and resume the
- * transfer of data.
- */
-static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
-                          struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(
-                       rtd->cpu_dai);
-       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_TIE |
-                                       CCSR_SSI_SIER_TFE0_EN);
-               else
-                       write_ssi_mask(&ssi->sier, 0, CCSR_SSI_SIER_RIE |
-                                       CCSR_SSI_SIER_RFF0_EN);
-               break;
-
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_TIE |
-                                       CCSR_SSI_SIER_TFE0_EN, 0);
-               else
-                       write_ssi_mask(&ssi->sier, CCSR_SSI_SIER_RIE |
-                                       CCSR_SSI_SIER_RFF0_EN, 0);
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               write_ssi(CCSR_SSI_SOR_TX_CLR, &ssi->sor);
-       else
-               write_ssi(CCSR_SSI_SOR_RX_CLR, &ssi->sor);
-
-       return 0;
-}
-
-static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
-       .startup        = fsl_ssi_startup,
-       .shutdown       = fsl_ssi_shutdown,
-       .trigger        = fsl_ssi_ac97_trigger,
-};
-
 static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
        .ac97_control = 1,
        .playback = {
@@ -730,7 +1162,7 @@ static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
                .rates = SNDRV_PCM_RATE_48000,
                .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
-       .ops = &fsl_ssi_ac97_dai_ops,
+       .ops = &fsl_ssi_dai_ops,
 };
 
 
@@ -788,56 +1220,6 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
        .write          = fsl_ssi_ac97_write,
 };
 
-/* Show the statistics of a flag only if its interrupt is enabled.  The
- * compiler will optimze this code to a no-op if the interrupt is not
- * enabled.
- */
-#define SIER_SHOW(flag, name) \
-       do { \
-               if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \
-                       length += sprintf(buf + length, #name "=%u\n", \
-                               ssi_private->stats.name); \
-       } while (0)
-
-
-/**
- * fsl_sysfs_ssi_show: display SSI statistics
- *
- * Display the statistics for the current SSI device.  To avoid confusion,
- * we only show those counts that are enabled.
- */
-static ssize_t fsl_sysfs_ssi_show(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       struct fsl_ssi_private *ssi_private =
-               container_of(attr, struct fsl_ssi_private, dev_attr);
-       ssize_t length = 0;
-
-       SIER_SHOW(RFRC_EN, rfrc);
-       SIER_SHOW(TFRC_EN, tfrc);
-       SIER_SHOW(CMDAU_EN, cmdau);
-       SIER_SHOW(CMDDU_EN, cmddu);
-       SIER_SHOW(RXT_EN, rxt);
-       SIER_SHOW(RDR1_EN, rdr1);
-       SIER_SHOW(RDR0_EN, rdr0);
-       SIER_SHOW(TDE1_EN, tde1);
-       SIER_SHOW(TDE0_EN, tde0);
-       SIER_SHOW(ROE1_EN, roe1);
-       SIER_SHOW(ROE0_EN, roe0);
-       SIER_SHOW(TUE1_EN, tue1);
-       SIER_SHOW(TUE0_EN, tue0);
-       SIER_SHOW(TFS_EN, tfs);
-       SIER_SHOW(RFS_EN, rfs);
-       SIER_SHOW(TLS_EN, tls);
-       SIER_SHOW(RLS_EN, rls);
-       SIER_SHOW(RFF1_EN, rff1);
-       SIER_SHOW(RFF0_EN, rff0);
-       SIER_SHOW(TFE1_EN, tfe1);
-       SIER_SHOW(TFE0_EN, tfe0);
-
-       return length;
-}
-
 /**
  * Make every character in a string lower-case
  */
@@ -859,6 +1241,8 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        int ret = 0;
        struct device_attribute *dev_attr = NULL;
        struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *of_id;
+       enum fsl_ssi_type hw_type;
        const char *p, *sprop;
        const uint32_t *iprop;
        struct resource res;
@@ -873,6 +1257,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        if (!of_device_is_available(np))
                return -ENODEV;
 
+       of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+       hw_type = (enum fsl_ssi_type) of_id->data;
+
        /* We only support the SSI in "I2S Slave" mode */
        sprop = of_get_property(np, "fsl,mode", NULL);
        if (!sprop) {
@@ -899,6 +1288,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
        ssi_private->use_dma = !of_property_read_bool(np,
                        "fsl,fiq-stream-filter");
+       ssi_private->hw_type = hw_type;
 
        if (ac97) {
                memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai,
@@ -935,8 +1325,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        }
 
        /* Are the RX and the TX clocks locked? */
-       if (!of_find_property(np, "fsl,ssi-asynchronous", NULL))
+       if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
                ssi_private->cpu_dai_drv.symmetric_rates = 1;
+               ssi_private->cpu_dai_drv.symmetric_channels = 1;
+               ssi_private->cpu_dai_drv.symmetric_samplebits = 1;
+       }
 
        /* Determine the FIFO depth. */
        iprop = of_get_property(np, "fsl,fifo-depth", NULL);
@@ -946,7 +1339,37 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                 /* Older 8610 DTs didn't have the fifo-depth property */
                ssi_private->fifo_depth = 8;
 
-       if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
+       ssi_private->baudclk_locked = false;
+       spin_lock_init(&ssi_private->baudclk_lock);
+
+       /*
+        * imx51 and later SoCs have a slightly different IP that allows the
+        * SSI configuration while the SSI unit is running.
+        *
+        * More important, it is necessary on those SoCs to configure the
+        * sperate TX/RX DMA bits just before starting the stream
+        * (fsl_ssi_trigger). The SDMA unit has to be configured before fsl_ssi
+        * sends any DMA requests to the SDMA unit, otherwise it is not defined
+        * how the SDMA unit handles the DMA request.
+        *
+        * SDMA units are present on devices starting at imx35 but the imx35
+        * reference manual states that the DMA bits should not be changed
+        * while the SSI unit is running (SSIEN). So we support the necessary
+        * online configuration of fsl-ssi starting at imx51.
+        */
+       switch (hw_type) {
+       case FSL_SSI_MCP8610:
+       case FSL_SSI_MX21:
+       case FSL_SSI_MX35:
+               ssi_private->offline_config = true;
+               break;
+       case FSL_SSI_MX51:
+               ssi_private->offline_config = false;
+               break;
+       }
+
+       if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 ||
+                       hw_type == FSL_SSI_MX35) {
                u32 dma_events[2];
                ssi_private->ssi_on_imx = true;
 
@@ -963,6 +1386,16 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                        goto error_irqmap;
                }
 
+               /* For those SLAVE implementations, we ingore non-baudclk cases
+                * and, instead, abandon MASTER mode that needs baud clock.
+                */
+               ssi_private->baudclk = devm_clk_get(&pdev->dev, "baud");
+               if (IS_ERR(ssi_private->baudclk))
+                       dev_warn(&pdev->dev, "could not get baud clock: %ld\n",
+                                PTR_ERR(ssi_private->baudclk));
+               else
+                       clk_prepare_enable(ssi_private->baudclk);
+
                /*
                 * We have burstsize be "fifo_depth - 2" to match the SSI
                 * watermark setting in fsl_ssi_startup().
@@ -1001,32 +1434,25 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                        dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
                imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
                        dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
-       } else if (ssi_private->use_dma) {
+       }
+
+       /*
+        * Enable interrupts only for MCP8610 and MX51. The other MXs have
+        * different writeable interrupt status registers.
+        */
+       if (ssi_private->use_dma) {
                /* The 'name' should not have any slashes in it. */
                ret = devm_request_irq(&pdev->dev, ssi_private->irq,
                                        fsl_ssi_isr, 0, ssi_private->name,
                                        ssi_private);
+               ssi_private->irq_stats = true;
                if (ret < 0) {
                        dev_err(&pdev->dev, "could not claim irq %u\n",
                                        ssi_private->irq);
-                       goto error_irqmap;
+                       goto error_clk;
                }
        }
 
-       /* Initialize the the device_attribute structure */
-       dev_attr = &ssi_private->dev_attr;
-       sysfs_attr_init(&dev_attr->attr);
-       dev_attr->attr.name = "statistics";
-       dev_attr->attr.mode = S_IRUGO;
-       dev_attr->show = fsl_sysfs_ssi_show;
-
-       ret = device_create_file(&pdev->dev, dev_attr);
-       if (ret) {
-               dev_err(&pdev->dev, "could not create sysfs %s file\n",
-                       ssi_private->dev_attr.attr.name);
-               goto error_clk;
-       }
-
        /* Register with ASoC */
        dev_set_drvdata(&pdev->dev, ssi_private);
 
@@ -1037,6 +1463,10 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                goto error_dev;
        }
 
+       ret = fsl_ssi_debugfs_create(ssi_private, &pdev->dev);
+       if (ret)
+               goto error_dbgfs;
+
        if (ssi_private->ssi_on_imx) {
                if (!ssi_private->use_dma) {
 
@@ -1056,11 +1486,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
 
                        ret = imx_pcm_fiq_init(pdev, &ssi_private->fiq_params);
                        if (ret)
-                               goto error_dev;
+                               goto error_pcm;
                } else {
                        ret = imx_pcm_dma_init(pdev);
                        if (ret)
-                               goto error_dev;
+                               goto error_pcm;
                }
        }
 
@@ -1102,19 +1532,28 @@ done:
        return 0;
 
 error_dai:
-       if (ssi_private->ssi_on_imx)
-               imx_pcm_dma_exit(pdev);
+       if (ssi_private->ssi_on_imx && !ssi_private->use_dma)
+               imx_pcm_fiq_exit(pdev);
+
+error_pcm:
+       fsl_ssi_debugfs_remove(ssi_private);
+
+error_dbgfs:
        snd_soc_unregister_component(&pdev->dev);
 
 error_dev:
        device_remove_file(&pdev->dev, dev_attr);
 
 error_clk:
-       if (ssi_private->ssi_on_imx)
+       if (ssi_private->ssi_on_imx) {
+               if (!IS_ERR(ssi_private->baudclk))
+                       clk_disable_unprepare(ssi_private->baudclk);
                clk_disable_unprepare(ssi_private->clk);
+       }
 
 error_irqmap:
-       irq_dispose_mapping(ssi_private->irq);
+       if (ssi_private->irq_stats)
+               irq_dispose_mapping(ssi_private->irq);
 
        return ret;
 }
@@ -1123,26 +1562,22 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 {
        struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
 
+       fsl_ssi_debugfs_remove(ssi_private);
+
        if (!ssi_private->new_binding)
                platform_device_unregister(ssi_private->pdev);
-       if (ssi_private->ssi_on_imx)
-               imx_pcm_dma_exit(pdev);
        snd_soc_unregister_component(&pdev->dev);
-       device_remove_file(&pdev->dev, &ssi_private->dev_attr);
-       if (ssi_private->ssi_on_imx)
+       if (ssi_private->ssi_on_imx) {
+               if (!IS_ERR(ssi_private->baudclk))
+                       clk_disable_unprepare(ssi_private->baudclk);
                clk_disable_unprepare(ssi_private->clk);
-       irq_dispose_mapping(ssi_private->irq);
+       }
+       if (ssi_private->irq_stats)
+               irq_dispose_mapping(ssi_private->irq);
 
        return 0;
 }
 
-static const struct of_device_id fsl_ssi_ids[] = {
-       { .compatible = "fsl,mpc8610-ssi", },
-       { .compatible = "fsl,imx21-ssi", },
-       {}
-};
-MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
-
 static struct platform_driver fsl_ssi_driver = {
        .driver = {
                .name = "fsl-ssi-dai",
index e6b9a69e2a68bea799796ec0ba8d2da096498d62..e6b63240a3d71a597dfa940312b49a0c68ff976f 100644 (file)
@@ -125,7 +125,9 @@ struct ccsr_ssi {
 #define CCSR_SSI_SRCR_REFS             0x00000001
 
 /* STCCR and SRCCR */
+#define CCSR_SSI_SxCCR_DIV2_SHIFT      18
 #define CCSR_SSI_SxCCR_DIV2            0x00040000
+#define CCSR_SSI_SxCCR_PSR_SHIFT       17
 #define CCSR_SSI_SxCCR_PSR             0x00020000
 #define CCSR_SSI_SxCCR_WL_SHIFT                13
 #define CCSR_SSI_SxCCR_WL_MASK         0x0001E000
index aee23077080a219983f0dd52764d1aa4199cb15c..2585ae44e634feb6bab623b6afdf93c58c3b288f 100644 (file)
@@ -41,9 +41,6 @@ static const struct snd_pcm_hardware imx_pcm_hardware = {
                SNDRV_PCM_INFO_PAUSE |
                SNDRV_PCM_INFO_RESUME,
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       .rate_min = 8000,
-       .channels_min = 2,
-       .channels_max = 2,
        .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
        .period_bytes_min = 128,
        .period_bytes_max = 65535, /* Limited by SDMA engine */
@@ -61,16 +58,11 @@ static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
 
 int imx_pcm_dma_init(struct platform_device *pdev)
 {
-       return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config,
+       return devm_snd_dmaengine_pcm_register(&pdev->dev,
+               &imx_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
                SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
 
-void imx_pcm_dma_exit(struct platform_device *pdev)
-{
-       snd_dmaengine_pcm_unregister(&pdev->dev);
-}
-EXPORT_SYMBOL_GPL(imx_pcm_dma_exit);
-
 MODULE_LICENSE("GPL");
index c75d43bb2e92de772a97865e98227176473135a4..6553202dd48c09d19fe2916447f553023276a897 100644 (file)
@@ -162,9 +162,6 @@ static struct snd_pcm_hardware snd_imx_hardware = {
                SNDRV_PCM_INFO_PAUSE |
                SNDRV_PCM_INFO_RESUME,
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       .rate_min = 8000,
-       .channels_min = 2,
-       .channels_max = 2,
        .buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
        .period_bytes_min = 128,
        .period_bytes_max = 16 * 1024,
index 5d5b73303e1169b7f6c2254e06d66a87409050cc..c79cb27473be771d9ee355cacf52229f5da6c40d 100644 (file)
@@ -40,16 +40,11 @@ struct imx_pcm_fiq_params {
 
 #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
 int imx_pcm_dma_init(struct platform_device *pdev);
-void imx_pcm_dma_exit(struct platform_device *pdev);
 #else
 static inline int imx_pcm_dma_init(struct platform_device *pdev)
 {
        return -ENODEV;
 }
-
-static inline void imx_pcm_dma_exit(struct platform_device *pdev)
-{
-}
 #endif
 
 #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
index 8499d5292f088a45e9ea736106ee2db13e7d205a..e1dc40143600a05854331a539590603d0d859fed 100644 (file)
 #include <sound/soc.h>
 
 struct imx_spdif_data {
-       struct snd_soc_dai_link dai[2];
+       struct snd_soc_dai_link dai;
        struct snd_soc_card card;
-       struct platform_device *txdev;
-       struct platform_device *rxdev;
 };
 
 static int imx_spdif_audio_probe(struct platform_device *pdev)
 {
        struct device_node *spdif_np, *np = pdev->dev.of_node;
        struct imx_spdif_data *data;
-       int ret = 0, num_links = 0;
+       int ret = 0;
 
        spdif_np = of_parse_phandle(np, "spdif-controller", 0);
        if (!spdif_np) {
@@ -35,74 +33,46 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data) {
-               dev_err(&pdev->dev, "failed to allocate memory\n");
                ret = -ENOMEM;
                goto end;
        }
 
-       if (of_property_read_bool(np, "spdif-out")) {
-               data->dai[num_links].name = "S/PDIF TX";
-               data->dai[num_links].stream_name = "S/PDIF PCM Playback";
-               data->dai[num_links].codec_dai_name = "dit-hifi";
-               data->dai[num_links].codec_name = "spdif-dit";
-               data->dai[num_links].cpu_of_node = spdif_np;
-               data->dai[num_links].platform_of_node = spdif_np;
-               num_links++;
-
-               data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0);
-               if (IS_ERR(data->txdev)) {
-                       ret = PTR_ERR(data->txdev);
-                       dev_err(&pdev->dev, "register dit failed: %d\n", ret);
-                       goto end;
-               }
-       }
+       data->dai.name = "S/PDIF PCM";
+       data->dai.stream_name = "S/PDIF PCM";
+       data->dai.codec_dai_name = "snd-soc-dummy-dai";
+       data->dai.codec_name = "snd-soc-dummy";
+       data->dai.cpu_of_node = spdif_np;
+       data->dai.platform_of_node = spdif_np;
+       data->dai.playback_only = true;
+       data->dai.capture_only = true;
 
-       if (of_property_read_bool(np, "spdif-in")) {
-               data->dai[num_links].name = "S/PDIF RX";
-               data->dai[num_links].stream_name = "S/PDIF PCM Capture";
-               data->dai[num_links].codec_dai_name = "dir-hifi";
-               data->dai[num_links].codec_name = "spdif-dir";
-               data->dai[num_links].cpu_of_node = spdif_np;
-               data->dai[num_links].platform_of_node = spdif_np;
-               num_links++;
-
-               data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0);
-               if (IS_ERR(data->rxdev)) {
-                       ret = PTR_ERR(data->rxdev);
-                       dev_err(&pdev->dev, "register dir failed: %d\n", ret);
-                       goto error_dit;
-               }
-       }
+       if (of_property_read_bool(np, "spdif-out"))
+               data->dai.capture_only = false;
+
+       if (of_property_read_bool(np, "spdif-in"))
+               data->dai.playback_only = false;
 
-       if (!num_links) {
+       if (data->dai.playback_only && data->dai.capture_only) {
                dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n");
-               goto error_dir;
+               goto end;
        }
 
        data->card.dev = &pdev->dev;
-       data->card.num_links = num_links;
-       data->card.dai_link = data->dai;
+       data->card.dai_link = &data->dai;
+       data->card.num_links = 1;
 
        ret = snd_soc_of_parse_card_name(&data->card, "model");
        if (ret)
-               goto error_dir;
+               goto end;
 
        ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
-               goto error_dir;
+               goto end;
        }
 
        platform_set_drvdata(pdev, data);
 
-       goto end;
-
-error_dir:
-       if (data->rxdev)
-               platform_device_unregister(data->rxdev);
-error_dit:
-       if (data->txdev)
-               platform_device_unregister(data->txdev);
 end:
        if (spdif_np)
                of_node_put(spdif_np);
@@ -110,18 +80,6 @@ end:
        return ret;
 }
 
-static int imx_spdif_audio_remove(struct platform_device *pdev)
-{
-       struct imx_spdif_data *data = platform_get_drvdata(pdev);
-
-       if (data->rxdev)
-               platform_device_unregister(data->rxdev);
-       if (data->txdev)
-               platform_device_unregister(data->txdev);
-
-       return 0;
-}
-
 static const struct of_device_id imx_spdif_dt_ids[] = {
        { .compatible = "fsl,imx-audio-spdif", },
        { /* sentinel */ }
@@ -135,7 +93,6 @@ static struct platform_driver imx_spdif_driver = {
                .of_match_table = imx_spdif_dt_ids,
        },
        .probe = imx_spdif_audio_probe,
-       .remove = imx_spdif_audio_remove,
 };
 
 module_platform_driver(imx_spdif_driver);
index f5f248c91c16db7c3db5a50654bceedb0e81953f..df552fa1aa65f13faee928c63d2a8b8bf6c9eae4 100644 (file)
@@ -304,8 +304,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
                        scr |= SSI_SCR_RE;
                sier |= sier_bits;
 
-               if (++ssi->enabled == 1)
-                       scr |= SSI_SCR_SSIEN;
+               scr |= SSI_SCR_SSIEN;
 
                break;
 
@@ -318,7 +317,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
                        scr &= ~SSI_SCR_RE;
                sier &= ~sier_bits;
 
-               if (--ssi->enabled == 0)
+               if (!(scr & (SSI_SCR_TE | SSI_SCR_RE)))
                        scr &= ~SSI_SCR_SSIEN;
 
                break;
@@ -536,7 +535,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
                        ret);
                goto failed_clk;
        }
-       clk_prepare_enable(ssi->clk);
+       ret = clk_prepare_enable(ssi->clk);
+       if (ret)
+               goto failed_clk;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ssi->base = devm_ioremap_resource(&pdev->dev, res);
@@ -624,9 +625,6 @@ static int imx_ssi_remove(struct platform_device *pdev)
 {
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
 
-       if (!ssi->dma_init)
-               imx_pcm_dma_exit(pdev);
-
        if (!ssi->fiq_init)
                imx_pcm_fiq_exit(pdev);
 
index 560c40fc9ebbb50241e3732f3a76ece064178bf2..be6562365b6a971a08efe55e3c1d7c49f0c0a874 100644 (file)
@@ -213,7 +213,6 @@ struct imx_ssi {
 
        int fiq_init;
        int dma_init;
-       int enabled;
 };
 
 #endif /* _IMX_SSI_H */
index 61e48852b9e8bd21b26eec98cca4fc9ba0eea145..3fd76bc391de19a2431dd320d0abfbdcd9616cf5 100644 (file)
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
                break;
        }
 
-       dapm->bias_level = level;
-
        return 0;
 }
 
index 71bf2f248cd47be5fb025baa6535296b49d75bbd..f2b5d756b1f3360846ef3bb1f8f43a4efd8547b1 100644 (file)
@@ -200,10 +200,6 @@ static const struct snd_pcm_hardware psc_dma_hardware = {
                SNDRV_PCM_INFO_BATCH,
        .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
                SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
-       .rate_min = 8000,
-       .rate_max = 48000,
-       .channels_min = 1,
-       .channels_max = 2,
        .period_bytes_max       = 1024 * 1024,
        .period_bytes_min       = 32,
        .periods_min            = 2,
index f4efaadb80a2223d29d3718643856fbcee15579c..5d07e8a74a21d9ab80f4e8f8eaf65cd26e448c19 100644 (file)
@@ -26,8 +26,7 @@
  * ALSA that we support all rates and let the codec driver decide what rates
  * are really supported.
  */
-#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
-                       SNDRV_PCM_RATE_CONTINUOUS)
+#define PSC_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
 
 /**
  * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode
index eb4373840bb6e1ab2cbbb1e5e9220e1c8474cb29..3665f612819d4bd2d443b0e7072cf9753ee1905b 100644 (file)
@@ -69,7 +69,6 @@ static int pcm030_fabric_probe(struct platform_device *op)
                return -ENOMEM;
 
        card->dev = &op->dev;
-       platform_set_drvdata(op, pdata);
 
        pdata->card = card;
 
@@ -98,6 +97,8 @@ static int pcm030_fabric_probe(struct platform_device *op)
        if (ret)
                dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
 
+       platform_set_drvdata(op, pdata);
+
        return ret;
 }
 
index b2fbb7075a6c9900aac6aea847b63242a359a5a7..2a1b1b5b5221089f32e395087e9c4651ddd00799 100644 (file)
@@ -8,14 +8,13 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-#include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
 #include <sound/simple_card.h>
 
-#define asoc_simple_get_card_info(p) \
-       container_of(p->dai_link, struct asoc_simple_card_info, snd_link)
-
 static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
                                       struct asoc_simple_dai *set,
                                       unsigned int daifmt)
@@ -24,7 +23,7 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
 
        daifmt |= set->fmt;
 
-       if (!ret && daifmt)
+       if (daifmt)
                ret = snd_soc_dai_set_fmt(dai, daifmt);
 
        if (ret == -ENOTSUPP) {
@@ -40,7 +39,8 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
 
 static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct asoc_simple_card_info *info = asoc_simple_get_card_info(rtd);
+       struct asoc_simple_card_info *info =
+                               snd_soc_card_get_drvdata(rtd->card);
        struct snd_soc_dai *codec = rtd->codec_dai;
        struct snd_soc_dai *cpu = rtd->cpu_dai;
        unsigned int daifmt = info->daifmt;
@@ -57,22 +57,182 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
+static int
+asoc_simple_card_sub_parse_of(struct device_node *np,
+                             struct asoc_simple_dai *dai,
+                             struct device_node **node)
+{
+       struct clk *clk;
+       int ret;
+
+       /*
+        * get node via "sound-dai = <&phandle port>"
+        * it will be used as xxx_of_node on soc_bind_dai_link()
+        */
+       *node = of_parse_phandle(np, "sound-dai", 0);
+       if (!*node)
+               return -ENODEV;
+
+       /* get dai->name */
+       ret = snd_soc_of_get_dai_name(np, &dai->name);
+       if (ret < 0)
+               goto parse_error;
+
+       /*
+        * bitclock-inversion, frame-inversion
+        * bitclock-master,    frame-master
+        * and specific "format" if it has
+        */
+       dai->fmt = snd_soc_of_parse_daifmt(np, NULL);
+
+       /*
+        * dai->sysclk come from
+        *  "clocks = <&xxx>" (if system has common clock)
+        *  or "system-clock-frequency = <xxx>"
+        *  or device's module clock.
+        */
+       if (of_property_read_bool(np, "clocks")) {
+               clk = of_clk_get(np, 0);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       goto parse_error;
+               }
+
+               dai->sysclk = clk_get_rate(clk);
+       } else if (of_property_read_bool(np, "system-clock-frequency")) {
+               of_property_read_u32(np,
+                                    "system-clock-frequency",
+                                    &dai->sysclk);
+       } else {
+               clk = of_clk_get(*node, 0);
+               if (!IS_ERR(clk))
+                       dai->sysclk = clk_get_rate(clk);
+       }
+
+       ret = 0;
+
+parse_error:
+       of_node_put(*node);
+
+       return ret;
+}
+
+static int asoc_simple_card_parse_of(struct device_node *node,
+                                    struct asoc_simple_card_info *info,
+                                    struct device *dev,
+                                    struct device_node **of_cpu,
+                                    struct device_node **of_codec,
+                                    struct device_node **of_platform)
+{
+       struct device_node *np;
+       char *name;
+       int ret;
+
+       /* get CPU/CODEC common format via simple-audio-card,format */
+       info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") &
+               (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK);
+
+       /* DAPM routes */
+       if (of_property_read_bool(node, "simple-audio-card,routing")) {
+               ret = snd_soc_of_parse_audio_routing(&info->snd_card,
+                                       "simple-audio-card,routing");
+               if (ret)
+                       return ret;
+       }
+
+       /* CPU sub-node */
+       ret = -EINVAL;
+       np = of_get_child_by_name(node, "simple-audio-card,cpu");
+       if (np)
+               ret = asoc_simple_card_sub_parse_of(np,
+                                                 &info->cpu_dai,
+                                                 of_cpu);
+       if (ret < 0)
+               return ret;
+
+       /* CODEC sub-node */
+       ret = -EINVAL;
+       np = of_get_child_by_name(node, "simple-audio-card,codec");
+       if (np)
+               ret = asoc_simple_card_sub_parse_of(np,
+                                                 &info->codec_dai,
+                                                 of_codec);
+       if (ret < 0)
+               return ret;
+
+       if (!info->cpu_dai.name || !info->codec_dai.name)
+               return -EINVAL;
+
+       /* card name is created from CPU/CODEC dai name */
+       name = devm_kzalloc(dev,
+                           strlen(info->cpu_dai.name)   +
+                           strlen(info->codec_dai.name) + 2,
+                           GFP_KERNEL);
+       sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name);
+       info->name = info->card = name;
+
+       /* simple-card assumes platform == cpu */
+       *of_platform = *of_cpu;
+
+       dev_dbg(dev, "card-name : %s\n", info->card);
+       dev_dbg(dev, "platform : %04x\n", info->daifmt);
+       dev_dbg(dev, "cpu : %s / %04x / %d\n",
+               info->cpu_dai.name,
+               info->cpu_dai.fmt,
+               info->cpu_dai.sysclk);
+       dev_dbg(dev, "codec : %s / %04x / %d\n",
+               info->codec_dai.name,
+               info->codec_dai.fmt,
+               info->codec_dai.sysclk);
+
+       return 0;
+}
+
 static int asoc_simple_card_probe(struct platform_device *pdev)
 {
-       struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
+       struct asoc_simple_card_info *cinfo;
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *of_cpu, *of_codec, *of_platform;
        struct device *dev = &pdev->dev;
+       int ret;
 
-       if (!cinfo) {
-               dev_err(dev, "no info for asoc-simple-card\n");
-               return -EINVAL;
+       cinfo           = NULL;
+       of_cpu          = NULL;
+       of_codec        = NULL;
+       of_platform     = NULL;
+
+       cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL);
+       if (!cinfo)
+               return -ENOMEM;
+
+       if (np && of_device_is_available(np)) {
+               cinfo->snd_card.dev = dev;
+
+               ret = asoc_simple_card_parse_of(np, cinfo, dev,
+                                               &of_cpu,
+                                               &of_codec,
+                                               &of_platform);
+               if (ret < 0) {
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(dev, "parse error %d\n", ret);
+                       return ret;
+               }
+       } else {
+               if (!dev->platform_data) {
+                       dev_err(dev, "no info for asoc-simple-card\n");
+                       return -EINVAL;
+               }
+
+               memcpy(cinfo, dev->platform_data, sizeof(*cinfo));
+               cinfo->snd_card.dev = dev;
        }
 
        if (!cinfo->name        ||
            !cinfo->card        ||
-           !cinfo->codec       ||
-           !cinfo->platform    ||
-           !cinfo->cpu_dai.name ||
-           !cinfo->codec_dai.name) {
+           !cinfo->codec_dai.name      ||
+           !(cinfo->codec              || of_codec)    ||
+           !(cinfo->platform           || of_platform) ||
+           !(cinfo->cpu_dai.name       || of_cpu)) {
                dev_err(dev, "insufficient asoc_simple_card_info settings\n");
                return -EINVAL;
        }
@@ -86,6 +246,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
        cinfo->snd_link.platform_name   = cinfo->platform;
        cinfo->snd_link.codec_name      = cinfo->codec;
        cinfo->snd_link.codec_dai_name  = cinfo->codec_dai.name;
+       cinfo->snd_link.cpu_of_node     = of_cpu;
+       cinfo->snd_link.codec_of_node   = of_codec;
+       cinfo->snd_link.platform_of_node = of_platform;
        cinfo->snd_link.init            = asoc_simple_card_dai_init;
 
        /*
@@ -95,25 +258,25 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
        cinfo->snd_card.owner           = THIS_MODULE;
        cinfo->snd_card.dai_link        = &cinfo->snd_link;
        cinfo->snd_card.num_links       = 1;
-       cinfo->snd_card.dev             = &pdev->dev;
 
-       return snd_soc_register_card(&cinfo->snd_card);
-}
+       snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo);
 
-static int asoc_simple_card_remove(struct platform_device *pdev)
-{
-       struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
-
-       return snd_soc_unregister_card(&cinfo->snd_card);
+       return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card);
 }
 
+static const struct of_device_id asoc_simple_of_match[] = {
+       { .compatible = "simple-audio-card", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
+
 static struct platform_driver asoc_simple_card = {
        .driver = {
                .name   = "asoc-simple-card",
                .owner = THIS_MODULE,
+               .of_match_table = asoc_simple_of_match,
        },
        .probe          = asoc_simple_card_probe,
-       .remove         = asoc_simple_card_remove,
 };
 
 module_platform_driver(asoc_simple_card);
similarity index 98%
rename from sound/soc/mid-x86/sst_platform.c
rename to sound/soc/intel/sst_platform.c
index b6b5eb698d33227af2193196847b64be291e595a..f465a81808636e0cf59e8644d4fa8f08e6cb2904 100644 (file)
@@ -89,16 +89,6 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
                        SNDRV_PCM_INFO_MMAP_VALID |
                        SNDRV_PCM_INFO_BLOCK_TRANSFER |
                        SNDRV_PCM_INFO_SYNC_START),
-       .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
-                       SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
-                       SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
-       .rates = (SNDRV_PCM_RATE_8000|
-                       SNDRV_PCM_RATE_44100 |
-                       SNDRV_PCM_RATE_48000),
-       .rate_min = SST_MIN_RATE,
-       .rate_max = SST_MAX_RATE,
-       .channels_min = SST_MIN_CHANNEL,
-       .channels_max = SST_MAX_CHANNEL,
        .buffer_bytes_max = SST_MAX_BUFFER,
        .period_bytes_min = SST_MIN_PERIOD_BYTES,
        .period_bytes_max = SST_MAX_PERIOD_BYTES,
similarity index 97%
rename from sound/soc/mid-x86/sst_platform.h
rename to sound/soc/intel/sst_platform.h
index cacc9066ec524a5ad6747f650b77615899d776d6..bee64fb7d2ef54871973952bb68c9a797486e390 100644 (file)
 #define SST_STEREO             2
 #define SST_MAX_CAP            5
 
-#define SST_MIN_RATE           8000
-#define SST_MAX_RATE           48000
-#define SST_MIN_CHANNEL                1
-#define SST_MAX_CHANNEL                5
 #define SST_MAX_BUFFER         (800*1024)
 #define SST_MIN_BUFFER         (800*1024)
 #define SST_MIN_PERIOD_BYTES   32
index 5351cba66c9e3584e39263e49137afb9260ed1ab..29f76af5d963c2fca31366e7140c21239d18a0f0 100644 (file)
@@ -1,6 +1,7 @@
 config SND_JZ4740_SOC
        tristate "SoC Audio for Ingenic JZ4740 SoC"
        depends on MACH_JZ4740 && SND_SOC
+       select SND_SOC_GENERIC_DMAENGINE_PCM
        help
          Say Y or M if you want to add support for codecs attached to
          the JZ4740 I2S interface. You will also need to select the audio
index 4c849a49c72ac3c6c6800aebec9292b3785be37c..8f220009e0f616e0572777c19a15c3a44c658ed8 100644 (file)
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/initval.h>
+#include <sound/dmaengine_pcm.h>
+
+#include <asm/mach-jz4740/dma.h>
 
 #include "jz4740-i2s.h"
-#include "jz4740-pcm.h"
 
 #define JZ_REG_AIC_CONF                0x00
 #define JZ_REG_AIC_CTRL                0x04
@@ -89,8 +91,8 @@ struct jz4740_i2s {
        struct clk *clk_aic;
        struct clk *clk_i2s;
 
-       struct jz4740_pcm_config pcm_config_playback;
-       struct jz4740_pcm_config pcm_config_capture;
+       struct snd_dmaengine_dai_dma_data playback_dma_data;
+       struct snd_dmaengine_dai_dma_data capture_dma_data;
 };
 
 static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
@@ -233,8 +235,6 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       enum jz4740_dma_width dma_width;
-       struct jz4740_pcm_config *pcm_config;
        unsigned int sample_size;
        uint32_t ctrl;
 
@@ -243,11 +243,9 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                sample_size = 0;
-               dma_width = JZ4740_DMA_WIDTH_8BIT;
                break;
        case SNDRV_PCM_FORMAT_S16:
                sample_size = 1;
-               dma_width = JZ4740_DMA_WIDTH_16BIT;
                break;
        default:
                return -EINVAL;
@@ -260,22 +258,13 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
                        ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
                else
                        ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;
-
-               pcm_config = &i2s->pcm_config_playback;
-               pcm_config->dma_config.dst_width = dma_width;
-
        } else {
                ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
                ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
-
-               pcm_config = &i2s->pcm_config_capture;
-               pcm_config->dma_config.src_width = dma_width;
        }
 
        jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
 
-       snd_soc_dai_set_dma_data(dai, substream, pcm_config);
-
        return 0;
 }
 
@@ -342,25 +331,19 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)
 
 static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
 {
-       struct jz4740_dma_config *dma_config;
+       struct snd_dmaengine_dai_dma_data *dma_data;
 
        /* Playback */
-       dma_config = &i2s->pcm_config_playback.dma_config;
-       dma_config->src_width = JZ4740_DMA_WIDTH_32BIT;
-       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
-       dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
-       dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
-       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
-       i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+       dma_data = &i2s->playback_dma_data;
+       dma_data->maxburst = 16;
+       dma_data->slave_id = JZ4740_DMA_TYPE_AIC_TRANSMIT;
+       dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO;
 
        /* Capture */
-       dma_config = &i2s->pcm_config_capture.dma_config;
-       dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT;
-       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
-       dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
-       dma_config->flags = JZ4740_DMA_DST_AUTOINC;
-       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
-       i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+       dma_data = &i2s->capture_dma_data;
+       dma_data->maxburst = 16;
+       dma_data->slave_id = JZ4740_DMA_TYPE_AIC_RECEIVE;
+       dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO;
 }
 
 static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
@@ -371,6 +354,8 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
        clk_prepare_enable(i2s->clk_aic);
 
        jz4740_i2c_init_pcm_config(i2s);
+       snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data,
+               &i2s->capture_dma_data);
 
        conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
                (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
@@ -432,91 +417,41 @@ static const struct snd_soc_component_driver jz4740_i2s_component = {
 static int jz4740_i2s_dev_probe(struct platform_device *pdev)
 {
        struct jz4740_i2s *i2s;
+       struct resource *mem;
        int ret;
 
-       i2s = kzalloc(sizeof(*i2s), GFP_KERNEL);
-
+       i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
        if (!i2s)
                return -ENOMEM;
 
-       i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!i2s->mem) {
-               ret = -ENOENT;
-               goto err_free;
-       }
-
-       i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem),
-                               pdev->name);
-       if (!i2s->mem) {
-               ret = -EBUSY;
-               goto err_free;
-       }
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       i2s->base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(i2s->base))
+               return PTR_ERR(i2s->base);
 
-       i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem));
-       if (!i2s->base) {
-               ret = -EBUSY;
-               goto err_release_mem_region;
-       }
+       i2s->phys_base = mem->start;
 
-       i2s->phys_base = i2s->mem->start;
+       i2s->clk_aic = devm_clk_get(&pdev->dev, "aic");
+       if (IS_ERR(i2s->clk_aic))
+               return PTR_ERR(i2s->clk_aic);
 
-       i2s->clk_aic = clk_get(&pdev->dev, "aic");
-       if (IS_ERR(i2s->clk_aic)) {
-               ret = PTR_ERR(i2s->clk_aic);
-               goto err_iounmap;
-       }
-
-       i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
-       if (IS_ERR(i2s->clk_i2s)) {
-               ret = PTR_ERR(i2s->clk_i2s);
-               goto err_clk_put_aic;
-       }
+       i2s->clk_i2s = devm_clk_get(&pdev->dev, "i2s");
+       if (IS_ERR(i2s->clk_i2s))
+               return PTR_ERR(i2s->clk_i2s);
 
        platform_set_drvdata(pdev, i2s);
-       ret = snd_soc_register_component(&pdev->dev, &jz4740_i2s_component,
-                                        &jz4740_i2s_dai, 1);
 
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to register DAI\n");
-               goto err_clk_put_i2s;
-       }
-
-       return 0;
-
-err_clk_put_i2s:
-       clk_put(i2s->clk_i2s);
-err_clk_put_aic:
-       clk_put(i2s->clk_aic);
-err_iounmap:
-       iounmap(i2s->base);
-err_release_mem_region:
-       release_mem_region(i2s->mem->start, resource_size(i2s->mem));
-err_free:
-       kfree(i2s);
-
-       return ret;
-}
+       ret = devm_snd_soc_register_component(&pdev->dev,
+               &jz4740_i2s_component, &jz4740_i2s_dai, 1);
+       if (ret)
+               return ret;
 
-static int jz4740_i2s_dev_remove(struct platform_device *pdev)
-{
-       struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
-
-       snd_soc_unregister_component(&pdev->dev);
-
-       clk_put(i2s->clk_i2s);
-       clk_put(i2s->clk_aic);
-
-       iounmap(i2s->base);
-       release_mem_region(i2s->mem->start, resource_size(i2s->mem));
-
-       kfree(i2s);
-
-       return 0;
+       return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+               SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 
 static struct platform_driver jz4740_i2s_driver = {
        .probe = jz4740_i2s_dev_probe,
-       .remove = jz4740_i2s_dev_remove,
        .driver = {
                .name = "jz4740-i2s",
                .owner = THIS_MODULE,
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
deleted file mode 100644 (file)
index 1d7ef28..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- *  Copyright (C) 2010, 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 as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <linux/dma-mapping.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/mach-jz4740/dma.h>
-#include "jz4740-pcm.h"
-
-struct jz4740_runtime_data {
-       unsigned long dma_period;
-       dma_addr_t dma_start;
-       dma_addr_t dma_pos;
-       dma_addr_t dma_end;
-
-       struct jz4740_dma_chan *dma;
-
-       dma_addr_t fifo_addr;
-};
-
-/* identify hardware playback capabilities */
-static const struct snd_pcm_hardware jz4740_pcm_hardware = {
-       .info = SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_MMAP_VALID |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
-
-       .rates                  = SNDRV_PCM_RATE_8000_48000,
-       .channels_min           = 1,
-       .channels_max           = 2,
-       .period_bytes_min       = 16,
-       .period_bytes_max       = 2 * PAGE_SIZE,
-       .periods_min            = 2,
-       .periods_max            = 128,
-       .buffer_bytes_max       = 128 * 2 * PAGE_SIZE,
-       .fifo_size              = 32,
-};
-
-static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd,
-       struct snd_pcm_substream *substream)
-{
-       unsigned long count;
-
-       if (prtd->dma_pos == prtd->dma_end)
-               prtd->dma_pos = prtd->dma_start;
-
-       if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
-               count = prtd->dma_end - prtd->dma_pos;
-       else
-               count = prtd->dma_period;
-
-       jz4740_dma_disable(prtd->dma);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
-               jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
-       } else {
-               jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
-               jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
-       }
-
-       jz4740_dma_set_transfer_count(prtd->dma, count);
-
-       prtd->dma_pos += count;
-
-       jz4740_dma_enable(prtd->dma);
-}
-
-static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
-       void *dev_id)
-{
-       struct snd_pcm_substream *substream = dev_id;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-
-       snd_pcm_period_elapsed(substream);
-
-       jz4740_pcm_start_transfer(prtd, substream);
-}
-
-static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct jz4740_pcm_config *config;
-
-       config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-       if (!config)
-               return 0;
-
-       if (!prtd->dma) {
-               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-                       prtd->dma = jz4740_dma_request(substream, "PCM Capture");
-               else
-                       prtd->dma = jz4740_dma_request(substream, "PCM Playback");
-       }
-
-       if (!prtd->dma)
-               return -EBUSY;
-
-       jz4740_dma_configure(prtd->dma, &config->dma_config);
-       prtd->fifo_addr = config->fifo_addr;
-
-       jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
-
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
-
-       prtd->dma_period = params_period_bytes(params);
-       prtd->dma_start = runtime->dma_addr;
-       prtd->dma_pos = prtd->dma_start;
-       prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
-
-       return 0;
-}
-
-static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct jz4740_runtime_data *prtd = substream->runtime->private_data;
-
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       if (prtd->dma) {
-               jz4740_dma_free(prtd->dma);
-               prtd->dma = NULL;
-       }
-
-       return 0;
-}
-
-static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct jz4740_runtime_data *prtd = substream->runtime->private_data;
-
-       if (!prtd->dma)
-               return -EBUSY;
-
-       prtd->dma_pos = prtd->dma_start;
-
-       return 0;
-}
-
-static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               jz4740_pcm_start_transfer(prtd, substream);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               jz4740_dma_disable(prtd->dma);
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-       unsigned long byte_offset;
-       snd_pcm_uframes_t offset;
-       struct jz4740_dma_chan *dma = prtd->dma;
-
-       /* prtd->dma_pos points to the end of the current transfer. So by
-        * subtracting prdt->dma_start we get the offset to the end of the
-        * current period in bytes. By subtracting the residue of the transfer
-        * we get the current offset in bytes. */
-       byte_offset = prtd->dma_pos - prtd->dma_start;
-       byte_offset -= jz4740_dma_get_residue(dma);
-
-       offset = bytes_to_frames(runtime, byte_offset);
-       if (offset >= runtime->buffer_size)
-               offset = 0;
-
-       return offset;
-}
-
-static int jz4740_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd;
-
-       prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
-       if (prtd == NULL)
-               return -ENOMEM;
-
-       snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
-
-       runtime->private_data = prtd;
-
-       return 0;
-}
-
-static int jz4740_pcm_close(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-
-       kfree(prtd);
-
-       return 0;
-}
-
-static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
-       struct vm_area_struct *vma)
-{
-       return remap_pfn_range(vma, vma->vm_start,
-                       substream->dma_buffer.addr >> PAGE_SHIFT,
-                       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
-static struct snd_pcm_ops jz4740_pcm_ops = {
-       .open           = jz4740_pcm_open,
-       .close          = jz4740_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
-       .hw_params      = jz4740_pcm_hw_params,
-       .hw_free        = jz4740_pcm_hw_free,
-       .prepare        = jz4740_pcm_prepare,
-       .trigger        = jz4740_pcm_trigger,
-       .pointer        = jz4740_pcm_pointer,
-       .mmap           = jz4740_pcm_mmap,
-};
-
-static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = jz4740_pcm_hardware.buffer_bytes_max;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-
-       buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
-                                         &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-
-       buf->bytes = size;
-
-       return 0;
-}
-
-static void jz4740_pcm_free(struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = 0; stream < SNDRV_PCM_STREAM_LAST; ++stream) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-
-               dma_free_noncoherent(pcm->card->dev, buf->bytes, buf->area,
-                               buf->addr);
-               buf->area = NULL;
-       }
-}
-
-static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_card *card = rtd->card->snd_card;
-       struct snd_pcm *pcm = rtd->pcm;
-       int ret;
-
-       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
-       if (ret)
-               return ret;
-
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = jz4740_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       goto err;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = jz4740_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       goto err;
-       }
-
-err:
-       return ret;
-}
-
-static struct snd_soc_platform_driver jz4740_soc_platform = {
-               .ops            = &jz4740_pcm_ops,
-               .pcm_new        = jz4740_pcm_new,
-               .pcm_free       = jz4740_pcm_free,
-};
-
-static int jz4740_pcm_probe(struct platform_device *pdev)
-{
-       return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
-}
-
-static int jz4740_pcm_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver jz4740_pcm_driver = {
-       .probe = jz4740_pcm_probe,
-       .remove = jz4740_pcm_remove,
-       .driver = {
-               .name = "jz4740-pcm-audio",
-               .owner = THIS_MODULE,
-       },
-};
-
-module_platform_driver(jz4740_pcm_driver);
-
-MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
deleted file mode 100644 (file)
index 1220cbb..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * 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 _JZ4740_PCM_H
-#define _JZ4740_PCM_H
-
-#include <linux/dma-mapping.h>
-#include <asm/mach-jz4740/dma.h>
-
-
-struct jz4740_pcm_config {
-       struct jz4740_dma_config dma_config;
-       phys_addr_t fifo_addr;
-};
-
-#endif
index 55fd6b5df55f5d988799b93ec64995fb4c06a038..82b5f37cd2c78ab16be9eda44b751201d8b9f09d 100644 (file)
@@ -73,7 +73,7 @@ static struct snd_soc_dai_link qi_lb60_dai = {
        .name = "jz4740",
        .stream_name = "jz4740",
        .cpu_dai_name = "jz4740-i2s",
-       .platform_name = "jz4740-pcm-audio",
+       .platform_name = "jz4740-i2s",
        .codec_dai_name = "jz4740-hifi",
        .codec_name = "jz4740-codec",
        .init = qi_lb60_codec_init,
index 4af1936cf0f4fdbbaafe0bee2879872418efadd7..aac22fccdcdc3e3954b35493df9773d4fd8c98fe 100644 (file)
 #include <sound/soc.h>
 #include "kirkwood.h"
 
-#define KIRKWOOD_RATES \
-       (SNDRV_PCM_RATE_8000_192000 |           \
-        SNDRV_PCM_RATE_CONTINUOUS |            \
-        SNDRV_PCM_RATE_KNOT)
-
-#define KIRKWOOD_FORMATS \
-       (SNDRV_PCM_FMTBIT_S16_LE | \
-        SNDRV_PCM_FMTBIT_S24_LE | \
-        SNDRV_PCM_FMTBIT_S32_LE)
-
 static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
 {
        struct snd_soc_pcm_runtime *soc_runtime = subs->private_data;
@@ -43,12 +33,6 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
                 SNDRV_PCM_INFO_MMAP_VALID |
                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                 SNDRV_PCM_INFO_PAUSE),
-       .formats                = KIRKWOOD_FORMATS,
-       .rates                  = KIRKWOOD_RATES,
-       .rate_min               = 8000,
-       .rate_max               = 384000,
-       .channels_min           = 1,
-       .channels_max           = 8,
        .buffer_bytes_max       = KIRKWOOD_SND_MAX_BUFFER_BYTES,
        .period_bytes_min       = KIRKWOOD_SND_MIN_PERIOD_BYTES,
        .period_bytes_max       = KIRKWOOD_SND_MAX_PERIOD_BYTES,
index d34d91743e3ffe95f9e4823bafdd33d78875b6c3..3920a5e8125f886e15caa6607fed9e84a32950cd 100644 (file)
         SNDRV_PCM_FMTBIT_S24_LE | \
         SNDRV_PCM_FMTBIT_S32_LE)
 
+#define KIRKWOOD_SPDIF_FORMATS \
+       (SNDRV_PCM_FMTBIT_S16_LE | \
+        SNDRV_PCM_FMTBIT_S24_LE)
+
 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
@@ -244,15 +248,15 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                   ctl);
        }
 
-       if (dai->id == 0)
-               ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
-       else
-               ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
-
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                /* configure */
                ctl = priv->ctl_play;
+               if (dai->id == 0)
+                       ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
+               else
+                       ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
+
                value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
                writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
@@ -449,14 +453,14 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
                                SNDRV_PCM_RATE_96000,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
                                SNDRV_PCM_RATE_96000,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
     },
@@ -469,17 +473,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
@@ -490,18 +494,18 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
     },
index b16abbbf7764beddd61d42514f70bd33338a7781..a371b4f91c534d22e1e13aacfff93a490dfb461d 100644 (file)
@@ -36,11 +36,6 @@ static const struct snd_pcm_hardware snd_mxs_hardware = {
                                  SNDRV_PCM_INFO_RESUME |
                                  SNDRV_PCM_INFO_INTERLEAVED |
                                  SNDRV_PCM_INFO_HALF_DUPLEX,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE |
-                                 SNDRV_PCM_FMTBIT_S20_3LE |
-                                 SNDRV_PCM_FMTBIT_S24_LE,
-       .channels_min           = 2,
-       .channels_max           = 2,
        .period_bytes_min       = 32,
        .period_bytes_max       = 8192,
        .periods_min            = 1,
@@ -56,16 +51,9 @@ static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = {
 
 int mxs_pcm_platform_register(struct device *dev)
 {
-       return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
-               SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
+       return devm_snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX);
 }
 EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
 
-void mxs_pcm_platform_unregister(struct device *dev)
-{
-       snd_dmaengine_pcm_unregister(dev);
-}
-EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister);
-
 MODULE_LICENSE("GPL");
index bc685b67cac71e80c17657357c9eb388eac0ac2e..035ea0436ca5fe83a83b210ba101ad90650acca3 100644 (file)
@@ -20,6 +20,5 @@
 #define _MXS_PCM_H
 
 int mxs_pcm_platform_register(struct device *dev);
-void mxs_pcm_platform_unregister(struct device *dev);
 
 #endif
index 54e622acac330d82a92d95164ae79e89cfb461e4..231d7e7b07110d9e219788810acf70d62f1e00c6 100644 (file)
@@ -50,9 +50,9 @@ static struct mxs_saif *mxs_saif[2];
  * This also means that both SAIFs must operate at the same sample rate.
  *
  * We abstract this as each saif has a master, the master could be
- * himself or other saifs. In the generic saif driver, saif does not need
- * to know the different clkmux. Saif only needs to know who is his master
- * and operating his master to generate the proper clock rate for him.
+ * itself or other saifs. In the generic saif driver, saif does not need
+ * to know the different clkmux. Saif only needs to know who is its master
+ * and operating its master to generate the proper clock rate for it.
  * The master id is provided in mach-specific layer according to different
  * clkmux setting.
  */
@@ -76,7 +76,7 @@ static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
  * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK
  * is provided by other SAIF, we provide a interface here to get its master
  * from its master_id.
- * Note that the master could be himself.
+ * Note that the master could be itself.
  */
 static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif)
 {
@@ -516,7 +516,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
                }
 
                /*
-                * If the saif's master is not himself, we also need to enable
+                * If the saif's master is not itself, we also need to enable
                 * itself clk for its internal basic logic to work.
                 */
                if (saif != master_saif) {
@@ -804,13 +804,6 @@ static int mxs_saif_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int mxs_saif_remove(struct platform_device *pdev)
-{
-       mxs_pcm_platform_unregister(&pdev->dev);
-
-       return 0;
-}
-
 static const struct of_device_id mxs_saif_dt_ids[] = {
        { .compatible = "fsl,imx28-saif", },
        { /* sentinel */ }
@@ -819,7 +812,6 @@ MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
 
 static struct platform_driver mxs_saif_driver = {
        .probe = mxs_saif_probe,
-       .remove = mxs_saif_remove,
 
        .driver = {
                .name = "mxs-saif",
index f588ee45b4fdd610d21c316f469b81b687da40a9..f434ed79d1b613bc64470cfa3041f4808b237f47 100644 (file)
@@ -32,9 +32,6 @@ static const struct snd_pcm_hardware nuc900_pcm_hardware = {
                                        SNDRV_PCM_INFO_MMAP_VALID |
                                        SNDRV_PCM_INFO_PAUSE |
                                        SNDRV_PCM_INFO_RESUME,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
-       .channels_min           = 1,
-       .channels_max           = 2,
        .buffer_bytes_max       = 4*1024,
        .period_bytes_min       = 1*1024,
        .period_bytes_max       = 4*1024,
index 83433fdea32ad790f839edd357c14824def13c07..86c75384c3c87dd0e4c9109f737122b1888ad295 100644 (file)
@@ -36,10 +36,10 @@ static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 
        if (mcbsp->pdata->reg_size == 2) {
                ((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
-               __raw_writew((u16)val, addr);
+               writew_relaxed((u16)val, addr);
        } else {
                ((u32 *)mcbsp->reg_cache)[reg] = val;
-               __raw_writel(val, addr);
+               writel_relaxed(val, addr);
        }
 }
 
@@ -48,22 +48,22 @@ static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
        void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
 
        if (mcbsp->pdata->reg_size == 2) {
-               return !from_cache ? __raw_readw(addr) :
+               return !from_cache ? readw_relaxed(addr) :
                                     ((u16 *)mcbsp->reg_cache)[reg];
        } else {
-               return !from_cache ? __raw_readl(addr) :
+               return !from_cache ? readl_relaxed(addr) :
                                     ((u32 *)mcbsp->reg_cache)[reg];
        }
 }
 
 static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
-       __raw_writel(val, mcbsp->st_data->io_base_st + reg);
+       writel_relaxed(val, mcbsp->st_data->io_base_st + reg);
 }
 
 static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 {
-       return __raw_readl(mcbsp->st_data->io_base_st + reg);
+       return readl_relaxed(mcbsp->st_data->io_base_st + reg);
 }
 
 #define MCBSP_READ(mcbsp, reg) \
index 6d216cb6c19bd2ba92c4d326d2ee6761dc2e5ef3..3fde9e402710f2bb16baf80b605da42772df69a0 100644 (file)
@@ -100,12 +100,12 @@ static int n810_startup(struct snd_pcm_substream *substream)
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
 
        n810_ext_control(&codec->dapm);
-       return clk_enable(sys_clkout2);
+       return clk_prepare_enable(sys_clkout2);
 }
 
 static void n810_shutdown(struct snd_pcm_substream *substream)
 {
-       clk_disable(sys_clkout2);
+       clk_disable_unprepare(sys_clkout2);
 }
 
 static int n810_hw_params(struct snd_pcm_substream *substream,
index 12e566be3793e61eb4fdd7d9ac47a23d638bc260..1bd531d718f953c3a2cd0e533e0f4340d3713892 100644 (file)
@@ -61,12 +61,12 @@ struct omap_dmic {
 
 static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
 {
-       __raw_writel(val, dmic->io_base + reg);
+       writel_relaxed(val, dmic->io_base + reg);
 }
 
 static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
 {
-       return __raw_readl(dmic->io_base + reg);
+       return readl_relaxed(dmic->io_base + reg);
 }
 
 static inline void omap_dmic_start(struct omap_dmic *dmic)
index cd9ee167959dcc0b34512ffdf32d26208d506c31..2f5b1536477e8895238d21f400f21370a14f3041 100644 (file)
@@ -74,12 +74,12 @@ struct omap_mcpdm {
 
 static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
 {
-       __raw_writel(val, mcpdm->io_base + reg);
+       writel_relaxed(val, mcpdm->io_base + reg);
 }
 
 static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
 {
-       return __raw_readl(mcpdm->io_base + reg);
+       return readl_relaxed(mcpdm->io_base + reg);
 }
 
 #ifdef DEBUG
index b8fa9862e54c4a6c6d99c8d3b88e8204d3cd9d63..07b8b7bc9d20f4e3cceebcb3dbb16492f51ddc46 100644 (file)
@@ -45,8 +45,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
                                  SNDRV_PCM_INFO_PAUSE |
                                  SNDRV_PCM_INFO_RESUME |
                                  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE |
-                                 SNDRV_PCM_FMTBIT_S32_LE,
        .period_bytes_min       = 32,
        .period_bytes_max       = 64 * 1024,
        .periods_min            = 2,
index 4db74a083db1ef792f90dde317ee9e7556eb4e1d..6473052b689963996713e44e601181ec2e14b47e 100644 (file)
@@ -11,7 +11,7 @@ config SND_PXA2XX_SOC
 config SND_MMP_SOC
        bool "Soc Audio for Marvell MMP chips"
        depends on ARCH_MMP
-       select SND_DMAENGINE_PCM
+       select SND_SOC_GENERIC_DMAENGINE_PCM
        select SND_ARM
        help
          Say Y if you want to add support for codecs attached to
index 7929e19b0ef5970b1942da441770df909f29629e..5e8d813301731f6b99a56228efafa81dfa78126e 100644 (file)
@@ -36,14 +36,9 @@ struct mmp_dma_data {
                SNDRV_PCM_INFO_PAUSE |          \
                SNDRV_PCM_INFO_RESUME)
 
-#define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
-                        SNDRV_PCM_FMTBIT_S24_LE | \
-                        SNDRV_PCM_FMTBIT_S32_LE)
-
 static struct snd_pcm_hardware mmp_pcm_hardware[] = {
        {
                .info                   = MMP_PCM_INFO,
-               .formats                = MMP_PCM_FORMATS,
                .period_bytes_min       = 1024,
                .period_bytes_max       = 2048,
                .periods_min            = 2,
@@ -53,7 +48,6 @@ static struct snd_pcm_hardware mmp_pcm_hardware[] = {
        },
        {
                .info                   = MMP_PCM_INFO,
-               .formats                = MMP_PCM_FORMATS,
                .period_bytes_min       = 1024,
                .period_bytes_max       = 2048,
                .periods_min            = 2,
@@ -67,27 +61,15 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *params)
 {
        struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_dmaengine_dai_dma_data *dma_params;
        struct dma_slave_config slave_config;
        int ret;
 
-       dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       if (!dma_params)
-               return 0;
-
-       ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
+       ret =
+           snd_dmaengine_pcm_prepare_slave_config(substream, params,
+                                                  &slave_config);
        if (ret)
                return ret;
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               slave_config.dst_addr     = dma_params->addr;
-               slave_config.dst_maxburst = 4;
-       } else {
-               slave_config.src_addr     = dma_params->addr;
-               slave_config.src_maxburst = 4;
-       }
-
        ret = dmaengine_slave_config(chan, &slave_config);
        if (ret)
                return ret;
index 73bb99f0109a2579597128e692c7d70f1de8758d..7eba7979b9af606df34b2d40be1dceb8ef9a7964 100644 (file)
@@ -405,8 +405,7 @@ static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-#define S6000_I2S_RATES        (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \
-                        SNDRV_PCM_RATE_8000_192000)
+#define S6000_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
 #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
index d219880815c0142dad341502405a9887977c159d..fb8461e1b1f6664c2aa151b96661c4103fbd61bd 100644 (file)
@@ -33,13 +33,6 @@ static struct snd_pcm_hardware s6000_pcm_hardware = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
                 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX),
-       .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE),
-       .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \
-                 SNDRV_PCM_RATE_8000_192000),
-       .rate_min = 0,
-       .rate_max = 1562500,
-       .channels_min = 2,
-       .channels_max = 8,
        .buffer_bytes_max = 0x7ffffff0,
        .period_bytes_min = 16,
        .period_bytes_max = 0xfffff0,
index 37459dfd168d3d16362330cdf0ba047d29d41e97..27930fc432dcfe4b750ba3a9f2ff70bf50d78f1e 100644 (file)
@@ -1,13 +1,22 @@
 config SND_SOC_SAMSUNG
        tristate "ASoC support for Samsung"
        depends on PLAT_SAMSUNG
-       select S3C64XX_DMA if ARCH_S3C64XX
-       select S3C24XX_DMA if ARCH_S3C24XX
+       select S3C2410_DMA if ARCH_S3C24XX
+       select S3C64XX_PL080 if ARCH_S3C64XX
+       select SND_S3C_DMA if !ARCH_S3C24XX
+       select SND_S3C_DMA_LEGACY if ARCH_S3C24XX
+       select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX
        help
          Say Y or M if you want to add support for codecs attached to
          the Samsung SoCs' Audio interfaces. You will also need to
          select the audio interfaces to support below.
 
+config SND_S3C_DMA
+       tristate
+
+config SND_S3C_DMA_LEGACY
+       tristate
+
 config SND_S3C24XX_I2S
        tristate
        select S3C2410_DMA
index 709f6059ad67da928245a2faf3df900552e82d44..86715d8efee66ca459adc99c2d68ca34907b1c45 100644 (file)
@@ -1,5 +1,6 @@
 # S3c24XX Platform Support
-snd-soc-s3c24xx-objs := dma.o
+snd-soc-s3c-dma-objs := dmaengine.o
+snd-soc-s3c-dma-legacy-objs := dma.o
 snd-soc-idma-objs := idma.o
 snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
 snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
@@ -9,7 +10,8 @@ snd-soc-samsung-spdif-objs := spdif.o
 snd-soc-pcm-objs := pcm.o
 snd-soc-i2s-objs := i2s.o
 
-obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c24xx.o
+obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o
+obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o
 obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o
 obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o
 obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
index 350ba23a9893484edb3d0585518b7048d568e875..4a88e36c82ec1c827d7cd8658e0223991a3b621f 100644 (file)
@@ -221,24 +221,6 @@ static struct snd_ac97_bus_ops s3c_ac97_ops = {
        .reset      = s3c_ac97_cold_reset,
 };
 
-static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
-                                 struct snd_pcm_hw_params *params,
-                                 struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct s3c_dma_params *dma_data;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_data = &s3c_ac97_pcm_out;
-       else
-               dma_data = &s3c_ac97_pcm_in;
-
-       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
-
-       return 0;
-}
-
 static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
                                struct snd_soc_dai *dai)
 {
@@ -279,21 +261,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
        return 0;
 }
 
-static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_hw_params *params,
-                                     struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               return -ENODEV;
-       else
-               snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in);
-
-       return 0;
-}
-
 static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
                                    int cmd, struct snd_soc_dai *dai)
 {
@@ -329,15 +296,27 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 }
 
 static const struct snd_soc_dai_ops s3c_ac97_dai_ops = {
-       .hw_params      = s3c_ac97_hw_params,
        .trigger        = s3c_ac97_trigger,
 };
 
 static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
-       .hw_params      = s3c_ac97_hw_mic_params,
        .trigger        = s3c_ac97_mic_trigger,
 };
 
+static int s3c_ac97_dai_probe(struct snd_soc_dai *dai)
+{
+       samsung_asoc_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in);
+
+       return 0;
+}
+
+static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai)
+{
+       samsung_asoc_init_dma_data(dai, NULL, &s3c_ac97_mic_in);
+
+       return 0;
+}
+
 static struct snd_soc_dai_driver s3c_ac97_dai[] = {
        [S3C_AC97_DAI_PCM] = {
                .name = "samsung-ac97",
@@ -354,6 +333,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
                        .channels_max = 2,
                        .rates = SNDRV_PCM_RATE_8000_48000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+               .probe = s3c_ac97_dai_probe,
                .ops = &s3c_ac97_dai_ops,
        },
        [S3C_AC97_DAI_MIC] = {
@@ -365,6 +345,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = {
                        .channels_max = 1,
                        .rates = SNDRV_PCM_RATE_8000_48000,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+               .probe = s3c_ac97_mic_dai_probe,
                .ops = &s3c_ac97_mic_dai_ops,
        },
 };
index fe2748b494d4cd38c6db6ae4409d38f56819ff3f..dc09b71b7d9f766398a94592a1657f7cdbe5667a 100644 (file)
@@ -35,12 +35,6 @@ static const struct snd_pcm_hardware dma_hardware = {
                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                    SNDRV_PCM_INFO_MMAP |
                                    SNDRV_PCM_INFO_MMAP_VALID,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE |
-                                   SNDRV_PCM_FMTBIT_U16_LE |
-                                   SNDRV_PCM_FMTBIT_U8 |
-                                   SNDRV_PCM_FMTBIT_S8,
-       .channels_min           = 2,
-       .channels_max           = 2,
        .buffer_bytes_max       = 128*1024,
        .period_bytes_min       = PAGE_SIZE,
        .period_bytes_max       = PAGE_SIZE*2,
@@ -441,6 +435,14 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
        .pcm_free       = dma_free_dma_buffers,
 };
 
+void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
+                               struct s3c_dma_params *playback,
+                               struct s3c_dma_params *capture)
+{
+       snd_soc_dai_init_dma_data(dai, playback, capture);
+}
+EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
+
 int samsung_asoc_dma_platform_register(struct device *dev)
 {
        return snd_soc_register_platform(dev, &samsung_asoc_platform);
index 0e86315a3eaf11859d32ab78b1327ce1a60e39c4..225e5378014eca4395d4481c77ddf2c1632b31a3 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef _S3C_AUDIO_H
 #define _S3C_AUDIO_H
 
+#include <sound/dmaengine_pcm.h>
+
 struct s3c_dma_params {
        struct s3c2410_dma_client *client;      /* stream identifier */
        int channel;                            /* Channel ID */
@@ -20,8 +22,12 @@ struct s3c_dma_params {
        unsigned ch;
        struct samsung_dma_ops *ops;
        char *ch_name;
+       struct snd_dmaengine_dai_dma_data dma_data;
 };
 
+void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
+                               struct s3c_dma_params *playback,
+                               struct s3c_dma_params *capture);
 int samsung_asoc_dma_platform_register(struct device *dev);
 void samsung_asoc_dma_platform_unregister(struct device *dev);
 
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c
new file mode 100644 (file)
index 0000000..750ce58
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * dmaengine.c - Samsung dmaengine wrapper
+ *
+ * Author: Mark Brown <broonie@linaro.org>
+ * Copyright 2013 Linaro
+ *
+ * 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/amba/pl08x.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "dma.h"
+
+#ifdef CONFIG_ARCH_S3C64XX
+#define filter_fn pl08x_filter_id
+#else
+#define filter_fn NULL
+#endif
+
+static const struct snd_dmaengine_pcm_config samsung_dmaengine_pcm_config = {
+       .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+       .compat_filter_fn = filter_fn,
+};
+
+void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
+                               struct s3c_dma_params *playback,
+                               struct s3c_dma_params *capture)
+{
+       struct snd_dmaengine_dai_dma_data *playback_data = NULL;
+       struct snd_dmaengine_dai_dma_data *capture_data = NULL;
+
+       if (playback) {
+               playback_data = &playback->dma_data;
+               playback_data->filter_data = (void *)playback->channel;
+               playback_data->chan_name = playback->ch_name;
+               playback_data->addr = playback->dma_addr;
+               playback_data->addr_width = playback->dma_size;
+       }
+       if (capture) {
+               capture_data = &capture->dma_data;
+               capture_data->filter_data = (void *)capture->channel;
+               capture_data->chan_name = capture->ch_name;
+               capture_data->addr = capture->dma_addr;
+               capture_data->addr_width = capture->dma_size;
+       }
+
+       snd_soc_dai_init_dma_data(dai, playback_data, capture_data);
+}
+EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
+
+int samsung_asoc_dma_platform_register(struct device *dev)
+{
+       return snd_dmaengine_pcm_register(dev, &samsung_dmaengine_pcm_config,
+                                         SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME |
+                                         SND_DMAENGINE_PCM_FLAG_COMPAT);
+}
+EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register);
+
+void samsung_asoc_dma_platform_unregister(struct device *dev)
+{
+       return snd_dmaengine_pcm_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister);
+
+MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
+MODULE_DESCRIPTION("Samsung dmaengine ASoC driver");
+MODULE_LICENSE("GPL");
index a5cbdb4f1655d8213a778159c34a0fb0321b2b77..92f64363427d44b741f2293fa84982c748a72d82 100644 (file)
@@ -702,6 +702,8 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
        }
        writel(mod, i2s->addr + I2SMOD);
 
+       samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
+
        i2s->frmclk = params_rate(params);
 
        return 0;
@@ -946,8 +948,11 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
        struct i2s_dai *i2s = to_info(dai);
        struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai;
 
-       if (other && other->clk) /* If this is probe on secondary */
+       if (other && other->clk) { /* If this is probe on secondary */
+               samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback,
+                                          NULL);
                goto probe_exit;
+       }
 
        i2s->addr = ioremap(i2s->base, 0x100);
        if (i2s->addr == NULL) {
@@ -963,7 +968,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
        }
        clk_prepare_enable(i2s->clk);
 
-       snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
+       samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
 
        if (other) {
                other->addr = i2s->addr;
index e4f318fc2f82bb048f5047a6773f1a2c8be40902..3d5cf1530b6f754c4ff03c476777e2a61c3d45a1 100644 (file)
@@ -35,14 +35,6 @@ static const struct snd_pcm_hardware idma_hardware = {
                    SNDRV_PCM_INFO_MMAP_VALID |
                    SNDRV_PCM_INFO_PAUSE |
                    SNDRV_PCM_INFO_RESUME,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE |
-                   SNDRV_PCM_FMTBIT_U16_LE |
-                   SNDRV_PCM_FMTBIT_S24_LE |
-                   SNDRV_PCM_FMTBIT_U24_LE |
-                   SNDRV_PCM_FMTBIT_U8 |
-                   SNDRV_PCM_FMTBIT_S8,
-       .channels_min = 2,
-       .channels_max = 2,
        .buffer_bytes_max = MAX_IDMA_BUFFER,
        .period_bytes_min = 128,
        .period_bytes_max = MAX_IDMA_PERIOD,
index e54256fc4b2c6d35faa47f8c3a1d42ddb3f5c74e..6a5e4bf6ac96efaa1b3b3dba063390165eee724e 100644 (file)
@@ -275,7 +275,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-       struct s3c_dma_params *dma_data;
        void __iomem *regs = pcm->regs;
        struct clk *clk;
        int sclk_div, sync_div;
@@ -284,13 +283,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
 
        dev_dbg(pcm->dev, "Entered %s\n", __func__);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_data = pcm->dma_playback;
-       else
-               dma_data = pcm->dma_capture;
-
-       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
-
        /* Strictly check for sample size */
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
@@ -461,10 +453,20 @@ static const struct snd_soc_dai_ops s3c_pcm_dai_ops = {
        .set_fmt        = s3c_pcm_set_fmt,
 };
 
+static int s3c_pcm_dai_probe(struct snd_soc_dai *dai)
+{
+       struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, pcm->dma_playback, pcm->dma_capture);
+
+       return 0;
+}
+
 #define S3C_PCM_RATES  SNDRV_PCM_RATE_8000_96000
 
 #define S3C_PCM_DAI_DECLARE                    \
        .symmetric_rates = 1,                                   \
+       .probe = s3c_pcm_dai_probe,                             \
        .ops = &s3c_pcm_dai_ops,                                \
        .playback = {                                           \
                .channels_min   = 2,                            \
index c3878f7acb83fb33ac39d370ecd384e42bc4a473..a71be45bbffc87b6bb52c896ac29a13360494c80 100644 (file)
@@ -1,5 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-ac97.h
- *
+/*
  * Copyright (c) 2006 Simtec Electronics <linux@simtec.co.uk>
  *             http://www.simtec.co.uk/products/SWLINUX/
  *
@@ -10,8 +9,8 @@
  * S3C2440 AC97 Controller
 */
 
-#ifndef __ASM_ARCH_REGS_AC97_H
-#define __ASM_ARCH_REGS_AC97_H __FILE__
+#ifndef __SAMSUNG_REGS_AC97_H__
+#define __SAMSUNG_REGS_AC97_H__
 
 #define S3C_AC97_GLBCTRL                               (0x00)
 
@@ -64,4 +63,4 @@
 #define S3C_AC97_PCM_DATA                              (0x18)
 #define S3C_AC97_MIC_DATA                              (0x1C)
 
-#endif /* __ASM_ARCH_REGS_AC97_H */
+#endif /* __SAMSUNG_REGS_AC97_H__ */
index a18d35e7a735f156de8a8ee63ab9a546fc526220..dc6cbbe9c4f0eae35ef7e7074047e068b0b50f5f 100644 (file)
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/include/plat/regs-iis.h
- *
+/*
  * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  *                   http://www.simtec.co.uk/products/SWLINUX/
  *
@@ -10,8 +9,8 @@
  * S3C2410 IIS register definition
 */
 
-#ifndef __ASM_ARCH_REGS_IIS_H
-#define __ASM_ARCH_REGS_IIS_H
+#ifndef __SAMSUNG_REGS_IIS_H__
+#define __SAMSUNG_REGS_IIS_H__
 
 #define S3C2410_IISCON                 (0x00)
 
@@ -67,4 +66,4 @@
 
 #define S3C2410_IISFIFO                        (0x10)
 
-#endif /* __ASM_ARCH_REGS_IIS_H */
+#endif /* __SAMSUNG_REGS_IIS_H__ */
index 14011d90d70af3180f4eeedee2fa254a6d5fde25..ff60e11ecb564674bdffbe8814392fe1b2b01065 100644 (file)
@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
 config SND_SOC_RCAR
        tristate "R-Car series SRU/SCU/SSIU/SSI support"
        select SND_SIMPLE_CARD
+       select REGMAP
        help
          This option enables R-Car SUR/SCU/SSIU/SSI sound support
 
index 1a8b03e4b41b9c3f7ce38fcc79130307d757cb51..c85f8eb66c972892654b7a4e37e2818b779f2b65 100644 (file)
@@ -89,29 +89,12 @@ struct camelot_pcm {
 #define DMABRG_PREALLOC_BUFFER         32 * 1024
 #define DMABRG_PREALLOC_BUFFER_MAX     32 * 1024
 
-/* support everything the SSI supports */
-#define DMABRG_RATES   \
-       SNDRV_PCM_RATE_8000_192000
-
-#define DMABRG_FMTS    \
-       (SNDRV_PCM_FMTBIT_S8      | SNDRV_PCM_FMTBIT_U8      |  \
-        SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_U16_LE  |  \
-        SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE |  \
-        SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |  \
-        SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
-
 static struct snd_pcm_hardware camelot_pcm_hardware = {
        .info = (SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
                SNDRV_PCM_INFO_MMAP_VALID |
                SNDRV_PCM_INFO_BATCH),
-       .formats =      DMABRG_FMTS,
-       .rates =        DMABRG_RATES,
-       .rate_min =             8000,
-       .rate_max =             192000,
-       .channels_min =         2,
-       .channels_max =         8,              /* max of the SSI */
        .buffer_bytes_max =     DMABRG_PERIOD_MAX,
        .period_bytes_min =     DMABRG_PERIOD_MIN,
        .period_bytes_max =     DMABRG_PERIOD_MAX / 2,
index b33ca7cd085bf4b766dee1900a4101beffc9fa72..1967f44e7cd4d18fd078a71c52c3f0faf472b95f 100644 (file)
@@ -232,9 +232,9 @@ struct fsi_stream {
         * these are for DMAEngine
         */
        struct dma_chan         *chan;
-       struct sh_dmae_slave    slave; /* see fsi_handler_init() */
        struct work_struct      work;
        dma_addr_t              dma;
+       int                     dma_id;
        int                     loop_cnt;
        int                     additional_pos;
 };
@@ -1410,15 +1410,6 @@ static void fsi_dma_do_work(struct work_struct *work)
        }
 }
 
-static bool fsi_dma_filter(struct dma_chan *chan, void *param)
-{
-       struct sh_dmae_slave *slave = param;
-
-       chan->private = slave;
-
-       return true;
-}
-
 static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
 {
        schedule_work(&io->work);
@@ -1446,15 +1437,34 @@ static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
 static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
 {
        dma_cap_mask_t mask;
+       int is_play = fsi_stream_is_play(fsi, io);
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+       io->chan = dma_request_slave_channel_compat(mask,
+                               shdma_chan_filter, (void *)io->dma_id,
+                               dev, is_play ? "tx" : "rx");
+       if (io->chan) {
+               struct dma_slave_config cfg;
+               int ret;
+
+               cfg.slave_id    = io->dma_id;
+               cfg.dst_addr    = 0; /* use default addr */
+               cfg.src_addr    = 0; /* use default addr */
+               cfg.direction   = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+
+               ret = dmaengine_slave_config(io->chan, &cfg);
+               if (ret < 0) {
+                       dma_release_channel(io->chan);
+                       io->chan = NULL;
+               }
+       }
+
        if (!io->chan) {
 
                /* switch to PIO handler */
-               if (fsi_stream_is_play(fsi, io))
+               if (is_play)
                        fsi->playback.handler   = &fsi_pio_push_handler;
                else
                        fsi->capture.handler    = &fsi_pio_pop_handler;
@@ -1777,12 +1787,6 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
                        SNDRV_PCM_INFO_MMAP             |
                        SNDRV_PCM_INFO_MMAP_VALID       |
                        SNDRV_PCM_INFO_PAUSE,
-       .formats                = FSI_FMTS,
-       .rates                  = FSI_RATES,
-       .rate_min               = 8000,
-       .rate_max               = 192000,
-       .channels_min           = 2,
-       .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
        .period_bytes_max       = 8192,
@@ -1960,7 +1964,7 @@ static void fsi_handler_init(struct fsi_priv *fsi,
        fsi->capture.priv       = fsi;
 
        if (info->tx_id) {
-               fsi->playback.slave.shdma_slave.slave_id = info->tx_id;
+               fsi->playback.dma_id  = info->tx_id;
                fsi->playback.handler = &fsi_dma_push_handler;
        }
 }
index 9430097979a580c972a989738bdeb9ada3557e5e..a53235c4d1b0dcc971d81ed04884e1636b80932a 100644 (file)
@@ -19,8 +19,8 @@
 struct rsnd_adg {
        struct clk *clk[CLKMAX];
 
-       int rate_of_441khz_div_6;
-       int rate_of_48khz_div_6;
+       int rbga_rate_for_441khz_div_6; /* RBGA */
+       int rbgb_rate_for_48khz_div_6;  /* RBGB */
        u32 ckr;
 };
 
@@ -30,41 +30,114 @@ struct rsnd_adg {
             i++, (pos) = adg->clk[i])
 #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
 
-static enum rsnd_reg rsnd_adg_ssi_reg_get(int id)
+static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
+                                        struct rsnd_mod *mod,
+                                        unsigned int src_rate,
+                                        unsigned int dst_rate)
 {
-       enum rsnd_reg reg;
+       struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+       struct device *dev = rsnd_priv_to_dev(priv);
+       int idx, sel, div, shift;
+       u32 mask, val;
+       int id = rsnd_mod_id(mod);
+       unsigned int sel_rate [] = {
+               clk_get_rate(adg->clk[CLKA]),   /* 000: CLKA */
+               clk_get_rate(adg->clk[CLKB]),   /* 001: CLKB */
+               clk_get_rate(adg->clk[CLKC]),   /* 010: CLKC */
+               0,                              /* 011: MLBCLK (not used) */
+               adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */
+               adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */
+       };
+
+       /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */
+       for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
+               for (div  = 128,        idx = 0;
+                    div <= 2048;
+                    div *= 2,          idx++) {
+                       if (src_rate == sel_rate[sel] / div) {
+                               val = (idx << 4) | sel;
+                               goto find_rate;
+                       }
+               }
+       }
+       dev_err(dev, "can't find convert src clk\n");
+       return -EINVAL;
+
+find_rate:
+       shift   = (id % 4) * 8;
+       mask    = 0xFF << shift;
+       val     = val << shift;
+
+       dev_dbg(dev, "adg convert src clk = %02x\n", val);
+
+       switch (id / 4) {
+       case 0:
+               rsnd_mod_bset(mod, AUDIO_CLK_SEL3, mask, val);
+               break;
+       case 1:
+               rsnd_mod_bset(mod, AUDIO_CLK_SEL4, mask, val);
+               break;
+       case 2:
+               rsnd_mod_bset(mod, AUDIO_CLK_SEL5, mask, val);
+               break;
+       }
+
+       /*
+        * Gen1 doesn't need dst_rate settings,
+        * since it uses SSI WS pin.
+        * see also rsnd_src_set_route_if_gen1()
+        */
+
+       return 0;
+}
+
+int rsnd_adg_set_convert_clk(struct rsnd_priv *priv,
+                            struct rsnd_mod *mod,
+                            unsigned int src_rate,
+                            unsigned int dst_rate)
+{
+       if (rsnd_is_gen1(priv))
+               return rsnd_adg_set_convert_clk_gen1(priv, mod,
+                                                    src_rate, dst_rate);
+
+       return -EINVAL;
+}
+
+static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val)
+{
+       int id = rsnd_mod_id(mod);
+       int shift = (id % 4) * 8;
+       u32 mask = 0xFF << shift;
+
+       val = val << shift;
 
        /*
         * SSI 8 is not connected to ADG.
         * it works with SSI 7
         */
        if (id == 8)
-               return RSND_REG_MAX;
-
-       if (0 <= id && id <= 3)
-               reg = RSND_REG_AUDIO_CLK_SEL0;
-       else if (4 <= id && id <= 7)
-               reg = RSND_REG_AUDIO_CLK_SEL1;
-       else
-               reg = RSND_REG_AUDIO_CLK_SEL2;
-
-       return reg;
+               return;
+
+       switch (id / 4) {
+       case 0:
+               rsnd_mod_bset(mod, AUDIO_CLK_SEL0, mask, val);
+               break;
+       case 1:
+               rsnd_mod_bset(mod, AUDIO_CLK_SEL1, mask, val);
+               break;
+       case 2:
+               rsnd_mod_bset(mod, AUDIO_CLK_SEL2, mask, val);
+               break;
+       }
 }
 
 int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod)
 {
-       struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-       enum rsnd_reg reg;
-       int id;
-
        /*
         * "mod" = "ssi" here.
         * we can get "ssi id" from mod
         */
-       id  = rsnd_mod_id(mod);
-       reg = rsnd_adg_ssi_reg_get(id);
-
-       rsnd_write(priv, mod, reg, 0);
+       rsnd_adg_set_ssi_clk(mod, 0);
 
        return 0;
 }
@@ -75,8 +148,7 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
        struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
        struct device *dev = rsnd_priv_to_dev(priv);
        struct clk *clk;
-       enum rsnd_reg reg;
-       int id, shift, i;
+       int i;
        u32 data;
        int sel_table[] = {
                [CLKA] = 0x1,
@@ -102,12 +174,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
        /*
         * find 1/6 clock from BRGA/BRGB
         */
-       if (rate == adg->rate_of_441khz_div_6) {
+       if (rate == adg->rbga_rate_for_441khz_div_6) {
                data = 0x10;
                goto found_clock;
        }
 
-       if (rate == adg->rate_of_48khz_div_6) {
+       if (rate == adg->rbgb_rate_for_48khz_div_6) {
                data = 0x20;
                goto found_clock;
        }
@@ -125,19 +197,10 @@ found_clock:
         * This "mod" = "ssi" here.
         * we can get "ssi id" from mod
         */
-       id  = rsnd_mod_id(mod);
-       reg = rsnd_adg_ssi_reg_get(id);
-
-       dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate);
-
-       /*
-        * Enable SSIx clock
-        */
-       shift = (id % 4) * 8;
+       rsnd_adg_set_ssi_clk(mod, data);
 
-       rsnd_bset(priv, mod, reg,
-                  0xFF << shift,
-                  data << shift);
+       dev_dbg(dev, "ADG: ssi%d selects clk%d = %d",
+               rsnd_mod_id(mod), i, rate);
 
        return 0;
 }
@@ -166,8 +229,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
         *      rsnd_adg_ssi_clk_try_start()
         */
        ckr = 0;
-       adg->rate_of_441khz_div_6 = 0;
-       adg->rate_of_48khz_div_6  = 0;
+       adg->rbga_rate_for_441khz_div_6 = 0;
+       adg->rbgb_rate_for_48khz_div_6  = 0;
        for_each_rsnd_clk(clk, adg, i) {
                rate = clk_get_rate(clk);
 
@@ -175,14 +238,14 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
                        continue;
 
                /* RBGA */
-               if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) {
-                       adg->rate_of_441khz_div_6 = rate / 6;
+               if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) {
+                       adg->rbga_rate_for_441khz_div_6 = rate / 6;
                        ckr |= brg_table[i] << 20;
                }
 
                /* RBGB */
-               if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) {
-                       adg->rate_of_48khz_div_6 = rate / 6;
+               if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) {
+                       adg->rbgb_rate_for_48khz_div_6 = rate / 6;
                        ckr |= brg_table[i] << 16;
                }
        }
index b3653d37f75f087cffd3880a5c22e06c693c78fe..743de5e3b1e1ed4cba8f5dcfce3a5d3cfd9471bf 100644 (file)
@@ -628,12 +628,6 @@ static struct snd_pcm_hardware rsnd_pcm_hardware = {
                        SNDRV_PCM_INFO_MMAP             |
                        SNDRV_PCM_INFO_MMAP_VALID       |
                        SNDRV_PCM_INFO_PAUSE,
-       .formats                = RSND_FMTS,
-       .rates                  = RSND_RATES,
-       .rate_min               = 8000,
-       .rate_max               = 192000,
-       .channels_min           = 2,
-       .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
        .period_bytes_max       = 8192,
index 61212ee97c28269a0cd245e424636c4f38efc4c7..add088bd4b2aa7163b98f5faab7bd84b52a77fff 100644 (file)
  */
 #include "rsnd.h"
 
-struct rsnd_gen_ops {
-       int (*probe)(struct platform_device *pdev,
-                    struct rcar_snd_info *info,
-                    struct rsnd_priv *priv);
-       void (*remove)(struct platform_device *pdev,
-                     struct rsnd_priv *priv);
-       int (*path_init)(struct rsnd_priv *priv,
-                        struct rsnd_dai *rdai,
-                        struct rsnd_dai_stream *io);
-       int (*path_exit)(struct rsnd_priv *priv,
-                        struct rsnd_dai *rdai,
-                        struct rsnd_dai_stream *io);
-};
-
 struct rsnd_gen {
        void __iomem *base[RSND_BASE_MAX];
 
@@ -86,12 +72,28 @@ static struct regmap_bus rsnd_regmap_bus = {
        .val_format_endian_default      = REGMAP_ENDIAN_NATIVE,
 };
 
+static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
+                                 struct rsnd_gen *gen, enum rsnd_reg reg)
+{
+       if (!gen->regs[reg]) {
+               struct device *dev = rsnd_priv_to_dev(priv);
+
+               dev_err(dev, "unsupported register access %x\n", reg);
+               return 0;
+       }
+
+       return 1;
+}
+
 u32 rsnd_read(struct rsnd_priv *priv,
              struct rsnd_mod *mod, enum rsnd_reg reg)
 {
        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
        u32 val;
 
+       if (!rsnd_is_accessible_reg(priv, gen, reg))
+               return 0;
+
        regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
 
        return val;
@@ -103,6 +105,9 @@ void rsnd_write(struct rsnd_priv *priv,
 {
        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 
+       if (!rsnd_is_accessible_reg(priv, gen, reg))
+               return;
+
        regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
 }
 
@@ -111,21 +116,48 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
 {
        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 
+       if (!rsnd_is_accessible_reg(priv, gen, reg))
+               return;
+
        regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
                                  mask, data);
 }
 
-/*
- *             Gen2
- *             will be filled in the future
- */
+static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
+                               struct rsnd_gen  *gen,
+                               struct reg_field *regf)
+{
+       int i;
+       struct device *dev = rsnd_priv_to_dev(priv);
+       struct regmap_config regc;
 
-/*
- *             Gen1
- */
-static int rsnd_gen1_path_init(struct rsnd_priv *priv,
-                              struct rsnd_dai *rdai,
-                              struct rsnd_dai_stream *io)
+       memset(&regc, 0, sizeof(regc));
+       regc.reg_bits = 32;
+       regc.val_bits = 32;
+
+       gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, &regc);
+       if (IS_ERR(gen->regmap)) {
+               dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
+               return PTR_ERR(gen->regmap);
+       }
+
+       for (i = 0; i < RSND_REG_MAX; i++) {
+               gen->regs[i] = NULL;
+               if (!regf[i].reg)
+                       continue;
+
+               gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
+               if (IS_ERR(gen->regs[i]))
+                       return PTR_ERR(gen->regs[i]);
+
+       }
+
+       return 0;
+}
+
+int rsnd_gen_path_init(struct rsnd_priv *priv,
+                      struct rsnd_dai *rdai,
+                      struct rsnd_dai_stream *io)
 {
        struct rsnd_mod *mod;
        int ret;
@@ -163,9 +195,9 @@ static int rsnd_gen1_path_init(struct rsnd_priv *priv,
        return ret;
 }
 
-static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
-                              struct rsnd_dai *rdai,
-                              struct rsnd_dai_stream *io)
+int rsnd_gen_path_exit(struct rsnd_priv *priv,
+                      struct rsnd_dai *rdai,
+                      struct rsnd_dai_stream *io)
 {
        struct rsnd_mod *mod, *n;
        int ret = 0;
@@ -179,6 +211,94 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
        return ret;
 }
 
+/*
+ *             Gen2
+ */
+
+/* single address mapping */
+#define RSND_GEN2_S_REG(gen, reg, id, offset)                          \
+       RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)
+
+/* multi address mapping */
+#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset)              \
+       RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)
+
+static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
+{
+       struct reg_field regf[RSND_REG_MAX] = {
+               RSND_GEN2_S_REG(gen, SSIU,      SSI_MODE0,      0x800),
+               RSND_GEN2_S_REG(gen, SSIU,      SSI_MODE1,      0x804),
+               /* FIXME: it needs SSI_MODE2/3 in the future */
+               RSND_GEN2_M_REG(gen, SSIU,      INT_ENABLE,     0x18,   0x80),
+
+               RSND_GEN2_S_REG(gen, ADG,       BRRA,           0x00),
+               RSND_GEN2_S_REG(gen, ADG,       BRRB,           0x04),
+               RSND_GEN2_S_REG(gen, ADG,       SSICKR,         0x08),
+               RSND_GEN2_S_REG(gen, ADG,       AUDIO_CLK_SEL0, 0x0c),
+               RSND_GEN2_S_REG(gen, ADG,       AUDIO_CLK_SEL1, 0x10),
+               RSND_GEN2_S_REG(gen, ADG,       AUDIO_CLK_SEL2, 0x14),
+
+               RSND_GEN2_M_REG(gen, SSI,       SSICR,          0x00,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSISR,          0x04,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSITDR,         0x08,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSIRDR,         0x0c,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSIWSR,         0x20,   0x40),
+       };
+
+       return rsnd_gen_regmap_init(priv, gen, regf);
+}
+
+static int rsnd_gen2_probe(struct platform_device *pdev,
+                          struct rcar_snd_info *info,
+                          struct rsnd_priv *priv)
+{
+       struct device *dev = rsnd_priv_to_dev(priv);
+       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+       struct resource *scu_res;
+       struct resource *adg_res;
+       struct resource *ssiu_res;
+       struct resource *ssi_res;
+       int ret;
+
+       /*
+        * map address
+        */
+       scu_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU);
+       adg_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG);
+       ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU);
+       ssi_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI);
+
+       gen->base[RSND_GEN2_SCU]  = devm_ioremap_resource(dev, scu_res);
+       gen->base[RSND_GEN2_ADG]  = devm_ioremap_resource(dev, adg_res);
+       gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res);
+       gen->base[RSND_GEN2_SSI]  = devm_ioremap_resource(dev, ssi_res);
+       if (IS_ERR(gen->base[RSND_GEN2_SCU])  ||
+           IS_ERR(gen->base[RSND_GEN2_ADG])  ||
+           IS_ERR(gen->base[RSND_GEN2_SSIU]) ||
+           IS_ERR(gen->base[RSND_GEN2_SSI]))
+               return -ENODEV;
+
+       ret = rsnd_gen2_regmap_init(priv, gen);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(dev, "Gen2 device probed\n");
+       dev_dbg(dev, "SRU  : %08x => %p\n", scu_res->start,
+               gen->base[RSND_GEN2_SCU]);
+       dev_dbg(dev, "ADG  : %08x => %p\n", adg_res->start,
+               gen->base[RSND_GEN2_ADG]);
+       dev_dbg(dev, "SSIU : %08x => %p\n", ssiu_res->start,
+               gen->base[RSND_GEN2_SSIU]);
+       dev_dbg(dev, "SSI  : %08x => %p\n", ssi_res->start,
+               gen->base[RSND_GEN2_SSI]);
+
+       return 0;
+}
+
+/*
+ *             Gen1
+ */
+
 /* single address mapping */
 #define RSND_GEN1_S_REG(gen, reg, id, offset)  \
        RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
@@ -189,19 +309,23 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
 
 static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
 {
-       int i;
-       struct device *dev = rsnd_priv_to_dev(priv);
-       struct regmap_config regc;
        struct reg_field regf[RSND_REG_MAX] = {
                RSND_GEN1_S_REG(gen, SRU,       SRC_ROUTE_SEL,  0x00),
                RSND_GEN1_S_REG(gen, SRU,       SRC_TMG_SEL0,   0x08),
                RSND_GEN1_S_REG(gen, SRU,       SRC_TMG_SEL1,   0x0c),
                RSND_GEN1_S_REG(gen, SRU,       SRC_TMG_SEL2,   0x10),
-               RSND_GEN1_S_REG(gen, SRU,       SRC_CTRL,       0xc0),
+               RSND_GEN1_S_REG(gen, SRU,       SRC_ROUTE_CTRL, 0xc0),
                RSND_GEN1_S_REG(gen, SRU,       SSI_MODE0,      0xD0),
                RSND_GEN1_S_REG(gen, SRU,       SSI_MODE1,      0xD4),
                RSND_GEN1_M_REG(gen, SRU,       BUSIF_MODE,     0x20,   0x4),
-               RSND_GEN1_M_REG(gen, SRU,       BUSIF_ADINR,    0x214,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_ROUTE_MODE0,0x50,   0x8),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_SWRSR,      0x200,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_SRCIR,      0x204,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_ADINR,      0x214,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_IFSCR,      0x21c,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_IFSVR,      0x220,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_SRCCR,      0x224,  0x40),
+               RSND_GEN1_M_REG(gen, SRU,       SRC_MNFSR,      0x228,  0x40),
 
                RSND_GEN1_S_REG(gen, ADG,       BRRA,           0x00),
                RSND_GEN1_S_REG(gen, ADG,       BRRB,           0x04),
@@ -219,24 +343,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
                RSND_GEN1_M_REG(gen, SSI,       SSIWSR,         0x20,   0x40),
        };
 
-       memset(&regc, 0, sizeof(regc));
-       regc.reg_bits = 32;
-       regc.val_bits = 32;
-
-       gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, &regc);
-       if (IS_ERR(gen->regmap)) {
-               dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
-               return PTR_ERR(gen->regmap);
-       }
-
-       for (i = 0; i < RSND_REG_MAX; i++) {
-               gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
-               if (IS_ERR(gen->regs[i]))
-                       return PTR_ERR(gen->regs[i]);
-
-       }
-
-       return 0;
+       return rsnd_gen_regmap_init(priv, gen, regf);
 }
 
 static int rsnd_gen1_probe(struct platform_device *pdev,
@@ -281,45 +388,16 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
 
 }
 
-static void rsnd_gen1_remove(struct platform_device *pdev,
-                            struct rsnd_priv *priv)
-{
-}
-
-static struct rsnd_gen_ops rsnd_gen1_ops = {
-       .probe          = rsnd_gen1_probe,
-       .remove         = rsnd_gen1_remove,
-       .path_init      = rsnd_gen1_path_init,
-       .path_exit      = rsnd_gen1_path_exit,
-};
-
 /*
  *             Gen
  */
-int rsnd_gen_path_init(struct rsnd_priv *priv,
-                      struct rsnd_dai *rdai,
-                      struct rsnd_dai_stream *io)
-{
-       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
-       return gen->ops->path_init(priv, rdai, io);
-}
-
-int rsnd_gen_path_exit(struct rsnd_priv *priv,
-                      struct rsnd_dai *rdai,
-                      struct rsnd_dai_stream *io)
-{
-       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
-       return gen->ops->path_exit(priv, rdai, io);
-}
-
 int rsnd_gen_probe(struct platform_device *pdev,
                   struct rcar_snd_info *info,
                   struct rsnd_priv *priv)
 {
        struct device *dev = rsnd_priv_to_dev(priv);
        struct rsnd_gen *gen;
+       int ret;
 
        gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
        if (!gen) {
@@ -327,23 +405,21 @@ int rsnd_gen_probe(struct platform_device *pdev,
                return -ENOMEM;
        }
 
+       priv->gen = gen;
+
+       ret = -ENODEV;
        if (rsnd_is_gen1(priv))
-               gen->ops = &rsnd_gen1_ops;
+               ret = rsnd_gen1_probe(pdev, info, priv);
+       else if (rsnd_is_gen2(priv))
+               ret = rsnd_gen2_probe(pdev, info, priv);
 
-       if (!gen->ops) {
+       if (ret < 0)
                dev_err(dev, "unknown generation R-Car sound device\n");
-               return -ENODEV;
-       }
-
-       priv->gen = gen;
 
-       return gen->ops->probe(pdev, info, priv);
+       return ret;
 }
 
 void rsnd_gen_remove(struct platform_device *pdev,
                     struct rsnd_priv *priv)
 {
-       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
-       gen->ops->remove(pdev, priv);
 }
index 9e463e50e7e62b81fabeaeecf39f50de4206eeaf..4ca66cd899c87415e263219c400fea5ce4e51df0 100644 (file)
  * see gen1/gen2 for detail
  */
 enum rsnd_reg {
-       /* SRU/SCU */
-       RSND_REG_SRC_ROUTE_SEL,
-       RSND_REG_SRC_TMG_SEL0,
-       RSND_REG_SRC_TMG_SEL1,
-       RSND_REG_SRC_TMG_SEL2,
-       RSND_REG_SRC_CTRL,
+       /* SRU/SCU/SSIU */
+       RSND_REG_SRC_ROUTE_SEL,         /* for Gen1 */
+       RSND_REG_SRC_TMG_SEL0,          /* for Gen1 */
+       RSND_REG_SRC_TMG_SEL1,          /* for Gen1 */
+       RSND_REG_SRC_TMG_SEL2,          /* for Gen1 */
+       RSND_REG_SRC_ROUTE_CTRL,        /* for Gen1 */
        RSND_REG_SSI_MODE0,
        RSND_REG_SSI_MODE1,
        RSND_REG_BUSIF_MODE,
-       RSND_REG_BUSIF_ADINR,
+       RSND_REG_INT_ENABLE,            /* for Gen2 */
+       RSND_REG_SRC_ROUTE_MODE0,
+       RSND_REG_SRC_SWRSR,
+       RSND_REG_SRC_SRCIR,
+       RSND_REG_SRC_ADINR,
+       RSND_REG_SRC_IFSCR,
+       RSND_REG_SRC_IFSVR,
+       RSND_REG_SRC_SRCCR,
+       RSND_REG_SRC_MNFSR,
 
        /* ADG */
        RSND_REG_BRRA,
@@ -49,9 +57,9 @@ enum rsnd_reg {
        RSND_REG_AUDIO_CLK_SEL0,
        RSND_REG_AUDIO_CLK_SEL1,
        RSND_REG_AUDIO_CLK_SEL2,
-       RSND_REG_AUDIO_CLK_SEL3,
-       RSND_REG_AUDIO_CLK_SEL4,
-       RSND_REG_AUDIO_CLK_SEL5,
+       RSND_REG_AUDIO_CLK_SEL3,        /* for Gen1 */
+       RSND_REG_AUDIO_CLK_SEL4,        /* for Gen1 */
+       RSND_REG_AUDIO_CLK_SEL5,        /* for Gen1 */
 
        /* SSI */
        RSND_REG_SSICR,
@@ -174,11 +182,11 @@ struct rsnd_dai {
        struct rsnd_dai_stream playback;
        struct rsnd_dai_stream capture;
 
-       int clk_master:1;
-       int bit_clk_inv:1;
-       int frm_clk_inv:1;
-       int sys_delay:1;
-       int data_alignment:1;
+       unsigned int clk_master:1;
+       unsigned int bit_clk_inv:1;
+       unsigned int frm_clk_inv:1;
+       unsigned int sys_delay:1;
+       unsigned int data_alignment:1;
 };
 
 #define rsnd_dai_nr(priv) ((priv)->dai_nr)
@@ -229,6 +237,10 @@ int rsnd_adg_probe(struct platform_device *pdev,
                   struct rsnd_priv *priv);
 void rsnd_adg_remove(struct platform_device *pdev,
                   struct rsnd_priv *priv);
+int rsnd_adg_set_convert_clk(struct rsnd_priv *priv,
+                            struct rsnd_mod *mod,
+                            unsigned int src_rate,
+                            unsigned int dst_rate);
 
 /*
  *     R-Car sound priv
@@ -282,6 +294,10 @@ void rsnd_scu_remove(struct platform_device *pdev,
                     struct rsnd_priv *priv);
 struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
 bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod);
+unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv,
+                                  struct rsnd_mod *ssi_mod,
+                                  struct snd_pcm_runtime *runtime);
+
 #define rsnd_scu_nr(priv) ((priv)->scu_nr)
 
 /*
index fa8fa15860b9bda89dc5d3af73c85a5c4f076f15..9bb08bb1d4553ba43cdc135b04c7c1b725a1af68 100644 (file)
 struct rsnd_scu {
        struct rsnd_scu_platform_info *info; /* rcar_snd.h */
        struct rsnd_mod mod;
+       struct clk *clk;
 };
 
 #define rsnd_scu_mode_flags(p) ((p)->info->flags)
+#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate)
+
+#define RSND_SCU_NAME_SIZE 16
 
 /*
  * ADINR
@@ -26,6 +30,15 @@ struct rsnd_scu {
 #define OTBL_18                (6 << 16)
 #define OTBL_16                (8 << 16)
 
+/*
+ *             image of SRC (Sampling Rate Converter)
+ *
+ * 96kHz   <-> +-----+ 48kHz   +-----+  48kHz  +-------+
+ * 48kHz   <-> | SRC | <------>        | SSI | <-----> | codec |
+ * 44.1kHz <-> +-----+         +-----+         +-------+
+ * ...
+ *
+ */
 
 #define rsnd_mod_to_scu(_mod)  \
        container_of((_mod), struct rsnd_scu, mod)
@@ -36,7 +49,8 @@ struct rsnd_scu {
                     ((pos) = (struct rsnd_scu *)(priv)->scu + i);      \
             i++)
 
-static int rsnd_scu_set_route(struct rsnd_priv *priv,
+/* Gen1 only */
+static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv,
                              struct rsnd_mod *mod,
                              struct rsnd_dai *rdai,
                              struct rsnd_dai_stream *io)
@@ -55,7 +69,7 @@ static int rsnd_scu_set_route(struct rsnd_priv *priv,
                { 0x3, 28, }, /* 7 */
                { 0x3, 30, }, /* 8 */
        };
-
+       struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
        u32 mask;
        u32 val;
        int shift;
@@ -85,9 +99,18 @@ static int rsnd_scu_set_route(struct rsnd_priv *priv,
         */
        shift   = (id % 4) * 8;
        mask    = 0x1F << shift;
-       if (8 == id) /* SRU8 is very special */
+
+       /*
+        * ADG is used as source clock if SRC was used,
+        * then, SSI WS is used as destination clock.
+        * SSI WS is used as source clock if SRC is not used
+        * (when playback, source/destination become reverse when capture)
+        */
+       if (rsnd_scu_convert_rate(scu)) /* use ADG */
+               val = 0;
+       else if (8 == id)               /* use SSI WS, but SRU8 is special */
                val = id << shift;
-       else
+       else                            /* use SSI WS */
                val = (id + 1) << shift;
 
        switch (id / 4) {
@@ -105,30 +128,45 @@ static int rsnd_scu_set_route(struct rsnd_priv *priv,
        return 0;
 }
 
-static int rsnd_scu_set_mode(struct rsnd_priv *priv,
-                            struct rsnd_mod *mod,
-                            struct rsnd_dai *rdai,
-                            struct rsnd_dai_stream *io)
+unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv,
+                                  struct rsnd_mod *ssi_mod,
+                                  struct snd_pcm_runtime *runtime)
 {
-       int id = rsnd_mod_id(mod);
-       u32 val;
+       struct rsnd_scu *scu;
+       unsigned int rate;
 
-       if (rsnd_is_gen1(priv)) {
-               val = (1 << id);
-               rsnd_mod_bset(mod, SRC_CTRL, val, val);
-       }
+       /* this function is assuming SSI id = SCU id here */
+       scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod)));
 
-       return 0;
+       /*
+        * return convert rate if SRC is used,
+        * otherwise, return runtime->rate as usual
+        */
+       rate = rsnd_scu_convert_rate(scu);
+       if (!rate)
+               rate = runtime->rate;
+
+       return rate;
 }
 
-static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
+static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv,
                              struct rsnd_mod *mod,
                              struct rsnd_dai *rdai,
                              struct rsnd_dai_stream *io)
 {
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+       struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
+       u32 convert_rate = rsnd_scu_convert_rate(scu);
        u32 adinr = runtime->channels;
 
+       /* set/clear soft reset */
+       rsnd_mod_write(mod, SRC_SWRSR, 0);
+       rsnd_mod_write(mod, SRC_SWRSR, 1);
+
+       /* Initialize the operation of the SRC internal circuits */
+       rsnd_mod_write(mod, SRC_SRCIR, 1);
+
+       /* Set channel number and output bit length */
        switch (runtime->sample_bits) {
        case 16:
                adinr |= OTBL_16;
@@ -139,9 +177,81 @@ static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
        default:
                return -EIO;
        }
+       rsnd_mod_write(mod, SRC_ADINR, adinr);
+
+       if (convert_rate) {
+               u32 fsrate = 0x0400000 / convert_rate * runtime->rate;
+               int ret;
+
+               /* Enable the initial value of IFS */
+               rsnd_mod_write(mod, SRC_IFSCR, 1);
+
+               /* Set initial value of IFS */
+               rsnd_mod_write(mod, SRC_IFSVR, fsrate);
+
+               /* Select SRC mode (fixed value) */
+               rsnd_mod_write(mod, SRC_SRCCR, 0x00010110);
+
+               /* Set the restriction value of the FS ratio (98%) */
+               rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98);
+
+               if (rsnd_is_gen1(priv)) {
+                       /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */
+               }
 
+               /* set convert clock */
+               ret = rsnd_adg_set_convert_clk(priv, mod,
+                                              runtime->rate,
+                                              convert_rate);
+               if (ret < 0)
+                       return ret;
+       }
+
+       /* Cancel the initialization and operate the SRC function */
+       rsnd_mod_write(mod, SRC_SRCIR, 0);
+
+       /* use DMA transfer */
        rsnd_mod_write(mod, BUSIF_MODE, 1);
-       rsnd_mod_write(mod, BUSIF_ADINR, adinr);
+
+       return 0;
+}
+
+static int rsnd_scu_transfer_start(struct rsnd_priv *priv,
+                                  struct rsnd_mod *mod,
+                                  struct rsnd_dai *rdai,
+                                  struct rsnd_dai_stream *io)
+{
+       struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
+       int id = rsnd_mod_id(mod);
+       u32 val;
+
+       if (rsnd_is_gen1(priv)) {
+               val = (1 << id);
+               rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val);
+       }
+
+       if (rsnd_scu_convert_rate(scu))
+               rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1);
+
+       return 0;
+}
+
+static int rsnd_scu_transfer_stop(struct rsnd_priv *priv,
+                                 struct rsnd_mod *mod,
+                                 struct rsnd_dai *rdai,
+                                 struct rsnd_dai_stream *io)
+{
+       struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
+       int id = rsnd_mod_id(mod);
+       u32 mask;
+
+       if (rsnd_is_gen1(priv)) {
+               mask = (1 << id);
+               rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0);
+       }
+
+       if (rsnd_scu_convert_rate(scu))
+               rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0);
 
        return 0;
 }
@@ -159,6 +269,7 @@ static int rsnd_scu_start(struct rsnd_mod *mod,
                          struct rsnd_dai_stream *io)
 {
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+       struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
        struct device *dev = rsnd_priv_to_dev(priv);
        int ret;
 
@@ -173,16 +284,19 @@ static int rsnd_scu_start(struct rsnd_mod *mod,
                return 0;
        }
 
+       clk_enable(scu->clk);
+
        /* it use DMA transter */
-       ret = rsnd_scu_set_route(priv, mod, rdai, io);
+
+       ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io);
        if (ret < 0)
                return ret;
 
-       ret = rsnd_scu_set_mode(priv, mod, rdai, io);
+       ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io);
        if (ret < 0)
                return ret;
 
-       ret = rsnd_scu_set_hpbif(priv, mod, rdai, io);
+       ret = rsnd_scu_transfer_start(priv, mod, rdai, io);
        if (ret < 0)
                return ret;
 
@@ -191,9 +305,27 @@ static int rsnd_scu_start(struct rsnd_mod *mod,
        return 0;
 }
 
+static int rsnd_scu_stop(struct rsnd_mod *mod,
+                         struct rsnd_dai *rdai,
+                         struct rsnd_dai_stream *io)
+{
+       struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+       struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
+
+       if (!rsnd_scu_hpbif_is_enable(mod))
+               return 0;
+
+       rsnd_scu_transfer_stop(priv, mod, rdai, io);
+
+       clk_disable(scu->clk);
+
+       return 0;
+}
+
 static struct rsnd_mod_ops rsnd_scu_ops = {
        .name   = "scu",
        .start  = rsnd_scu_start,
+       .stop   = rsnd_scu_stop,
 };
 
 struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id)
@@ -210,6 +342,8 @@ int rsnd_scu_probe(struct platform_device *pdev,
 {
        struct device *dev = rsnd_priv_to_dev(priv);
        struct rsnd_scu *scu;
+       struct clk *clk;
+       char name[RSND_SCU_NAME_SIZE];
        int i, nr;
 
        /*
@@ -226,9 +360,16 @@ int rsnd_scu_probe(struct platform_device *pdev,
        priv->scu       = scu;
 
        for_each_rsnd_scu(scu, priv, i) {
+               snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i);
+
+               clk = devm_clk_get(dev, name);
+               if (IS_ERR(clk))
+                       return PTR_ERR(clk);
+
                rsnd_mod_init(priv, &scu->mod,
                              &rsnd_scu_ops, i);
                scu->info = &info->scu_info[i];
+               scu->clk = clk;
 
                dev_dbg(dev, "SCU%d probed\n", i);
        }
index 5ac20cd5e00607efd0b8113fc85aec9ed97f57f4..4b8cf7ca9d19fb016b971cf9f0f1ddeb74fbb954 100644 (file)
@@ -187,9 +187,10 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
 }
 
 static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
-                                    unsigned int rate)
+                                    struct rsnd_dai_stream *io)
 {
        struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod);
+       struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
        struct device *dev = rsnd_priv_to_dev(priv);
        int i, j, ret;
        int adg_clk_div_table[] = {
@@ -199,6 +200,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
                1, 2, 4, 8, 16, 6, 12,
        };
        unsigned int main_rate;
+       unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime);
 
        /*
         * Find best clock, and try to start ADG
@@ -209,7 +211,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
                        /*
                         * this driver is assuming that
                         * system word is 64fs (= 2 x 32bit)
-                        * see rsnd_ssi_start()
+                        * see rsnd_ssi_init()
                         */
                        main_rate = rate / adg_clk_div_table[i]
                                * 32 * 2 * ssi_clk_mul_table[j];
@@ -251,14 +253,10 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
                clk_enable(ssi->clk);
 
                if (rsnd_rdai_is_clk_master(rdai)) {
-                       struct snd_pcm_runtime *runtime;
-
-                       runtime = rsnd_io_to_runtime(io);
-
                        if (rsnd_ssi_clk_from_parent(ssi))
                                rsnd_ssi_hw_start(ssi->parent, rdai, io);
                        else
-                               rsnd_ssi_master_clk_start(ssi, runtime->rate);
+                               rsnd_ssi_master_clk_start(ssi, io);
                }
        }
 
@@ -457,6 +455,10 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
        /* enable PIO IRQ */
        ssi->cr_etc = UIEN | OIEN | DIEN;
 
+       /* enable PIO interrupt if gen2 */
+       if (rsnd_is_gen2(priv))
+               rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000);
+
        rsnd_ssi_hw_start(ssi, rdai, io);
 
        dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
@@ -650,7 +652,7 @@ int rsnd_ssi_probe(struct platform_device *pdev,
 
                snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i);
 
-               clk = clk_get(dev, name);
+               clk = devm_clk_get(dev, name);
                if (IS_ERR(clk))
                        return PTR_ERR(clk);
 
@@ -711,7 +713,6 @@ void rsnd_ssi_remove(struct platform_device *pdev,
        int i;
 
        for_each_rsnd_ssi(ssi, priv, i) {
-               clk_put(ssi->clk);
                if (rsnd_ssi_dma_available(ssi))
                        rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod));
        }
index 4e53d87e881d0891a3d8437881d12d41225303cc..fe1df50805a3035ea455d40771c55d4cb4f6585d 100644 (file)
@@ -1728,6 +1728,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        }
 
        snd_soc_dapm_link_dai_widgets(card);
+       snd_soc_dapm_connect_dai_link_widgets(card);
 
        if (card->controls)
                snd_soc_add_card_controls(card, card->controls, card->num_controls);
@@ -3212,11 +3213,11 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
                        break;
                case 2:
                        ((u16 *)(&ucontrol->value.bytes.data))[0]
-                               &= ~params->mask;
+                               &= cpu_to_be16(~params->mask);
                        break;
                case 4:
                        ((u32 *)(&ucontrol->value.bytes.data))[0]
-                               &= ~params->mask;
+                               &= cpu_to_be32(~params->mask);
                        break;
                default:
                        return -EINVAL;
@@ -3484,7 +3485,7 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0,
                                                      freq, dir);
        else
-               return -EINVAL;
+               return -ENOTSUPP;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
 
@@ -3505,7 +3506,7 @@ int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
                return codec->driver->set_sysclk(codec, clk_id, source,
                                                 freq, dir);
        else
-               return -EINVAL;
+               return -ENOTSUPP;
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk);
 
@@ -4617,10 +4618,14 @@ int snd_soc_of_get_dai_name(struct device_node *of_node,
 
                        if (id < 0 || id >= pos->num_dai) {
                                ret = -EINVAL;
-                       } else {
-                               *dai_name = pos->dai_drv[id].name;
-                               ret = 0;
+                               break;
                        }
+
+                       ret = 0;
+
+                       *dai_name = pos->dai_drv[id].name;
+                       if (!*dai_name)
+                               *dai_name = pos->name;
                }
 
                break;
index dcade130157f3433d88ddbf7db7c311c43ea8042..2a44fe9122a2bf5ab0a4a0f6fc91b0c3cc510ff2 100644 (file)
@@ -371,12 +371,16 @@ static void dapm_reset(struct snd_soc_card *card)
        }
 }
 
-static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
+static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg,
+       unsigned int *value)
 {
-       if (w->codec)
-               return snd_soc_read(w->codec, reg);
-       else if (w->platform)
-               return snd_soc_platform_read(w->platform, reg);
+       if (w->codec) {
+               *value = snd_soc_read(w->codec, reg);
+               return 0;
+       } else if (w->platform) {
+               *value = snd_soc_platform_read(w->platform, reg);
+               return 0;
+       }
 
        dev_err(w->dapm->dev, "ASoC: no valid widget read method\n");
        return -1;
@@ -430,13 +434,12 @@ static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
                        return ret;
        } else {
                soc_widget_lock(w);
-               ret = soc_widget_read(w, reg);
+               ret = soc_widget_read(w, reg, &old);
                if (ret < 0) {
                        soc_widget_unlock(w);
                        return ret;
                }
 
-               old = ret;
                new = (old & ~mask) | (value & mask);
                change = old != new;
                if (change) {
@@ -513,7 +516,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
                unsigned int invert = mc->invert;
 
                if (reg != SND_SOC_NOPM) {
-                       val = soc_widget_read(w, reg);
+                       soc_widget_read(w, reg, &val);
                        val = (val >> shift) & mask;
                        if (invert)
                                val = max - val;
@@ -529,7 +532,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
                        w->kcontrol_news[i].private_value;
                int val, item;
 
-               val = soc_widget_read(w, e->reg);
+               soc_widget_read(w, e->reg, &val);
                item = (val >> e->shift_l) & e->mask;
 
                if (item < e->max && !strcmp(p->name, e->texts[item]))
@@ -558,7 +561,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
                        w->kcontrol_news[i].private_value;
                int val, item;
 
-               val = soc_widget_read(w, e->reg);
+               soc_widget_read(w, e->reg, &val);
                val = (val >> e->shift_l) & e->mask;
                for (item = 0; item < e->max; item++) {
                        if (val == e->values[item])
@@ -2782,7 +2785,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
 
                /* Read the initial power state from the device */
                if (w->reg >= 0) {
-                       val = soc_widget_read(w, w->reg) >> w->shift;
+                       soc_widget_read(w, w->reg, &val);
+                       val = val >> w->shift;
                        val &= w->mask;
                        if (val == w->on_val)
                                w->power = 1;
@@ -2868,6 +2872,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
        unsigned int val;
        int connect, change;
        struct snd_soc_dapm_update update;
+       int ret = 0;
 
        if (snd_soc_volsw_is_stereo(mc))
                dev_warn(codec->dapm.dev,
@@ -2901,12 +2906,16 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
                        card->update = &update;
                }
 
-               soc_dapm_mixer_update_power(card, kcontrol, connect);
+               ret = soc_dapm_mixer_update_power(card, kcontrol, connect);
 
                card->update = NULL;
        }
 
        mutex_unlock(&card->dapm_mutex);
+
+       if (ret > 0)
+               soc_dpcm_runtime_update(card);
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -2955,6 +2964,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
        unsigned int val, mux, change;
        unsigned int mask;
        struct snd_soc_dapm_update update;
+       int ret = 0;
 
        if (ucontrol->value.enumerated.item[0] > e->max - 1)
                return -EINVAL;
@@ -2978,12 +2988,16 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
                update.val = val;
                card->update = &update;
 
-               soc_dapm_mux_update_power(card, kcontrol, mux, e);
+               ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
 
                card->update = NULL;
        }
 
        mutex_unlock(&card->dapm_mutex);
+
+       if (ret > 0)
+               soc_dpcm_runtime_update(card);
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -3019,6 +3033,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
        struct soc_enum *e =
                (struct soc_enum *)kcontrol->private_value;
        int change;
+       int ret = 0;
 
        if (ucontrol->value.enumerated.item[0] >= e->max)
                return -EINVAL;
@@ -3028,9 +3043,13 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
        value = ucontrol->value.enumerated.item[0];
        change = dapm_kcontrol_set_value(kcontrol, value);
        if (change)
-               soc_dapm_mux_update_power(card, kcontrol, value, e);
+               ret = soc_dapm_mux_update_power(card, kcontrol, value, e);
 
        mutex_unlock(&card->dapm_mutex);
+
+       if (ret > 0)
+               soc_dpcm_runtime_update(card);
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
@@ -3097,6 +3116,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
        unsigned int val, mux, change;
        unsigned int mask;
        struct snd_soc_dapm_update update;
+       int ret = 0;
 
        if (ucontrol->value.enumerated.item[0] > e->max - 1)
                return -EINVAL;
@@ -3120,12 +3140,16 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
                update.val = val;
                card->update = &update;
 
-               soc_dapm_mux_update_power(card, kcontrol, mux, e);
+               ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
 
                card->update = NULL;
        }
 
        mutex_unlock(&card->dapm_mutex);
+
+       if (ret > 0)
+               soc_dpcm_runtime_update(card);
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
@@ -3614,6 +3638,55 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
        return 0;
 }
 
+void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
+{
+       struct snd_soc_pcm_runtime *rtd = card->rtd;
+       struct snd_soc_dai *cpu_dai, *codec_dai;
+       struct snd_soc_dapm_route r;
+       int i;
+
+       memset(&r, 0, sizeof(r));
+
+       /* for each BE DAI link... */
+       for (i = 0; i < card->num_rtd; i++) {
+               rtd = &card->rtd[i];
+               cpu_dai = rtd->cpu_dai;
+               codec_dai = rtd->codec_dai;
+
+               /* dynamic FE links have no fixed DAI mapping */
+               if (rtd->dai_link->dynamic)
+                       continue;
+
+               /* there is no point in connecting BE DAI links with dummies */
+               if (snd_soc_dai_is_dummy(codec_dai) ||
+                       snd_soc_dai_is_dummy(cpu_dai))
+                       continue;
+
+               /* connect BE DAI playback if widgets are valid */
+               if (codec_dai->playback_widget && cpu_dai->playback_widget) {
+                       r.source = cpu_dai->playback_widget->name;
+                       r.sink = codec_dai->playback_widget->name;
+                       dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
+                               cpu_dai->codec->name, r.source,
+                               codec_dai->platform->name, r.sink);
+
+                       snd_soc_dapm_add_route(&card->dapm, &r);
+               }
+
+               /* connect BE DAI capture if widgets are valid */
+               if (codec_dai->capture_widget && cpu_dai->capture_widget) {
+                       r.source = codec_dai->capture_widget->name;
+                       r.sink = cpu_dai->capture_widget->name;
+                       dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
+                               codec_dai->codec->name, r.source,
+                               cpu_dai->platform->name, r.sink);
+
+                       snd_soc_dapm_add_route(&card->dapm, &r);
+               }
+
+       }
+}
+
 static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
        int event)
 {
index 999861942d28d4712d2e62657d0778fba3baf30b..7ac745df1412689c6adf0bf246399870b79e44e7 100644 (file)
@@ -67,7 +67,7 @@ static void devm_card_release(struct device *dev, void *res)
  */
 int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
 {
-       struct device **ptr;
+       struct snd_soc_card **ptr;
        int ret;
 
        ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
@@ -76,7 +76,7 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
 
        ret = snd_soc_register_card(card);
        if (ret == 0) {
-               *ptr = dev;
+               *ptr = card;
                devres_add(dev, ptr);
        } else {
                devres_free(ptr);
index 87e86357124eb0001666343d6c8ef3ff03d72ee7..560a7787d8a761735fc51e45dc290f14934ac0bb 100644 (file)
@@ -144,6 +144,8 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
        if (ret == 0) {
                if (dma_caps.cmd_pause)
                        hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
+               if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
+                       hw.info |= SNDRV_PCM_INFO_BATCH;
        }
 
        return snd_soc_set_runtime_hwparams(substream, &hw);
@@ -187,6 +189,21 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
                                                 dma_data->filter_data);
 }
 
+static bool dmaengine_pcm_can_report_residue(struct dma_chan *chan)
+{
+       struct dma_slave_caps dma_caps;
+       int ret;
+
+       ret = dma_get_slave_caps(chan, &dma_caps);
+       if (ret != 0)
+               return true;
+
+       if (dma_caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR)
+               return false;
+
+       return true;
+}
+
 static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
@@ -239,6 +256,16 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
                                max_buffer_size);
                if (ret)
                        goto err_free;
+
+               /*
+                * This will only return false if we know for sure that at least
+                * one channel does not support residue reporting. If the DMA
+                * driver does not implement the slave_caps API we rely having
+                * the NO_RESIDUE flag set manually in case residue reporting is
+                * not supported.
+                */
+               if (!dmaengine_pcm_can_report_residue(pcm->chan[i]))
+                       pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE;
        }
 
        return 0;
@@ -248,6 +275,18 @@ err_free:
        return ret;
 }
 
+static snd_pcm_uframes_t dmaengine_pcm_pointer(
+       struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+
+       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
+               return snd_dmaengine_pcm_pointer_no_residue(substream);
+       else
+               return snd_dmaengine_pcm_pointer(substream);
+}
+
 static const struct snd_pcm_ops dmaengine_pcm_ops = {
        .open           = dmaengine_pcm_open,
        .close          = snd_dmaengine_pcm_close,
@@ -255,7 +294,7 @@ static const struct snd_pcm_ops dmaengine_pcm_ops = {
        .hw_params      = dmaengine_pcm_hw_params,
        .hw_free        = snd_pcm_lib_free_pages,
        .trigger        = snd_dmaengine_pcm_trigger,
-       .pointer        = snd_dmaengine_pcm_pointer,
+       .pointer        = dmaengine_pcm_pointer,
 };
 
 static const struct snd_soc_platform_driver dmaengine_pcm_platform = {
@@ -265,46 +304,72 @@ static const struct snd_soc_platform_driver dmaengine_pcm_platform = {
        .probe_order    = SND_SOC_COMP_ORDER_LATE,
 };
 
-static const struct snd_pcm_ops dmaengine_no_residue_pcm_ops = {
-       .open           = dmaengine_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
-       .hw_params      = dmaengine_pcm_hw_params,
-       .hw_free        = snd_pcm_lib_free_pages,
-       .trigger        = snd_dmaengine_pcm_trigger,
-       .pointer        = snd_dmaengine_pcm_pointer_no_residue,
-};
-
-static const struct snd_soc_platform_driver dmaengine_no_residue_pcm_platform = {
-       .ops            = &dmaengine_no_residue_pcm_ops,
-       .pcm_new        = dmaengine_pcm_new,
-       .pcm_free       = dmaengine_pcm_free,
-       .probe_order    = SND_SOC_COMP_ORDER_LATE,
-};
-
 static const char * const dmaengine_pcm_dma_channel_names[] = {
        [SNDRV_PCM_STREAM_PLAYBACK] = "tx",
        [SNDRV_PCM_STREAM_CAPTURE] = "rx",
 };
 
-static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
-       struct device *dev)
+static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
+       struct device *dev, const struct snd_dmaengine_pcm_config *config)
 {
        unsigned int i;
+       const char *name;
+       struct dma_chan *chan;
 
        if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
                           SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
            !dev->of_node)
-               return;
+               return 0;
+
+       if (config && config->dma_dev) {
+               /*
+                * If this warning is seen, it probably means that your Linux
+                * device structure does not match your HW device structure.
+                * It would be best to refactor the Linux device structure to
+                * correctly match the HW structure.
+                */
+               dev_warn(dev, "DMA channels sourced from device %s",
+                        dev_name(config->dma_dev));
+               dev = config->dma_dev;
+       }
 
-       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
-               pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx");
-               pcm->chan[1] = pcm->chan[0];
-       } else {
-               for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-                       pcm->chan[i] = dma_request_slave_channel(dev,
-                                       dmaengine_pcm_dma_channel_names[i]);
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       name = "rx-tx";
+               else
+                       name = dmaengine_pcm_dma_channel_names[i];
+               if (config && config->chan_names[i])
+                       name = config->chan_names[i];
+               chan = dma_request_slave_channel_reason(dev, name);
+               if (IS_ERR(chan)) {
+                       if (PTR_ERR(chan) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+                       pcm->chan[i] = NULL;
+               } else {
+                       pcm->chan[i] = chan;
                }
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
+       }
+
+       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+               pcm->chan[1] = pcm->chan[0];
+
+       return 0;
+}
+
+static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
+{
+       unsigned int i;
+
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (!pcm->chan[i])
+                       continue;
+               dma_release_channel(pcm->chan[i]);
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
        }
 }
 
@@ -318,6 +383,7 @@ int snd_dmaengine_pcm_register(struct device *dev,
        const struct snd_dmaengine_pcm_config *config, unsigned int flags)
 {
        struct dmaengine_pcm *pcm;
+       int ret;
 
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
        if (!pcm)
@@ -326,14 +392,21 @@ int snd_dmaengine_pcm_register(struct device *dev,
        pcm->config = config;
        pcm->flags = flags;
 
-       dmaengine_pcm_request_chan_of(pcm, dev);
+       ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
+       if (ret)
+               goto err_free_dma;
 
-       if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
-               return snd_soc_add_platform(dev, &pcm->platform,
-                               &dmaengine_no_residue_pcm_platform);
-       else
-               return snd_soc_add_platform(dev, &pcm->platform,
-                               &dmaengine_pcm_platform);
+       ret = snd_soc_add_platform(dev, &pcm->platform,
+               &dmaengine_pcm_platform);
+       if (ret)
+               goto err_free_dma;
+
+       return 0;
+
+err_free_dma:
+       dmaengine_pcm_release_chan(pcm);
+       kfree(pcm);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
 
@@ -348,7 +421,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 {
        struct snd_soc_platform *platform;
        struct dmaengine_pcm *pcm;
-       unsigned int i;
 
        platform = snd_soc_lookup_platform(dev);
        if (!platform)
@@ -356,15 +428,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 
        pcm = soc_platform_to_pcm(platform);
 
-       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-               if (pcm->chan[i]) {
-                       dma_release_channel(pcm->chan[i]);
-                       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
-                               break;
-               }
-       }
-
        snd_soc_remove_platform(platform);
+       dmaengine_pcm_release_chan(pcm);
        kfree(pcm);
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
index 4f11d23f20621971b8806e70618ee8e4e1c3846f..aa886cca3ecf94a8ecf2c360312cd3dc3bcb4184 100644 (file)
@@ -99,14 +99,14 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
        config.val_bits = data_bits;
 
        switch (control) {
-#if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE)
+#if IS_ENABLED(CONFIG_REGMAP_I2C)
        case SND_SOC_I2C:
                codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
                                                      &config);
                break;
 #endif
 
-#if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE)
+#if IS_ENABLED(CONFIG_REGMAP_SPI)
        case SND_SOC_SPI:
                codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
                                                      &config);
index 42782c01e41320e924efb4b93c839802f0df5722..5932971cf54de4e2d53643d4df125dd656df2ecd 100644 (file)
@@ -84,35 +84,117 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        int ret;
 
-       if (!soc_dai->driver->symmetric_rates &&
-           !rtd->dai_link->symmetric_rates)
-               return 0;
+       if (soc_dai->rate && (soc_dai->driver->symmetric_rates ||
+                               rtd->dai_link->symmetric_rates)) {
+               dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n",
+                               soc_dai->rate);
+
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_RATE,
+                                               soc_dai->rate, soc_dai->rate);
+               if (ret < 0) {
+                       dev_err(soc_dai->dev,
+                               "ASoC: Unable to apply rate constraint: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
 
-       /* This can happen if multiple streams are starting simultaneously -
-        * the second can need to get its constraints before the first has
-        * picked a rate.  Complain and allow the application to carry on.
-        */
-       if (!soc_dai->rate) {
-               dev_warn(soc_dai->dev,
-                        "ASoC: Not enforcing symmetric_rates due to race\n");
-               return 0;
+       if (soc_dai->channels && (soc_dai->driver->symmetric_channels ||
+                               rtd->dai_link->symmetric_channels)) {
+               dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n",
+                               soc_dai->channels);
+
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_CHANNELS,
+                                               soc_dai->channels,
+                                               soc_dai->channels);
+               if (ret < 0) {
+                       dev_err(soc_dai->dev,
+                               "ASoC: Unable to apply channel symmetry constraint: %d\n",
+                               ret);
+                       return ret;
+               }
        }
 
-       dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate);
+       if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits ||
+                               rtd->dai_link->symmetric_samplebits)) {
+               dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n",
+                               soc_dai->sample_bits);
 
-       ret = snd_pcm_hw_constraint_minmax(substream->runtime,
-                                          SNDRV_PCM_HW_PARAM_RATE,
-                                          soc_dai->rate, soc_dai->rate);
-       if (ret < 0) {
-               dev_err(soc_dai->dev,
-                       "ASoC: Unable to apply rate symmetry constraint: %d\n",
-                       ret);
-               return ret;
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+                                               soc_dai->sample_bits,
+                                               soc_dai->sample_bits);
+               if (ret < 0) {
+                       dev_err(soc_dai->dev,
+                               "ASoC: Unable to apply sample bits symmetry constraint: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       unsigned int rate, channels, sample_bits, symmetry;
+
+       rate = params_rate(params);
+       channels = params_channels(params);
+       sample_bits = snd_pcm_format_physical_width(params_format(params));
+
+       /* reject unmatched parameters when applying symmetry */
+       symmetry = cpu_dai->driver->symmetric_rates ||
+               codec_dai->driver->symmetric_rates ||
+               rtd->dai_link->symmetric_rates;
+       if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) {
+               dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
+                               cpu_dai->rate, rate);
+               return -EINVAL;
+       }
+
+       symmetry = cpu_dai->driver->symmetric_channels ||
+               codec_dai->driver->symmetric_channels ||
+               rtd->dai_link->symmetric_channels;
+       if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) {
+               dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
+                               cpu_dai->channels, channels);
+               return -EINVAL;
+       }
+
+       symmetry = cpu_dai->driver->symmetric_samplebits ||
+               codec_dai->driver->symmetric_samplebits ||
+               rtd->dai_link->symmetric_samplebits;
+       if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) {
+               dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
+                               cpu_dai->sample_bits, sample_bits);
+               return -EINVAL;
        }
 
        return 0;
 }
 
+static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver;
+       struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver;
+       struct snd_soc_dai_link *link = rtd->dai_link;
+
+       return cpu_driver->symmetric_rates || codec_driver->symmetric_rates ||
+               link->symmetric_rates || cpu_driver->symmetric_channels ||
+               codec_driver->symmetric_channels || link->symmetric_channels ||
+               cpu_driver->symmetric_samplebits ||
+               codec_driver->symmetric_samplebits ||
+               link->symmetric_samplebits;
+}
+
 /*
  * List of sample sizes that might go over the bus for parameter
  * application.  There ought to be a wildcard sample size for things
@@ -148,24 +230,32 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
        }
 }
 
-static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
+static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
        struct snd_soc_pcm_stream *codec_stream,
        struct snd_soc_pcm_stream *cpu_stream)
 {
-       hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
-       hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max);
+       struct snd_pcm_hardware *hw = &runtime->hw;
+
        hw->channels_min = max(codec_stream->channels_min,
                cpu_stream->channels_min);
        hw->channels_max = min(codec_stream->channels_max,
                cpu_stream->channels_max);
-       hw->formats = codec_stream->formats & cpu_stream->formats;
-       hw->rates = codec_stream->rates & cpu_stream->rates;
-       if (codec_stream->rates
-               & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-               hw->rates |= cpu_stream->rates;
-       if (cpu_stream->rates
-               & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-               hw->rates |= codec_stream->rates;
+       if (hw->formats)
+               hw->formats &= codec_stream->formats & cpu_stream->formats;
+       else
+               hw->formats = codec_stream->formats & cpu_stream->formats;
+       hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates,
+               cpu_stream->rates);
+
+       hw->rate_min = 0;
+       hw->rate_max = UINT_MAX;
+
+       snd_pcm_limit_hw_rates(runtime);
+
+       hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
+       hw->rate_min = max(hw->rate_min, codec_stream->rate_min);
+       hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
+       hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max);
 }
 
 /*
@@ -235,15 +325,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 
        /* Check that the codec and cpu DAIs are compatible */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback,
+               soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback,
                        &cpu_dai_drv->playback);
        } else {
-               soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture,
+               soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture,
                        &cpu_dai_drv->capture);
        }
 
+       if (soc_pcm_has_symmetry(substream))
+               runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
+
        ret = -EINVAL;
-       snd_pcm_limit_hw_rates(runtime);
        if (!runtime->hw.rates) {
                printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
                        codec_dai->name, cpu_dai->name);
@@ -390,11 +482,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        if (!codec_dai->active)
                codec_dai->rate = 0;
 
-       /* Muting the DAC suppresses artifacts caused during digital
-        * shutdown, for example from stopping clocks.
-        */
-       snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
-
        if (cpu_dai->driver->ops->shutdown)
                cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 
@@ -525,6 +612,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
+       ret = soc_pcm_params_symmetry(substream, params);
+       if (ret)
+               goto out;
+
        if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
                ret = rtd->dai_link->ops->hw_params(substream, params);
                if (ret < 0) {
@@ -561,9 +652,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       /* store the rate for each DAIs */
+       /* store the parameters for each DAIs */
        cpu_dai->rate = params_rate(params);
+       cpu_dai->channels = params_channels(params);
+       cpu_dai->sample_bits =
+               snd_pcm_format_physical_width(params_format(params));
+
        codec_dai->rate = params_rate(params);
+       codec_dai->channels = params_channels(params);
+       codec_dai->sample_bits =
+               snd_pcm_format_physical_width(params_format(params));
 
 out:
        mutex_unlock(&rtd->pcm_mutex);
@@ -594,12 +692,26 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_codec *codec = rtd->codec;
+       bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
+       /* clear the corresponding DAIs parameters when going to be inactive */
+       if (cpu_dai->active == 1) {
+               cpu_dai->rate = 0;
+               cpu_dai->channels = 0;
+               cpu_dai->sample_bits = 0;
+       }
+
+       if (codec_dai->active == 1) {
+               codec_dai->rate = 0;
+               codec_dai->channels = 0;
+               codec_dai->sample_bits = 0;
+       }
+
        /* apply codec digital mute */
-       if (!codec->active)
+       if ((playback && codec_dai->playback_active == 1) ||
+           (!playback && codec_dai->capture_active == 1))
                snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
 
        /* free any machine hw params */
@@ -665,7 +777,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
                        return ret;
        }
 
-       if (platform->driver->ops && platform->driver->bespoke_trigger) {
+       if (platform->driver->bespoke_trigger) {
                ret = platform->driver->bespoke_trigger(substream, cmd);
                if (ret < 0)
                        return ret;
@@ -1124,6 +1236,20 @@ unwind:
        return err;
 }
 
+static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
+       struct snd_soc_pcm_stream *stream)
+{
+       runtime->hw.rate_min = stream->rate_min;
+       runtime->hw.rate_max = stream->rate_max;
+       runtime->hw.channels_min = stream->channels_min;
+       runtime->hw.channels_max = stream->channels_max;
+       if (runtime->hw.formats)
+               runtime->hw.formats &= stream->formats;
+       else
+               runtime->hw.formats = stream->formats;
+       runtime->hw.rates = stream->rates;
+}
+
 static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1131,21 +1257,10 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
-               runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
-               runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
-               runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
-               runtime->hw.formats &= cpu_dai_drv->playback.formats;
-               runtime->hw.rates = cpu_dai_drv->playback.rates;
-       } else {
-               runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
-               runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
-               runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
-               runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
-               runtime->hw.formats &= cpu_dai_drv->capture.formats;
-               runtime->hw.rates = cpu_dai_drv->capture.rates;
-       }
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback);
+       else
+               dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture);
 }
 
 static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
@@ -2026,10 +2141,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
        int ret = 0, playback = 0, capture = 0;
 
        if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
-               if (cpu_dai->driver->playback.channels_min)
-                       playback = 1;
-               if (cpu_dai->driver->capture.channels_min)
-                       capture = 1;
+               playback = rtd->dai_link->dpcm_playback;
+               capture = rtd->dai_link->dpcm_capture;
        } else {
                if (codec_dai->driver->playback.channels_min &&
                    cpu_dai->driver->playback.channels_min)
index 5e633659c1b38154ebd1a75aa0e4f005b4f089a0..7f22ca35a4131af0ae4d58fadd9e5fe8909decf5 100644 (file)
@@ -59,10 +59,6 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
 EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
 
 static const struct snd_pcm_hardware dummy_dma_hardware = {
-       .formats                = 0xffffffff,
-       .channels_min           = 1,
-       .channels_max           = UINT_MAX,
-
        /* Random values to keep userspace happy when checking constraints */
        .info                   = SNDRV_PCM_INFO_INTERLEAVED |
                                  SNDRV_PCM_INFO_BLOCK_TRANSFER,
@@ -123,6 +119,13 @@ static struct snd_soc_dai_driver dummy_dai = {
         },
 };
 
+int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
+{
+       if (dai->driver == &dummy_dai)
+               return 1;
+       return 0;
+}
+
 static int snd_soc_dummy_probe(struct platform_device *pdev)
 {
        int ret;
index 21a8c954af1cd6dfedd65100cc331d54145f4746..4ab442a63d7ed55c411f1729995bd12efdce88db 100644 (file)
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <sound/dmaengine_pcm.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/spear_dma.h>
 #include <sound/spear_spdif.h>
 #include "spdif_in_regs.h"
+#include "spear_pcm.h"
 
 struct spdif_in_params {
        u32 format;
@@ -37,6 +39,8 @@ struct spdif_in_dev {
        struct device *dev;
        void (*reset_perip)(void);
        int irq;
+       struct snd_dmaengine_dai_dma_data dma_params_rx;
+       struct snd_dmaengine_pcm_config config;
 };
 
 static void spdif_in_configure(struct spdif_in_dev *host)
@@ -53,7 +57,8 @@ static int spdif_in_dai_probe(struct snd_soc_dai *dai)
 {
        struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
 
-       dai->capture_dma_data = &host->dma_params;
+       host->dma_params_rx.filter_data = &host->dma_params;
+       dai->capture_dma_data = &host->dma_params_rx;
 
        return 0;
 }
@@ -244,7 +249,6 @@ static int spdif_in_probe(struct platform_device *pdev)
        host->dma_params.addr = res_fifo->start;
        host->dma_params.max_burst = 16;
        host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       host->dma_params.filter = pdata->filter;
        host->reset_perip = pdata->reset_perip;
 
        host->dev = &pdev->dev;
@@ -257,8 +261,13 @@ static int spdif_in_probe(struct platform_device *pdev)
                return ret;
        }
 
-       return devm_snd_soc_register_component(&pdev->dev, &spdif_in_component,
-                                              &spdif_in_dai, 1);
+       ret = devm_snd_soc_register_component(&pdev->dev, &spdif_in_component,
+                                             &spdif_in_dai, 1);
+       if (ret)
+               return ret;
+
+       return devm_spear_pcm_platform_register(&pdev->dev, &host->config,
+                                               pdata->filter);
 }
 
 static struct platform_driver spdif_in_driver = {
index b6ef6f78dc781ad8a45c18d594b1cdc4945647f1..fe99f461aff0bfd97337f663ba2f13eecd626bbb 100644 (file)
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <sound/dmaengine_pcm.h>
 #include <sound/soc.h>
 #include <sound/spear_dma.h>
 #include <sound/spear_spdif.h>
 #include "spdif_out_regs.h"
+#include "spear_pcm.h"
 
 struct spdif_out_params {
        u32 rate;
@@ -35,6 +37,8 @@ struct spdif_out_dev {
        struct spdif_out_params saved_params;
        u32 running;
        void __iomem *io_base;
+       struct snd_dmaengine_dai_dma_data dma_params_tx;
+       struct snd_dmaengine_pcm_config config;
 };
 
 static void spdif_out_configure(struct spdif_out_dev *host)
@@ -244,7 +248,8 @@ static int spdif_soc_dai_probe(struct snd_soc_dai *dai)
 {
        struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
 
-       dai->playback_dma_data = &host->dma_params;
+       host->dma_params_tx.filter_data = &host->dma_params;
+       dai->playback_dma_data = &host->dma_params_tx;
 
        return snd_soc_add_dai_controls(dai, spdif_out_controls,
                                ARRAY_SIZE(spdif_out_controls));
@@ -280,6 +285,7 @@ static int spdif_out_probe(struct platform_device *pdev)
        struct spdif_out_dev *host;
        struct spear_spdif_platform_data *pdata;
        struct resource *res;
+       int ret;
 
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
        if (!host) {
@@ -302,12 +308,16 @@ static int spdif_out_probe(struct platform_device *pdev)
        host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA;
        host->dma_params.max_burst = 16;
        host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       host->dma_params.filter = pdata->filter;
 
        dev_set_drvdata(&pdev->dev, host);
 
-       return devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
-                                              &spdif_out_dai, 1);
+       ret = devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
+                                             &spdif_out_dai, 1);
+       if (ret)
+               return ret;
+
+       return devm_spear_pcm_platform_register(&pdev->dev, &host->config,
+                                               pdata->filter);
 }
 
 #ifdef CONFIG_PM
index 4707f2b862c3762502d622d1d799944ee0e401fc..0e5a8f35d0ad22da7925445a5d074fefb5478ab1 100644 (file)
@@ -18,6 +18,7 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/spear_dma.h>
+#include "spear_pcm.h"
 
 static const struct snd_pcm_hardware spear_pcm_hardware = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -31,49 +32,24 @@ static const struct snd_pcm_hardware spear_pcm_hardware = {
        .fifo_size = 0, /* fifo size in bytes */
 };
 
-static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
-       struct snd_pcm_substream *substream)
-{
-       struct spear_dma_data *dma_data;
-
-       dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-       return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data);
-}
-
 static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = {
        .pcm_hardware = &spear_pcm_hardware,
-       .compat_request_channel = spear_pcm_request_chan,
        .prealloc_buffer_size = 16 * 1024,
 };
 
-static int spear_soc_platform_probe(struct platform_device *pdev)
+int devm_spear_pcm_platform_register(struct device *dev,
+                       struct snd_dmaengine_pcm_config *config,
+                       bool (*filter)(struct dma_chan *chan, void *slave))
 {
-       return snd_dmaengine_pcm_register(&pdev->dev,
-               &spear_dmaengine_pcm_config,
+       *config = spear_dmaengine_pcm_config;
+       config->compat_filter_fn = filter;
+
+       return snd_dmaengine_pcm_register(dev, config,
                SND_DMAENGINE_PCM_FLAG_NO_DT |
                SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
-
-static int spear_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_dmaengine_pcm_unregister(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver spear_pcm_driver = {
-       .driver = {
-               .name = "spear-pcm-audio",
-               .owner = THIS_MODULE,
-       },
-
-       .probe = spear_soc_platform_probe,
-       .remove = spear_soc_platform_remove,
-};
-
-module_platform_driver(spear_pcm_driver);
+EXPORT_SYMBOL_GPL(devm_spear_pcm_platform_register);
 
 MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
 MODULE_DESCRIPTION("SPEAr PCM DMA module");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:spear-pcm-audio");
diff --git a/sound/soc/spear/spear_pcm.h b/sound/soc/spear/spear_pcm.h
new file mode 100644 (file)
index 0000000..9b0ca62
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SPEAR_PCM_H__
+#define __SPEAR_PCM_H__
+
+int devm_spear_pcm_platform_register(struct device *dev,
+                       struct snd_dmaengine_pcm_config *config,
+                       bool (*filter)(struct dma_chan *chan, void *slave));
+
+#endif
index 8fc653ca3ab40b3ef04d1a58723a2466086ab8ff..65a85f542521563627be1fe02b4c22c6bfdea194 100644 (file)
@@ -116,3 +116,13 @@ config SND_SOC_TEGRA_ALC5632
        help
          Say Y or M here if you want to add support for SoC audio on the
          Toshiba AC100 netbook.
+
+config SND_SOC_TEGRA_MAX98090
+       tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
+       depends on SND_SOC_TEGRA && I2C && GPIOLIB
+       select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
+       select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
+       select SND_SOC_MAX98090
+       help
+         Say Y or M here if you want to add support for SoC audio on Tegra
+         boards using the MAX98090 codec, such as Venice2.
index 21d2550a08a4fc1e15e41f4c66cc0a84a290396f..5ae588cd96c4c39ff8060f98a6f1248f9e4855d9 100644 (file)
@@ -24,6 +24,7 @@ snd-soc-tegra-wm8903-objs := tegra_wm8903.o
 snd-soc-tegra-wm9712-objs := tegra_wm9712.o
 snd-soc-tegra-trimslice-objs := trimslice.o
 snd-soc-tegra-alc5632-objs := tegra_alc5632.o
+snd-soc-tegra-max98090-objs := tegra_max98090.o
 
 obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
 obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
@@ -31,3 +32,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
 obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
 obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
 obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
+obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o
index ae27bcd586d25428458c305c16448395b9f74d88..088518d7694ae95d09ebf795d1dc7cdd33fc9a64 100644 (file)
@@ -404,7 +404,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
        ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops);
        if (ret) {
                dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret);
-               goto err_asoc_utils_fini;
+               goto err_clk_disable_unprepare;
        }
 
        ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component,
@@ -412,7 +412,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
                ret = -ENOMEM;
-               goto err_asoc_utils_fini;
+               goto err_clk_disable_unprepare;
        }
 
        ret = tegra_pcm_platform_register(&pdev->dev);
@@ -428,6 +428,8 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
 
 err_unregister_component:
        snd_soc_unregister_component(&pdev->dev);
+err_clk_disable_unprepare:
+       clk_disable_unprepare(ac97->clk_ac97);
 err_asoc_utils_fini:
        tegra_asoc_utils_fini(&ac97->util_data);
 err_clk_put:
index 364bf6a907e1c39a36df89ded1d6b2681172940f..8c819f8114708f7a94e33929a04ebecbdf3e2ffc 100644 (file)
@@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index 08bc6931c7c7fc0477703037098a8e7185d7c69d..8c7c1028e5797dbc9b23ec88b58a4cd840db1c5c 100644 (file)
@@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
        int ret, spdifclock;
 
-       mask = TEGRA20_SPDIF_CTRL_PACK |
-              TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+       mask |= TEGRA20_SPDIF_CTRL_PACK |
+               TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
-               val = TEGRA20_SPDIF_CTRL_PACK |
-                     TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+               val |= TEGRA20_SPDIF_CTRL_PACK |
+                      TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
                break;
        default:
                return -EINVAL;
index 231a785b3921a5bd95d87914a92e7f5f2d266a63..02247fee1cf7e1450fb4bbcdf2e58cf5ee76c7e8 100644 (file)
@@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c
new file mode 100644 (file)
index 0000000..0283cfb
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Tegra machine ASoC driver for boards using a MAX90809 CODEC.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (C) 2010-2012 - NVIDIA, Inc.
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+ * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_asoc_utils.h"
+
+#define DRV_NAME "tegra-snd-max98090"
+
+struct tegra_max98090 {
+       struct tegra_asoc_utils_data util_data;
+       int gpio_hp_det;
+};
+
+static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct snd_soc_card *card = codec->card;
+       struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card);
+       int srate, mclk;
+       int err;
+
+       srate = params_rate(params);
+       switch (srate) {
+       case 8000:
+       case 16000:
+       case 24000:
+       case 32000:
+       case 48000:
+       case 64000:
+       case 96000:
+               mclk = 12288000;
+               break;
+       case 11025:
+       case 22050:
+       case 44100:
+       case 88200:
+               mclk = 11289600;
+               break;
+       default:
+               mclk = 12000000;
+               break;
+       }
+
+       err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+       if (err < 0) {
+               dev_err(card->dev, "Can't configure clocks\n");
+               return err;
+       }
+
+       err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+                                       SND_SOC_CLOCK_IN);
+       if (err < 0) {
+               dev_err(card->dev, "codec_dai clock not set\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_ops tegra_max98090_ops = {
+       .hw_params = tegra_max98090_asoc_hw_params,
+};
+
+static struct snd_soc_jack tegra_max98090_hp_jack;
+
+static struct snd_soc_jack_pin tegra_max98090_hp_jack_pins[] = {
+       {
+               .pin = "Headphones",
+               .mask = SND_JACK_HEADPHONE,
+       },
+};
+
+static struct snd_soc_jack_gpio tegra_max98090_hp_jack_gpio = {
+       .name = "Headphone detection",
+       .report = SND_JACK_HEADPHONE,
+       .debounce_time = 150,
+       .invert = 1,
+};
+
+static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphones", NULL),
+       SND_SOC_DAPM_SPK("Speakers", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_kcontrol_new tegra_max98090_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Speakers"),
+};
+
+static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card);
+
+       if (gpio_is_valid(machine->gpio_hp_det)) {
+               snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
+                               &tegra_max98090_hp_jack);
+               snd_soc_jack_add_pins(&tegra_max98090_hp_jack,
+                               ARRAY_SIZE(tegra_max98090_hp_jack_pins),
+                               tegra_max98090_hp_jack_pins);
+
+               tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det;
+               snd_soc_jack_add_gpios(&tegra_max98090_hp_jack,
+                                       1,
+                                       &tegra_max98090_hp_jack_gpio);
+       }
+
+       return 0;
+}
+
+static struct snd_soc_dai_link tegra_max98090_dai = {
+       .name = "max98090",
+       .stream_name = "max98090 PCM",
+       .codec_dai_name = "HiFi",
+       .init = tegra_max98090_asoc_init,
+       .ops = &tegra_max98090_ops,
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card snd_soc_tegra_max98090 = {
+       .name = "tegra-max98090",
+       .owner = THIS_MODULE,
+       .dai_link = &tegra_max98090_dai,
+       .num_links = 1,
+       .controls = tegra_max98090_controls,
+       .num_controls = ARRAY_SIZE(tegra_max98090_controls),
+       .dapm_widgets = tegra_max98090_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(tegra_max98090_dapm_widgets),
+       .fully_routed = true,
+};
+
+static int tegra_max98090_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct snd_soc_card *card = &snd_soc_tegra_max98090;
+       struct tegra_max98090 *machine;
+       int ret;
+
+       machine = devm_kzalloc(&pdev->dev,
+                       sizeof(struct tegra_max98090), GFP_KERNEL);
+       if (!machine) {
+               dev_err(&pdev->dev, "Can't allocate tegra_max98090\n");
+               return -ENOMEM;
+       }
+
+       card->dev = &pdev->dev;
+       platform_set_drvdata(pdev, card);
+       snd_soc_card_set_drvdata(card, machine);
+
+       machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+       if (machine->gpio_hp_det == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+
+       ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+       if (ret)
+               goto err;
+
+       ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+       if (ret)
+               goto err;
+
+       tegra_max98090_dai.codec_of_node = of_parse_phandle(np,
+                       "nvidia,audio-codec", 0);
+       if (!tegra_max98090_dai.codec_of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'nvidia,audio-codec' missing or invalid\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       tegra_max98090_dai.cpu_of_node = of_parse_phandle(np,
+                       "nvidia,i2s-controller", 0);
+       if (!tegra_max98090_dai.cpu_of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'nvidia,i2s-controller' missing or invalid\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       tegra_max98090_dai.platform_of_node = tegra_max98090_dai.cpu_of_node;
+
+       ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
+       if (ret)
+               goto err;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+                       ret);
+               goto err_fini_utils;
+       }
+
+       return 0;
+
+err_fini_utils:
+       tegra_asoc_utils_fini(&machine->util_data);
+err:
+       return ret;
+}
+
+static int tegra_max98090_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card);
+
+       snd_soc_jack_free_gpios(&tegra_max98090_hp_jack, 1,
+                               &tegra_max98090_hp_jack_gpio);
+
+       snd_soc_unregister_card(card);
+
+       tegra_asoc_utils_fini(&machine->util_data);
+
+       return 0;
+}
+
+static const struct of_device_id tegra_max98090_of_match[] = {
+       { .compatible = "nvidia,tegra-audio-max98090", },
+       {},
+};
+
+static struct platform_driver tegra_max98090_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+               .of_match_table = tegra_max98090_of_match,
+       },
+       .probe = tegra_max98090_probe,
+       .remove = tegra_max98090_remove,
+};
+module_platform_driver(tegra_max98090_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra max98090 machine ASoC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_max98090_of_match);
index 7b2d23ba69b3bf397ba3fb963feb2d3d2b5948af..c09ffd18791b9de9b13713dc068ee5cb4d75e42d 100644 (file)
@@ -42,9 +42,6 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
        .info                   = SNDRV_PCM_INFO_MMAP |
                                  SNDRV_PCM_INFO_MMAP_VALID |
                                  SNDRV_PCM_INFO_INTERLEAVED,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
-       .channels_min           = 2,
-       .channels_max           = 2,
        .period_bytes_min       = 1024,
        .period_bytes_max       = PAGE_SIZE,
        .periods_min            = 2,
index 5e119630b0e03fa677b49302e517499f8cb1df5f..45b57892b6a53564e60434262b56fb0ae16b91df 100644 (file)
@@ -55,7 +55,6 @@ static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link tegra_wm9712_dai = {
        .name = "AC97 HiFi",
        .stream_name = "AC97 HiFi",
-       .cpu_dai_name = "tegra20-ac97",
        .codec_dai_name = "wm9712-hifi",
        .codec_name = "wm9712-codec",
        .init = tegra_wm9712_init,
index fbd077f4de729e24da0049e96924e6d27dababba..f0829de28708b20724fffddf831bec56818152d1 100644 (file)
@@ -40,11 +40,6 @@ static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
        .info             = SNDRV_PCM_INFO_INTERLEAVED |
                            SNDRV_PCM_INFO_BATCH |
                            SNDRV_PCM_INFO_PAUSE,
-#ifdef __BIG_ENDIAN
-       .formats          = SNDRV_PCM_FMTBIT_S16_BE,
-#else
-       .formats          = SNDRV_PCM_FMTBIT_S16_LE,
-#endif
        .period_bytes_min = 1024,
        .period_bytes_max = 8 * 1024,
        .periods_min      = 2,
index 178d1bad62591565589803f52c859a2062044df2..b3b66aa98dce7d8b3f6844eb9f65a7d59a728cd8 100644 (file)
@@ -91,6 +91,8 @@ static int mop500_of_probe(struct platform_device *pdev,
        for (i = 0; i < 2; i++) {
                mop500_dai_links[i].cpu_of_node = msp_np[i];
                mop500_dai_links[i].cpu_dai_name = NULL;
+               mop500_dai_links[i].platform_of_node = msp_np[i];
+               mop500_dai_links[i].platform_name = NULL;
                mop500_dai_links[i].codec_of_node = codec_np;
                mop500_dai_links[i].codec_name = NULL;
        }
index c6fb5cce980e365f4fa84a02fa2b4254a9887e66..5f4807b2c0072b00b29619fb4d224e475ddfab3f 100644 (file)
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/of.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/asoc-ux500-msp.h>
 
 #include <sound/soc.h>
 #include <sound/soc-dai.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "ux500_msp_i2s.h"
 #include "ux500_msp_dai.h"
@@ -654,16 +656,52 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int ux500_msp_dai_of_probe(struct snd_soc_dai *dai)
+{
+       struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+       struct snd_dmaengine_dai_dma_data *playback_dma_data;
+       struct snd_dmaengine_dai_dma_data *capture_dma_data;
+
+       playback_dma_data = devm_kzalloc(dai->dev,
+                                        sizeof(*playback_dma_data),
+                                        GFP_KERNEL);
+       if (!playback_dma_data)
+               return -ENOMEM;
+
+       capture_dma_data = devm_kzalloc(dai->dev,
+                                       sizeof(*capture_dma_data),
+                                       GFP_KERNEL);
+       if (!capture_dma_data)
+               return -ENOMEM;
+
+       playback_dma_data->addr = drvdata->msp->playback_dma_data.tx_rx_addr;
+       capture_dma_data->addr = drvdata->msp->capture_dma_data.tx_rx_addr;
+
+       playback_dma_data->maxburst = 4;
+       capture_dma_data->maxburst = 4;
+
+       snd_soc_dai_init_dma_data(dai, playback_dma_data, capture_dma_data);
+
+       return 0;
+}
+
 static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
 {
        struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
+       struct msp_i2s_platform_data *pdata = dai->dev->platform_data;
+       int ret;
 
-       dai->playback_dma_data = &drvdata->msp->playback_dma_data;
-       dai->capture_dma_data = &drvdata->msp->capture_dma_data;
+       if (!pdata) {
+               ret = ux500_msp_dai_of_probe(dai);
+               return ret;
+       }
 
        drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
        drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
 
+       snd_soc_dai_init_dma_data(dai,
+                                 &drvdata->msp->playback_dma_data,
+                                 &drvdata->msp->capture_dma_data);
        return 0;
 }
 
@@ -680,87 +718,19 @@ static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
        }
 };
 
-static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
-       {
-               .name = "ux500-msp-i2s.0",
-               .probe = ux500_msp_dai_probe,
-               .id = 0,
-               .suspend = NULL,
-               .resume = NULL,
-               .playback = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .capture = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .ops = ux500_msp_dai_ops,
-       },
-       {
-               .name = "ux500-msp-i2s.1",
-               .probe = ux500_msp_dai_probe,
-               .id = 1,
-               .suspend = NULL,
-               .resume = NULL,
-               .playback = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .capture = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .ops = ux500_msp_dai_ops,
-       },
-       {
-               .name = "ux500-msp-i2s.2",
-               .id = 2,
-               .probe = ux500_msp_dai_probe,
-               .suspend = NULL,
-               .resume = NULL,
-               .playback = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .capture = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .ops = ux500_msp_dai_ops,
-       },
-       {
-               .name = "ux500-msp-i2s.3",
-               .probe = ux500_msp_dai_probe,
-               .id = 3,
-               .suspend = NULL,
-               .resume = NULL,
-               .playback = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .capture = {
-                       .channels_min = UX500_MSP_MIN_CHANNELS,
-                       .channels_max = UX500_MSP_MAX_CHANNELS,
-                       .rates = UX500_I2S_RATES,
-                       .formats = UX500_I2S_FORMATS,
-               },
-               .ops = ux500_msp_dai_ops,
-       },
+static struct snd_soc_dai_driver ux500_msp_dai_drv = {
+       .probe                 = ux500_msp_dai_probe,
+       .suspend               = NULL,
+       .resume                = NULL,
+       .playback.channels_min = UX500_MSP_MIN_CHANNELS,
+       .playback.channels_max = UX500_MSP_MAX_CHANNELS,
+       .playback.rates        = UX500_I2S_RATES,
+       .playback.formats      = UX500_I2S_FORMATS,
+       .capture.channels_min  = UX500_MSP_MIN_CHANNELS,
+       .capture.channels_max  = UX500_MSP_MAX_CHANNELS,
+       .capture.rates         = UX500_I2S_RATES,
+       .capture.formats       = UX500_I2S_FORMATS,
+       .ops                   = ux500_msp_dai_ops,
 };
 
 static const struct snd_soc_component_driver ux500_msp_component = {
@@ -771,10 +741,14 @@ static const struct snd_soc_component_driver ux500_msp_component = {
 static int ux500_msp_drv_probe(struct platform_device *pdev)
 {
        struct ux500_msp_i2s_drvdata *drvdata;
+       struct msp_i2s_platform_data *pdata = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
        int ret = 0;
 
-       dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__,
-               pdev->name);
+       if (!pdata && !np) {
+               dev_err(&pdev->dev, "No platform data or Device Tree found\n");
+               return -ENODEV;
+       }
 
        drvdata = devm_kzalloc(&pdev->dev,
                                sizeof(struct ux500_msp_i2s_drvdata),
@@ -826,7 +800,7 @@ static int ux500_msp_drv_probe(struct platform_device *pdev)
        dev_set_drvdata(&pdev->dev, drvdata);
 
        ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component,
-                                        &ux500_msp_dai_drv[drvdata->msp->id], 1);
+                                        &ux500_msp_dai_drv, 1);
        if (ret < 0) {
                dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
                        __func__, drvdata->msp->id);
index 1ca8b08ae993d34a100b22032315b9c94ce9ec03..959d7b4edf56a94d167d09ea07ca7a597a64bbce 100644 (file)
@@ -646,6 +646,34 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
 
 }
 
+static int ux500_msp_i2s_of_init_msp(struct platform_device *pdev,
+                               struct ux500_msp *msp,
+                               struct msp_i2s_platform_data **platform_data)
+{
+       struct msp_i2s_platform_data *pdata;
+
+       *platform_data = devm_kzalloc(&pdev->dev,
+                                    sizeof(struct msp_i2s_platform_data),
+                                    GFP_KERNEL);
+       pdata = *platform_data;
+       if (!pdata)
+               return -ENOMEM;
+
+       msp->playback_dma_data.dma_cfg = devm_kzalloc(&pdev->dev,
+                                       sizeof(struct stedma40_chan_cfg),
+                                       GFP_KERNEL);
+       if (!msp->playback_dma_data.dma_cfg)
+               return -ENOMEM;
+
+       msp->capture_dma_data.dma_cfg = devm_kzalloc(&pdev->dev,
+                                       sizeof(struct stedma40_chan_cfg),
+                                       GFP_KERNEL);
+       if (!msp->capture_dma_data.dma_cfg)
+               return -ENOMEM;
+
+       return 0;
+}
+
 int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                        struct ux500_msp **msp_p,
                        struct msp_i2s_platform_data *platform_data)
@@ -653,30 +681,28 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
        struct resource *res = NULL;
        struct device_node *np = pdev->dev.of_node;
        struct ux500_msp *msp;
+       int ret;
 
        *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL);
        msp = *msp_p;
        if (!msp)
                return -ENOMEM;
 
-       if (np) {
-               if (!platform_data) {
-                       platform_data = devm_kzalloc(&pdev->dev,
-                               sizeof(struct msp_i2s_platform_data), GFP_KERNEL);
-                       if (!platform_data)
-                               return -ENOMEM;
-               }
-       } else
-               if (!platform_data)
+       if (!platform_data) {
+               if (np) {
+                       ret = ux500_msp_i2s_of_init_msp(pdev, msp,
+                                                       &platform_data);
+                       if (ret)
+                               return ret;
+               } else
                        return -EINVAL;
+       } else {
+               msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx;
+               msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx;
+               msp->id = platform_data->id;
+       }
 
-       dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
-               pdev->name, platform_data->id);
-
-       msp->id = platform_data->id;
        msp->dev = &pdev->dev;
-       msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx;
-       msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
index 258d0bcee0bd540aed67c757742f1a0f698f3a5f..875de0f68b8567dd3ec1d89213fbe849775ec563 100644 (file)
@@ -475,7 +475,7 @@ struct ux500_msp_dma_params {
 };
 
 struct ux500_msp {
-       enum msp_i2s_id id;
+       int id;
        void __iomem *registers;
        struct device *dev;
        struct ux500_msp_dma_params playback_dma_data;
index ce554de5d9dc5a131aa52e9f3d9c1da87b8ddb8c..51a66a87305ae0ad96b26206108f13bcec5a189f 100644 (file)
 #include "ux500_msp_i2s.h"
 #include "ux500_pcm.h"
 
-#define UX500_PLATFORM_MIN_RATE 8000
-#define UX500_PLATFORM_MAX_RATE 48000
-
-#define UX500_PLATFORM_MIN_CHANNELS 1
-#define UX500_PLATFORM_MAX_CHANNELS 8
-
 #define UX500_PLATFORM_PERIODS_BYTES_MIN       128
 #define UX500_PLATFORM_PERIODS_BYTES_MAX       (64 * PAGE_SIZE)
 #define UX500_PLATFORM_PERIODS_MIN             2
@@ -45,15 +39,6 @@ static const struct snd_pcm_hardware ux500_pcm_hw = {
                SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_RESUME |
                SNDRV_PCM_INFO_PAUSE,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE |
-               SNDRV_PCM_FMTBIT_U16_LE |
-               SNDRV_PCM_FMTBIT_S16_BE |
-               SNDRV_PCM_FMTBIT_U16_BE,
-       .rates = SNDRV_PCM_RATE_KNOT,
-       .rate_min = UX500_PLATFORM_MIN_RATE,
-       .rate_max = UX500_PLATFORM_MAX_RATE,
-       .channels_min = UX500_PLATFORM_MIN_CHANNELS,
-       .channels_max = UX500_PLATFORM_MAX_CHANNELS,
        .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
        .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN,
        .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX,
@@ -65,14 +50,10 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
        struct snd_pcm_substream *substream)
 {
        struct snd_soc_dai *dai = rtd->cpu_dai;
-       struct device *dev = dai->dev;
        u16 per_data_width, mem_data_width;
        struct stedma40_chan_cfg *dma_cfg;
        struct ux500_msp_dma_params *dma_params;
 
-       dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
-               snd_pcm_stream_str(substream));
-
        dma_params = snd_soc_dai_get_dma_data(dai, substream);
        dma_cfg = dma_params->dma_cfg;
 
@@ -108,26 +89,36 @@ static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
                struct dma_slave_config *slave_config)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct ux500_msp_dma_params *dma_params;
-       struct stedma40_chan_cfg *dma_cfg;
+       struct msp_i2s_platform_data *pdata = rtd->cpu_dai->dev->platform_data;
+       struct snd_dmaengine_dai_dma_data *snd_dma_params;
+       struct ux500_msp_dma_params *ste_dma_params;
+       dma_addr_t dma_addr;
        int ret;
 
-       dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       dma_cfg = dma_params->dma_cfg;
+       if (pdata) {
+               ste_dma_params =
+                       snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+               dma_addr = ste_dma_params->tx_rx_addr;
+       } else {
+               snd_dma_params =
+                       snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+               dma_addr = snd_dma_params->addr;
+       }
 
        ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
        if (ret)
                return ret;
 
        slave_config->dst_maxburst = 4;
-       slave_config->dst_addr_width = dma_cfg->dst_info.data_width;
        slave_config->src_maxburst = 4;
-       slave_config->src_addr_width = dma_cfg->src_info.data_width;
+
+       slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+       slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               slave_config->dst_addr = dma_params->tx_rx_addr;
+               slave_config->dst_addr = dma_addr;
        else
-               slave_config->src_addr = dma_params->tx_rx_addr;
+               slave_config->src_addr = dma_addr;
 
        return 0;
 }
@@ -139,15 +130,25 @@ static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = {
        .prepare_slave_config = ux500_pcm_prepare_slave_config,
 };
 
+static const struct snd_dmaengine_pcm_config ux500_dmaengine_of_pcm_config = {
+       .compat_request_channel = ux500_pcm_request_chan,
+       .prepare_slave_config = ux500_pcm_prepare_slave_config,
+};
+
 int ux500_pcm_register_platform(struct platform_device *pdev)
 {
+       const struct snd_dmaengine_pcm_config *pcm_config;
+       struct device_node *np = pdev->dev.of_node;
        int ret;
 
-       ret = snd_dmaengine_pcm_register(&pdev->dev,
-                       &ux500_dmaengine_pcm_config,
-                       SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
-                       SND_DMAENGINE_PCM_FLAG_COMPAT |
-                       SND_DMAENGINE_PCM_FLAG_NO_DT);
+       if (np)
+               pcm_config = &ux500_dmaengine_of_pcm_config;
+       else
+               pcm_config = &ux500_dmaengine_pcm_config;
+
+       ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config,
+                                        SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
+                                        SND_DMAENGINE_PCM_FLAG_COMPAT);
        if (ret < 0) {
                dev_err(&pdev->dev,
                        "%s: ERROR: Failed to register platform '%s' (%d)!\n",
index 8e3d9a6c7a3ba6e88f6cd29d0894a6c5a69162d7..25c38afaee4900463692c93b4182db82f93b36bd 100644 (file)
@@ -174,7 +174,7 @@ static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
                dac_rate_new = 8 * (ssc_rate / ssc_div);
 
                status = clk_round_rate(chip->board->dac_clk, dac_rate_new);
-               if (status < 0)
+               if (status <= 0)
                        return status;
 
                /* Ignore difference smaller than 256 Hz. */
index b9ba0fcc45df10d4151bb39f8a5d6284dc8ec23e..83aabea259d7113d82d94d870bd04ebffd64b633 100644 (file)
@@ -636,8 +636,22 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
        if (usb_pipein(ep->pipe) ||
                        snd_usb_endpoint_implicit_feedback_sink(ep)) {
 
+               urb_packs = packs_per_ms;
+               /*
+                * Wireless devices can poll at a max rate of once per 4ms.
+                * For dataintervals less than 5, increase the packet count to
+                * allow the host controller to use bursting to fill in the
+                * gaps.
+                */
+               if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) {
+                       int interval = ep->datainterval;
+                       while (interval < 5) {
+                               urb_packs <<= 1;
+                               ++interval;
+                       }
+               }
                /* make capture URBs <= 1 ms and smaller than a period */
-               urb_packs = min(max_packs_per_urb, packs_per_ms);
+               urb_packs = min(max_packs_per_urb, urb_packs);
                while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
                        urb_packs >>= 1;
                ep->nurbs = MAX_URBS;
index 3525231c6b97325dcbb400ae0c7f9e021555ad8b..d244fd3703d8382c85989b6934611e418600c728 100644 (file)
@@ -189,8 +189,10 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
                             chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&
                            fp->altsetting == 5 && fp->maxpacksize == 392)
                                rate = 96000;
-                       /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
-                       if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068))
+                       /* Creative VF0420/VF0470 Live Cams report 16 kHz instead of 8kHz */
+                       if (rate == 16000 &&
+                           (chip->usb_id == USB_ID(0x041e, 0x4064) ||
+                            chip->usb_id == USB_ID(0x041e, 0x4068)))
                                rate = 8000;
 
                        fp->rate_table[fp->nr_rates] = rate;
index c21a3df9a0df1ef6900a468ee7af36ad7b57ab19..2c44139b404188607fc47e863aa9b33419ae5fcc 100644 (file)
@@ -110,7 +110,7 @@ static const struct snd_pcm_hardware pcm_hw = {
 #define HIFACE_RATE_96000  0x4a
 #define HIFACE_RATE_176400 0x40
 #define HIFACE_RATE_192000 0x48
-#define HIFACE_RATE_352000 0x58
+#define HIFACE_RATE_352800 0x58
 #define HIFACE_RATE_384000 0x68
 
 static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate)
@@ -141,8 +141,8 @@ static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate)
        case 192000:
                rate_value = HIFACE_RATE_192000;
                break;
-       case 352000:
-               rate_value = HIFACE_RATE_352000;
+       case 352800:
+               rate_value = HIFACE_RATE_352800;
                break;
        case 384000:
                rate_value = HIFACE_RATE_384000;
index cc2dd1f0decb8816197623321f3fe55ad8d15467..32af6b741ef5a8aff8581f90b0c5d583d151a6ee 100644 (file)
@@ -322,6 +322,12 @@ static struct usbmix_name_map hercules_usb51_map[] = {
        { 0 }                           /* terminator */
 };
 
+/* Plantronics Gamecom 780 has a broken volume control, better to disable it */
+static struct usbmix_name_map gamecom780_map[] = {
+       { 9, NULL }, /* FU, speaker out */
+       {}
+};
+
 /*
  * Control map entries
  */
@@ -358,6 +364,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x046d, 0x09a4),
                .ignore_ctl_error = 1,
        },
+       {       /* Plantronics GameCom 780 */
+               .id = USB_ID(0x047f, 0xc010),
+               .map = gamecom780_map,
+       },
        {
                /* Hercules DJ Console (Windows Edition) */
                .id = USB_ID(0x06f8, 0xb000),
index 3454262358b398913779954846ab12c11e7c5973..f4b12c216f1cd55c2db4396746a5abc9f20ed302 100644 (file)
@@ -1603,7 +1603,7 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
                        return err;
        }
 
-       return err;
+       return 0;
 }
 
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
index f5f0595ef9c7a36bfef2d5c48c425a61e9dd796d..f652b10ce90582c2a2b72d8d11c74309ae2f0d3e 100644 (file)
        }
 },
 
-/* Creative/Toshiba Multimedia Center SB-0500 */
+/* Creative/E-Mu devices */
 {
-       USB_DEVICE(0x041e, 0x3048),
+       USB_DEVICE(0x041e, 0x3010),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .vendor_name = "Toshiba",
-               .product_name = "SB-0500",
+               .vendor_name = "Creative Labs",
+               .product_name = "Sound Blaster MP3+",
                .ifnum = QUIRK_NO_INTERFACE
        }
 },
-
-/* Creative/E-Mu devices */
+/* Creative/Toshiba Multimedia Center SB-0500 */
 {
-       USB_DEVICE(0x041e, 0x3010),
+       USB_DEVICE(0x041e, 0x3048),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .vendor_name = "Creative Labs",
-               .product_name = "Sound Blaster MP3+",
+               .vendor_name = "Toshiba",
+               .product_name = "SB-0500",
                .ifnum = QUIRK_NO_INTERFACE
        }
 },
@@ -2520,6 +2519,46 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .type = QUIRK_MIDI_RAW_BYTES
        }
 },
+{
+       USB_DEVICE(0x1235, 0x0010),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Focusrite",
+               .product_name = "Saffire 6 USB",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 4,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000,
+                                       .rate_min = 44100,
+                                       .rate_max = 48000,
+                                       .nr_rates = 2,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000
+                                       }
+                               }
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_MIDI_RAW_BYTES
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        USB_DEVICE(0x1235, 0x0018),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -2569,6 +2608,57 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .type = QUIRK_MIDI_NOVATION
        }
 },
+{
+       /*
+        * Focusrite Scarlett 18i6
+        *
+        * Avoid mixer creation, which otherwise fails because some of
+        * the interface descriptor subtypes for interface 0 are
+        * unknown.  That should be fixed or worked-around but this at
+        * least allows the device to be used successfully with a DAW
+        * and an external mixer.  See comments below about other
+        * ignored interfaces.
+        */
+       USB_DEVICE(0x1235, 0x8004),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Focusrite",
+               .product_name = "Scarlett 18i6",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = & (const struct snd_usb_audio_quirk[]) {
+                       {
+                               /* InterfaceSubClass 1 (Control Device) */
+                               .ifnum = 0,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               /* InterfaceSubClass 1 (Control Device) */
+                               .ifnum = 3,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = 4,
+                               .type = QUIRK_MIDI_STANDARD_INTERFACE
+                       },
+                       {
+                               /* InterfaceSubClass 1 (Device Firmware Update) */
+                               .ifnum = 5,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Access Music devices */
 {
@@ -2671,7 +2761,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
-       USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
+       USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
                       USB_DEVICE_ID_MATCH_INT_CLASS |
                       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2679,13 +2769,13 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
        .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
                .vendor_name = "Hauppauge",
-               .product_name = "HVR-850",
+               .product_name = "HVR-950Q",
                .ifnum = QUIRK_ANY_INTERFACE,
                .type = QUIRK_AUDIO_ALIGN_TRANSFER,
        }
 },
 {
-       USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
+       USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
                       USB_DEVICE_ID_MATCH_INT_CLASS |
                       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2699,7 +2789,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
-       USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
+       USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
                       USB_DEVICE_ID_MATCH_INT_CLASS |
                       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2713,7 +2803,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
-       USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
+       USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
                       USB_DEVICE_ID_MATCH_INT_CLASS |
                       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2727,7 +2817,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
-       USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
+       USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
                       USB_DEVICE_ID_MATCH_INT_CLASS |
                       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2741,7 +2831,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
-       USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
+       USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
        .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
                       USB_DEVICE_ID_MATCH_INT_CLASS |
                       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2749,7 +2839,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
        .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
                .vendor_name = "Hauppauge",
-               .product_name = "HVR-950Q",
+               .product_name = "HVR-850",
                .ifnum = QUIRK_ANY_INTERFACE,
                .type = QUIRK_AUDIO_ALIGN_TRANSFER,
        }
@@ -3052,58 +3142,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
-{
-       /*
-        * Focusrite Scarlett 18i6
-        *
-        * Avoid mixer creation, which otherwise fails because some of
-        * the interface descriptor subtypes for interface 0 are
-        * unknown.  That should be fixed or worked-around but this at
-        * least allows the device to be used successfully with a DAW
-        * and an external mixer.  See comments below about other
-        * ignored interfaces.
-        */
-       USB_DEVICE(0x1235, 0x8004),
-       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .vendor_name = "Focusrite",
-               .product_name = "Scarlett 18i6",
-               .ifnum = QUIRK_ANY_INTERFACE,
-               .type = QUIRK_COMPOSITE,
-               .data = & (const struct snd_usb_audio_quirk[]) {
-                       {
-                               /* InterfaceSubClass 1 (Control Device) */
-                               .ifnum = 0,
-                               .type = QUIRK_IGNORE_INTERFACE
-                       },
-                       {
-                               .ifnum = 1,
-                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
-                       },
-                       {
-                               .ifnum = 2,
-                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
-                       },
-                       {
-                               /* InterfaceSubClass 1 (Control Device) */
-                               .ifnum = 3,
-                               .type = QUIRK_IGNORE_INTERFACE
-                       },
-                       {
-                               .ifnum = 4,
-                               .type = QUIRK_MIDI_STANDARD_INTERFACE
-                       },
-                       {
-                               /* InterfaceSubClass 1 (Device Firmware Update) */
-                               .ifnum = 5,
-                               .type = QUIRK_IGNORE_INTERFACE
-                       },
-                       {
-                               .ifnum = -1
-                       }
-               }
-       }
-},
-
 {
        /*
         * Some USB MIDI devices don't have an audio control interface,
index 0df9ede99dfd798730376574511fa1041f2f528c..89730707614c3686be440a7d763700e375cd1f81 100644 (file)
@@ -660,10 +660,23 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
        return err;
 }
 
+/* quirk for Plantronics GameCom 780 with CM6302 chip */
+static int snd_usb_gamecon780_boot_quirk(struct usb_device *dev)
+{
+       /* set the initial volume and don't change; other values are either
+        * too loud or silent due to firmware bug (bko#65251)
+        */
+       u8 buf[2] = { 0x74, 0xdc };
+       return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
+                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+                       UAC_FU_VOLUME << 8, 9 << 8, buf, 2);
+}
+
 /*
  * Novation Twitch DJ controller
+ * Focusrite Novation Saffire 6 USB audio card
  */
-static int snd_usb_twitch_boot_quirk(struct usb_device *dev)
+static int snd_usb_novation_boot_quirk(struct usb_device *dev)
 {
        /* preemptively set up the device because otherwise the
         * raw MIDI endpoints are not active */
@@ -972,9 +985,9 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
                /* Digidesign Mbox 2 */
                return snd_usb_mbox2_boot_quirk(dev);
 
-       case USB_ID(0x1235, 0x0018):
-               /* Focusrite Novation Twitch */
-               return snd_usb_twitch_boot_quirk(dev);
+       case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
+       case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
+               return snd_usb_novation_boot_quirk(dev);
 
        case USB_ID(0x133e, 0x0815):
                /* Access Music VirusTI Desktop */
@@ -986,6 +999,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
                return snd_usb_nativeinstruments_boot_quirk(dev);
        case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
                return snd_usb_fasttrackpro_boot_quirk(dev);
+       case USB_ID(0x047f, 0xc010): /* Plantronics Gamecom 780 */
+               return snd_usb_gamecon780_boot_quirk(dev);
        }
 
        return 0;
index 0362d575de7d185752b2a23a53845236c71510f6..217c82ee3665704282443261c512d1c3920ed699 100644 (file)
@@ -1606,6 +1606,24 @@ process_arg(struct event_format *event, struct print_arg *arg, char **tok)
 static enum event_type
 process_op(struct event_format *event, struct print_arg *arg, char **tok);
 
+/*
+ * For __print_symbolic() and __print_flags, we need to completely
+ * evaluate the first argument, which defines what to print next.
+ */
+static enum event_type
+process_field_arg(struct event_format *event, struct print_arg *arg, char **tok)
+{
+       enum event_type type;
+
+       type = process_arg(event, arg, tok);
+
+       while (type == EVENT_OP) {
+               type = process_op(event, arg, tok);
+       }
+
+       return type;
+}
+
 static enum event_type
 process_cond(struct event_format *event, struct print_arg *top, char **tok)
 {
@@ -2371,7 +2389,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok)
                goto out_free;
        }
 
-       type = process_arg(event, field, &token);
+       type = process_field_arg(event, field, &token);
 
        /* Handle operations in the first argument */
        while (type == EVENT_OP)
@@ -2424,7 +2442,8 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
                goto out_free;
        }
 
-       type = process_arg(event, field, &token);
+       type = process_field_arg(event, field, &token);
+
        if (test_type_token(type, token, EVENT_DELIM, ","))
                goto out_free_field;
 
@@ -3446,7 +3465,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                 * is in the bottom half of the 32 bit field.
                 */
                offset &= 0xffff;
-               val = (unsigned long long)(data + offset);
+               val = (unsigned long long)((unsigned long)data + offset);
                break;
        default: /* not sure what to do there */
                return 0;
index 369c03648f8846d3da12bf96a938f6e76485fbed..1cd035708931144dccbfdb68f4c1024903e45631 100644 (file)
@@ -2078,8 +2078,10 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
                if (evsel->idx == (int) desc[i].leader_idx) {
                        evsel->leader = evsel;
                        /* {anon_group} is a dummy name */
-                       if (strcmp(desc[i].name, "{anon_group}"))
+                       if (strcmp(desc[i].name, "{anon_group}")) {
                                evsel->group_name = desc[i].name;
+                               desc[i].name = NULL;
+                       }
                        evsel->nr_members = desc[i].nr_members;
 
                        if (i >= nr_groups || nr > 0) {
@@ -2105,7 +2107,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
 
        ret = 0;
 out_free:
-       while ((int) --i >= 0)
+       for (i = 0; i < nr_groups; i++)
                free(desc[i].name);
        free(desc);
 
index cd8e2f59271969f410daf28afdf93523699f475c..49eaf1d7d89d0554a146a272e923cd139e6cbac7 100644 (file)
@@ -70,14 +70,13 @@ int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
        /* Override latest entry if it had no specific time coverage */
        if (!curr->start) {
                comm__override(curr, str, timestamp);
-               return 0;
+       } else {
+               new = comm__new(str, timestamp);
+               if (!new)
+                       return -ENOMEM;
+               list_add(&new->list, &thread->comm_list);
        }
 
-       new = comm__new(str, timestamp);
-       if (!new)
-               return -ENOMEM;
-
-       list_add(&new->list, &thread->comm_list);
        thread->comm_set = true;
 
        return 0;
index 4178effd9e99ce217c2c65a34dcfe09b4eb5edfa..7b3646adb92f597cf9016c88e3c5d97e12f2b9c0 100644 (file)
@@ -87,4 +87,5 @@ Thomas Renninger <trenn@suse.de>
 .fi
 .SH "SEE ALSO"
 .LP
-cpupower(1), cpupower\-monitor(1), cpupower\-info(1), cpupower\-set(1)
+cpupower(1), cpupower\-monitor(1), cpupower\-info(1), cpupower\-set(1),
+cpupower\-idle\-set(1)
diff --git a/tools/power/cpupower/man/cpupower-idle-set.1 b/tools/power/cpupower/man/cpupower-idle-set.1
new file mode 100644 (file)
index 0000000..6b16072
--- /dev/null
@@ -0,0 +1,71 @@
+.TH "CPUPOWER-IDLE-SET" "1" "0.1" "" "cpupower Manual"
+.SH "NAME"
+.LP
+cpupower idle\-set \- Utility to set cpu idle state specific kernel options
+.SH "SYNTAX"
+.LP
+cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
+.SH "DESCRIPTION"
+.LP
+The cpupower idle\-set subcommand allows to set cpu idle, also called cpu
+sleep state, specific options offered by the kernel. One example is disabling
+sleep states. This can be handy for power vs performance tuning.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-d\fR \fB\-\-disable\fR
+Disable a specific processor sleep state.
+.TP
+\fB\-e\fR \fB\-\-enable\fR
+Enable a specific processor sleep state.
+
+.SH "REMARKS"
+.LP
+Cpuidle Governors Policy on Disabling Sleep States
+
+.RS 4
+Depending on the used  cpuidle governor, implementing the kernel policy
+how to choose sleep states, subsequent sleep states on this core, might get
+disabled as well.
+
+There are two cpuidle governors ladder and menu. While the ladder
+governor is always available, if CONFIG_CPU_IDLE is selected, the
+menu governor additionally requires CONFIG_NO_HZ.
+
+The behavior and the effect of the disable variable depends on the
+implementation of a particular governor. In the ladder governor, for
+example, it is not coherent, i.e. if one is disabling a light state,
+then all deeper states are disabled as well. Likewise, if one enables a
+deep state but a lighter state still is disabled, then this has no effect.
+.RE
+.LP
+Disabling the Lightest Sleep State may not have any Affect
+
+.RS 4
+If criteria are not met to enter deeper sleep states and the lightest sleep
+state is chosen when idle, the kernel may still enter this sleep state,
+irrespective of whether it is disabled or not. This is also reflected in
+the usage count of the disabled sleep state when using the cpupower idle-info
+command.
+.RE
+.LP
+Selecting specific CPU Cores
+
+.RS 4
+By default processor sleep states of all CPU cores are set. Please refer
+to the cpupower(1) manpage in the \-\-cpu option section how to disable
+C-states of specific cores.
+.RE
+.SH "FILES"
+.nf
+\fI/sys/devices/system/cpu/cpu*/cpuidle/state*\fP
+\fI/sys/devices/system/cpu/cpuidle/*\fP
+.fi
+.SH "AUTHORS"
+.nf
+Thomas Renninger <trenn@suse.de>
+.fi
+.SH "SEE ALSO"
+.LP
+cpupower(1), cpupower\-monitor(1), cpupower\-info(1), cpupower\-set(1),
+cpupower\-idle\-info(1)
index dc4de37621117f7dc6fe8d47669e761063c9eed0..bcf1d2f0b791337169ee54ffce946619006015ae 100644 (file)
@@ -18,9 +18,9 @@
 #include "helpers/bitmask.h"
 
 static struct option set_opts[] = {
-       { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
-       { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
-       { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
+       { .name = "perf-bias",  .has_arg = required_argument,   .flag = NULL,   .val = 'b'},
+       { .name = "sched-mc",   .has_arg = required_argument,   .flag = NULL,   .val = 'm'},
+       { .name = "sched-smt",  .has_arg = required_argument,   .flag = NULL,   .val = 's'},
        { },
 };
 
index 5cdc600e8152efae140687df6a532933e196cf59..851c7a16ca49633f0db3fd155b15466dfc4ab4fa 100644 (file)
@@ -278,7 +278,7 @@ static char *sysfs_idlestate_get_one_string(unsigned int cpu,
 int sysfs_is_idlestate_disabled(unsigned int cpu,
                                unsigned int idlestate)
 {
-       if (sysfs_get_idlestate_count(cpu) < idlestate)
+       if (sysfs_get_idlestate_count(cpu) <= idlestate)
                return -1;
 
        if (!sysfs_idlestate_file_exists(cpu, idlestate,
@@ -303,7 +303,7 @@ int sysfs_idlestate_disable(unsigned int cpu,
        char value[SYSFS_PATH_MAX];
        int bytes_written;
 
-       if (sysfs_get_idlestate_count(cpu) < idlestate)
+       if (sysfs_get_idlestate_count(cpu) <= idlestate)
                return -1;
 
        if (!sysfs_idlestate_file_exists(cpu, idlestate,
index 396d6c44e9d738d8cf85a0ce20317b001c573212..acf2165c04e64f8b15e844b787de9f59c324b199 100644 (file)
@@ -3,11 +3,12 @@
 CC = $(CROSS_COMPILE)gcc
 PTHREAD_LIBS = -lpthread
 WARNINGS = -Wall -Wextra
-CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) -I../include
+CFLAGS = $(WARNINGS) -g -I../include
+LDFLAGS = $(PTHREAD_LIBS)
 
 all: testusb ffs-test
 %: %.c
-       $(CC) $(CFLAGS) -o $@ $^
+       $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
 
 clean:
        $(RM) testusb ffs-test
index a0aa84b5941ac96aabae48b03d80278052ce8929..4f588bc941861b10f7d5dccf9305941c8d3cc218 100644 (file)
@@ -1898,6 +1898,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        int r;
        struct kvm_vcpu *vcpu, *v;
 
+       if (id >= KVM_MAX_VCPUS)
+               return -EINVAL;
+
        vcpu = kvm_arch_vcpu_create(kvm, id);
        if (IS_ERR(vcpu))
                return PTR_ERR(vcpu);