Merge remote-tracking branches 'spi/topic/fsl-espi', 'spi/topic/gpio', 'spi/topic...
authorMark Brown <broonie@linaro.org>
Thu, 23 Jan 2014 13:07:09 +0000 (13:07 +0000)
committerMark Brown <broonie@linaro.org>
Thu, 23 Jan 2014 13:07:09 +0000 (13:07 +0000)
1541 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/spi/nvidia,tegra20-spi.txt [deleted file]
Documentation/devicetree/bindings/spi/spi-bus.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/gpio.txt [deleted file]
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 [new file with mode: 0644]
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/spi/spi-summary
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/include/uapi/asm/unistd.h
arch/arc/kernel/perf_event.c
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/exynos5250.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/crypto/aesbs-core.S_shipped
arch/arm/crypto/bsaes-armv7.pl
arch/arm/include/asm/io.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/xen/page.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-timer.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/mach-s3c64xx-dt.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-tegra/fuse.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/flush.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/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/cacheflush.h
arch/parisc/include/asm/page.h
arch/parisc/include/asm/serial.h
arch/parisc/kernel/cache.c
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/mpc5125twr.dts
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/exception-64s.h
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/include/asm/unaligned.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/head_64.S
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/lib/copyuser_64.S
arch/powerpc/mm/hugetlbpage-book3e.c
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/opal-lpc.c
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.h
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/smp.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/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.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/s390/pci/pci_event.c
arch/sh/kernel/sh_ksyms_32.c
arch/sh/lib/Makefile
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/kernel/iommu.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/kgdb_64.c
arch/sparc/kernel/smp_64.c
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/ablk_helper.c [deleted file]
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/crypto/ablk_helper.h [deleted file]
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/vmx.c
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 [new file with mode: 0644]
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/ac.c
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/battery.c
drivers/acpi/bus.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/ata/sata_sis.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/bluetooth/ath3k.c
drivers/bluetooth/btusb.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/char/tpm/tpm_ppi.c
drivers/clk/clk-divider.c
drivers/clk/clk-s2mps11.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.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/intel_pstate.c
drivers/cpufreq/tegra-cpufreq.c
drivers/cpuidle/cpuidle-calxeda.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/ioat/dma.c
drivers/dma/mmp_pdma.c
drivers/dma/mv_xor.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/core/subdev.c
drivers/gpu/drm/nouveau/core/engine/device/base.c
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.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/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
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_abi16.c
drivers/gpu/drm/nouveau/nouveau_acpi.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.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_atpx_handler.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_kms.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_trace.h
drivers/gpu/drm/radeon/radeon_uvd.c
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/cm.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/ulp/ipoib/ipoib_netlink.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/input/input.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/input/touchscreen/zforce_ts.c
drivers/iommu/arm-smmu.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/telespci.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.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/rtsx_pcr.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/ti-ssp.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/maps/pxa2xx-flash.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/net/bonding/bond_3ad.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/arc/emac_main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.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/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h
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/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/phy.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/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_selftest.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
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_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.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/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/tile/tilegx.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/hamradio/hdlcdrv.c
drivers/net/hamradio/yam.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/vitesse.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/dm9601.c
drivers/net/usb/hso.c
drivers/net/usb/mcs7830.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/main.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/main.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/xen-netback/common.h
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/of/Kconfig
drivers/of/address.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/pci/host/pci-mvebu.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pci-acpi.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 [new file with mode: 0644]
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/chromeos_laptop.c [deleted file]
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/power/Kconfig
drivers/power/power_supply_core.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/s390/char/tty3270.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/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx-hsspi.c [new file with mode: 0644]
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bitbang-txrx.h
drivers/spi/spi-clps711x.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-falcon.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-imx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mxs.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-sc18is602.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh.c
drivers/spi/spi-sirf.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-txx9.c
drivers/spi/spi.c
drivers/staging/bcm/Bcmnet.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/netlogic/xlr_net.c
drivers/staging/nvec/nvec.c
drivers/staging/rtl8188eu/core/rtw_ap.c
drivers/staging/rtl8188eu/os_dep/os_intfs.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/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/ioctl.c
fs/cifs/link.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/gfs2/aops.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/log.c
fs/gfs2/meta_io.c
fs/gfs2/ops_fstype.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_attr_remote.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 [new file with mode: 0644]
include/crypto/algapi.h
include/crypto/authenc.h
include/crypto/scatterwalk.h
include/drm/drm_pciids.h
include/linux/assoc_array.h
include/linux/auxvec.h
include/linux/compiler-intel.h
include/linux/dcache.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/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/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/spi-nuc900.h
include/linux/pstore.h
include/linux/reboot.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/shmem_fs.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/spi/spi.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/llc_pdu.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/memalloc.h
include/sound/soc-dapm.h
include/target/target_core_base.h
include/trace/ftrace.h
include/uapi/drm/radeon_drm.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/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/fremap.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mlock.c
mm/mprotect.c
mm/page_alloc.c
mm/pgtable-generic.c
mm/rmap.c
mm/shmem.c
net/8021q/vlan_dev.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/fragmentation.c
net/batman-adv/icmp_socket.c
net/batman-adv/main.c
net/batman-adv/network-coding.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_sock.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_stp_bpdu.c
net/compat.c
net/core/dev.c
net/core/drop_monitor.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/netpoll.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ipv6.c
net/dccp/probe.c
net/hsr/hsr_framereg.c
net/hsr/hsr_netlink.c
net/ieee802154/6lowpan.c
net/ipv4/fib_rules.c
net/ipv4/gre_offload.c
net/ipv4/inet_diag.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.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/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.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/llc/af_llc.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/tx.c
net/mac80211/util.c
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_conntrack_seqadj.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_log.c
net/netfilter/nft_exthdr.c
net/netfilter/xt_hashlimit.c
net/netlink/genetlink.c
net/nfc/core.c
net/packet/af_packet.c
net/rds/ib.c
net/rds/ib_send.c
net/rose/af_rose.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_generic.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/tipc/link.c
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/ibss.c
net/wireless/nl80211.c
net/wireless/radiotap.c
net/wireless/sme.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/objsec.h
security/selinux/include/xfrm.h
security/selinux/ss/services.c
security/selinux/xfrm.c
sound/atmel/abdac.c
sound/core/pcm_lib.c
sound/firewire/amdtp.c
sound/firewire/dice.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
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/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/sam9x5_wm8731.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-wm8962.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/omap/n810.c
sound/soc/sh/Kconfig
sound/soc/soc-core.c
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c
sound/usb/endpoint.c
sound/usb/mixer_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..0f2f920e87348515995cb553ece45cf0949213b7 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
@@ -159,6 +159,8 @@ clock which they consume.
   mixer                        343
   hdmi                 344
   g2d                  345
+  mdma0                        346
+  smmu_mdma0           347
 
 
    [Clock Muxes]
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/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 800dafe5b01b1b6cc0e6c8f4fcd6d9432c9d699f..e5a4d1b4acfe1efca8b0a41d5d736ddf8187f009 100644 (file)
@@ -67,7 +67,7 @@ only 1(SINGLE), 2(DUAL) and 4(QUAD).
 Dual/Quad mode is not allowed when 3-wire mode is used.
 
 If a gpio chipselect is used for the SPI slave the gpio number will be passed
-via the cs_gpio
+via the SPI master node cs-gpios property.
 
 SPI example for an MPC5200 SPI bus:
        spi@f00 {
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.txt b/Documentation/gpio.txt
deleted file mode 100644 (file)
index 6f83fa9..0000000
+++ /dev/null
@@ -1,775 +0,0 @@
-GPIO Interfaces
-
-This provides an overview of GPIO access conventions on Linux.
-
-These calls use the gpio_* naming prefix.  No other calls should use that
-prefix, or the related __gpio_* prefix.
-
-
-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 busses.
-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 writeprotect status, driving
-a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
-watchdog, sensing a switch, and so on.
-
-
-GPIO conventions
-================
-Note that this is called a "convention" because you don't need to do it this
-way, and it's no crime if you don't.  There **are** cases where portability
-is not the main issue; GPIOs are often used for the kind of board-specific
-glue logic that may even change between board revisions, and can't ever be
-used on a board that's wired differently.  Only least-common-denominator
-functionality can be very portable.  Other features are platform-specific,
-and that can be critical for glue logic.
-
-Plus, this doesn't require any implementation framework, just an interface.
-One platform might implement it as simple inline functions accessing chip
-registers; another might implement it by delegating through abstractions
-used for several very different kinds of GPIO controller.  (There is some
-optional code supporting such an implementation strategy, described later
-in this document, but drivers acting as clients to the GPIO interface must
-not care how it's implemented.)
-
-That said, if the convention is supported on their platform, drivers should
-use it when possible.  Platforms must select ARCH_REQUIRE_GPIOLIB or
-ARCH_WANT_OPTIONAL_GPIOLIB in their Kconfig.  Drivers that can't work without
-standard GPIO calls should have Kconfig entries which depend on GPIOLIB.  The
-GPIO calls are available, either as "real code" or as optimized-away stubs,
-when drivers use the include file:
-
-       #include <linux/gpio.h>
-
-If you stick to this convention then it'll be easier for other developers to
-see what your code is doing, and help maintain it.
-
-Note that these operations include I/O barriers on platforms which need to
-use them; drivers don't need to add them explicitly.
-
-
-Identifying GPIOs
------------------
-GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
-reserves "negative" numbers for other purposes like marking signals as
-"not available on this board", or indicating faults.  Code that doesn't
-touch the underlying hardware treats these integers as opaque cookies.
-
-Platforms define how they use those integers, and usually #define symbols
-for the GPIO lines so that board-specific setup code directly corresponds
-to the relevant schematics.  In contrast, drivers should only use GPIO
-numbers passed to them from that setup code, using platform_data to hold
-board-specific pin configuration data (along with other board specific
-data they need).  That avoids portability problems.
-
-So for example one platform uses numbers 32-159 for GPIOs; while another
-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.
-
-If you want to initialize a structure with an invalid GPIO number, use
-some negative number (perhaps "-EINVAL"); that will never be valid.  To
-test if such number from such a structure could reference a GPIO, you
-may use this predicate:
-
-       int gpio_is_valid(int number);
-
-A number that's not valid will be rejected by calls which may request
-or free GPIOs (see below).  Other numbers may also be rejected; for
-example, a number might be valid but temporarily unused on a given board.
-
-Whether a platform supports multiple GPIO controllers is a platform-specific
-implementation issue, as are whether that support can leave "holes" in the space
-of GPIO numbers, and whether new controllers can be added at runtime.  Such issues
-can affect things including whether adjacent GPIO numbers are both valid.
-
-Using GPIOs
------------
-The first thing a system should do with a GPIO is allocate it, using
-the gpio_request() call; see later.
-
-One of the next things to do with a GPIO, often in board setup code when
-setting up a platform_device using the GPIO, is mark its direction:
-
-       /* set as input or output, returning 0 or negative errno */
-       int gpio_direction_input(unsigned gpio);
-       int gpio_direction_output(unsigned gpio, int value);
-
-The return value is zero for success, else a negative errno.  It should
-be checked, since the get/set calls don't have error returns and since
-misconfiguration is possible.  You should normally issue these calls from
-a task context.  However, for spinlock-safe GPIOs it's 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.
-
-For compatibility with legacy interfaces to GPIOs, setting the direction
-of a GPIO implicitly requests that GPIO (see below) if it has not been
-requested already.  That compatibility is being removed from the optional
-gpiolib framework.
-
-Setting the direction can fail if the GPIO number is invalid, or when
-that particular GPIO can't be used in that mode.  It's generally a bad
-idea to rely on boot firmware to have set the direction correctly, since
-it probably wasn't validated to do more than boot Linux.  (Similarly,
-that board setup code probably needs to multiplex that pin as a GPIO,
-and configure pullups/pulldowns appropriately.)
-
-
-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
-(nonthreaded) IRQ handlers and similar contexts.
-
-Use the following calls to access such GPIOs,
-for which gpio_cansleep() will always return false (see below):
-
-       /* GPIO INPUT:  return zero or nonzero */
-       int gpio_get_value(unsigned gpio);
-
-       /* GPIO OUTPUT */
-       void gpio_set_value(unsigned gpio, 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 have no error returns because "invalid GPIO" should have
-been reported earlier from gpio_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.
-
-Platform-specific implementations are encouraged to optimize the two
-calls to access the GPIO value in cases where the GPIO number (and for
-output, value) are constant.  It's normal for them to need only a couple
-of instructions in such cases (reading or writing a hardware register),
-and not to need spinlocks.  Such optimized calls can make bitbanging
-applications a lot more efficient (in both space and time) than spending
-dozens of instructions on subroutine calls.
-
-
-GPIO access that may sleep
---------------------------
-Some GPIO controllers must be accessed using message based busses 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 (which requires a valid GPIO number,
-which should have been previously allocated with gpio_request):
-
-       int gpio_cansleep(unsigned gpio);
-
-To access such GPIOs, a different set of accessors is defined:
-
-       /* GPIO INPUT:  return zero or nonzero, might sleep */
-       int gpio_get_value_cansleep(unsigned gpio);
-
-       /* GPIO OUTPUT, might sleep */
-       void gpio_set_value_cansleep(unsigned gpio, 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.
-
-  ** IN ADDITION ** calls to setup and configure such GPIOs must be made
-from contexts which may sleep, since they may need to access the GPIO
-controller chip too:  (These setup calls are usually made from board
-setup or driver probe/teardown code, so this is an easy constraint.)
-
-       gpio_direction_input()
-       gpio_direction_output()
-       gpio_request()
-
-##     gpio_request_one()
-##     gpio_request_array()
-##     gpio_free_array()
-
-       gpio_free()
-       gpio_set_debounce()
-
-
-
-Claiming and Releasing GPIOs
-----------------------------
-To help catch system configuration errors, two calls are defined.
-
-       /* request GPIO, returning 0 or negative errno.
-        * non-null labels may be useful for diagnostics.
-        */
-       int gpio_request(unsigned gpio, const char *label);
-
-       /* release previously-claimed GPIO */
-       void gpio_free(unsigned gpio);
-
-Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
-GPIOs that have already been claimed with that call.  The return value of
-gpio_request() must be checked.  You should normally issue these calls from
-a task context.  However, for spinlock-safe GPIOs it's OK to request GPIOs
-before tasking is enabled, as part of early board setup.
-
-These calls serve two basic purposes.  One is marking the signals which
-are actually in use as GPIOs, for better diagnostics; systems may have
-several hundred potential GPIOs, but often only a dozen are used on any
-given board.  Another is to catch conflicts, identifying errors when
-(a) two or more drivers wrongly think they have exclusive use of that
-signal, or (b) something wrongly believes it's safe to remove drivers
-needed to manage a signal that's in active use.  That is, requesting a
-GPIO can serve as a kind of lock.
-
-Some platforms may also use knowledge about what GPIOs are active for
-power management, such as by powering down unused chip sectors and, more
-easily, gating off unused clocks.
-
-For GPIOs that use pins known to the pinctrl subsystem, that subsystem should
-be informed of their use; a gpiolib driver's .request() operation may call
-pinctrl_request_gpio(), and a gpiolib driver's .free() operation may call
-pinctrl_free_gpio(). The pinctrl subsystem allows a pinctrl_request_gpio()
-to succeed concurrently with a pin or pingroup being "owned" by a device for
-pin multiplexing.
-
-Any programming of pin multiplexing hardware that is needed to route the
-GPIO signal to the appropriate pin should occur within a GPIO driver's
-.direction_input() or .direction_output() operations, and occur after any
-setup of an output GPIO's value. This allows a glitch-free migration from a
-pin's special function to GPIO. This is sometimes required when using a GPIO
-to implement a workaround on signals typically driven by a non-GPIO HW block.
-
-Some platforms allow some or all GPIO signals to be routed to different pins.
-Similarly, other aspects of the GPIO or pin may need to be configured, such as
-pullup/pulldown. Platform software should arrange that any such details are
-configured prior to gpio_request() being called for those GPIOs, e.g. using
-the pinctrl subsystem's mapping table, so that GPIO users need not be aware
-of these details.
-
-Also note that it's your responsibility to have stopped using a GPIO
-before you free it.
-
-Considering in most cases GPIOs are actually configured right after they
-are claimed, three additional calls are defined:
-
-       /* request a single GPIO, with initial configuration specified by
-        * 'flags', identical to gpio_request() wrt other arguments and
-        * return value
-        */
-       int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-
-       /* request multiple GPIOs in a single call
-        */
-       int gpio_request_array(struct gpio *array, size_t num);
-
-       /* release multiple GPIOs in a single call
-        */
-       void gpio_free_array(struct gpio *array, size_t num);
-
-where 'flags' is currently defined to specify the following properties:
-
-       * GPIOF_DIR_IN          - to configure direction as input
-       * GPIOF_DIR_OUT         - to configure direction as output
-
-       * GPIOF_INIT_LOW        - as output, set initial level to LOW
-       * GPIOF_INIT_HIGH       - as output, set initial level to HIGH
-       * GPIOF_OPEN_DRAIN      - gpio pin is open drain type.
-       * GPIOF_OPEN_SOURCE     - gpio pin is open source type.
-
-       * GPIOF_EXPORT_DIR_FIXED        - export gpio to sysfs, keep direction
-       * GPIOF_EXPORT_DIR_CHANGEABLE   - also export, allow changing direction
-
-since GPIOF_INIT_* are only valid when configured as output, so group valid
-combinations as:
-
-       * GPIOF_IN              - configure as input
-       * GPIOF_OUT_INIT_LOW    - configured as output, initial level LOW
-       * GPIOF_OUT_INIT_HIGH   - configured as output, initial level HIGH
-
-When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is
-open drain type. Such pins will not be driven to 1 in output mode. It is
-require to connect pull-up on such pins. By enabling this flag, gpio lib will
-make the direction to input when it is asked to set value of 1 in output mode
-to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode.
-
-When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is
-open source type. Such pins will not be driven to 0 in output mode. It is
-require to connect pull-down on such pin. By enabling this flag, gpio lib will
-make the direction to input when it is asked to set value of 0 in output mode
-to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode.
-
-In the future, these flags can be extended to support more properties.
-
-Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
-introduced to encapsulate all three fields as:
-
-       struct gpio {
-               unsigned        gpio;
-               unsigned long   flags;
-               const char      *label;
-       };
-
-A typical example of usage:
-
-       static struct gpio leds_gpios[] = {
-               { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */
-               { 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* default to OFF */
-               { 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* default to OFF */
-               { 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* default to OFF */
-               { ... },
-       };
-
-       err = gpio_request_one(31, GPIOF_IN, "Reset Button");
-       if (err)
-               ...
-
-       err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
-       if (err)
-               ...
-
-       gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
-
-
-GPIOs mapped to IRQs
---------------------
-GPIO numbers are unsigned integers; so are IRQ numbers.  These make up
-two logically distinct namespaces (GPIO 0 need not use IRQ 0).  You can
-map between them using calls like:
-
-       /* map GPIO numbers to IRQ numbers */
-       int gpio_to_irq(unsigned gpio);
-
-       /* map IRQ numbers to GPIO numbers (avoid using this) */
-       int irq_to_gpio(unsigned irq);
-
-Those return either the corresponding number in the other namespace, or
-else a negative errno code if the mapping can't be done.  (For example,
-some GPIOs can't be used as IRQs.)  It is an unchecked error to use a GPIO
-number that wasn't set up as an input using gpio_direction_input(), or
-to use an IRQ number that didn't originally come from gpio_to_irq().
-
-These two mapping calls are expected to cost on the order of a single
-addition or subtraction.  They're not allowed to sleep.
-
-Non-error values returned from gpio_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.
-
-Non-error values returned from irq_to_gpio() would most commonly be used
-with gpio_get_value(), for example to initialize or update driver state
-when the IRQ is edge-triggered.  Note that some platforms don't support
-this reverse mapping, so you should avoid using it.
-
-
-Emulating Open Drain Signals
-----------------------------
-Sometimes shared signals need to use "open drain" signaling, where only the
-low signal level is actually driven.  (That term applies to CMOS transistors;
-"open collector" is used for TTL.)  A pullup resistor causes the high 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 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:  gpio_direction_output(gpio, 0) ... this drives the signal
-       and overrides the pullup.
-
- HIGH: gpio_direction_input(gpio) ... this turns off the output,
-       so the pullup (or some other device) controls the signal.
-
-If you are "driving" the signal high but gpio_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.
-
-
-GPIO controllers and the pinctrl subsystem
-------------------------------------------
-
-A GPIO controller on a SOC might be tightly coupled with the pinctrl
-subsystem, in the sense that the pins can be used by other functions
-together with an optional gpio feature. We have already covered the
-case where e.g. a GPIO controller need to reserve a pin or set the
-direction of a pin by calling any of:
-
-pinctrl_request_gpio()
-pinctrl_free_gpio()
-pinctrl_gpio_direction_input()
-pinctrl_gpio_direction_output()
-
-But how does the pin control subsystem cross-correlate the GPIO
-numbers (which are a global business) to a certain pin on a certain
-pin controller?
-
-This is done by registering "ranges" of pins, which are essentially
-cross-reference tables. These are described in
-Documentation/pinctrl.txt
-
-While the pin allocation is totally managed by the pinctrl subsystem,
-gpio (under gpiolib) is still maintained by gpio drivers. It may happen
-that different pin ranges in a SoC is managed by different gpio drivers.
-
-This makes it logical to let gpio drivers announce their pin ranges to
-the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
-to request the corresponding pin to be prepared by the pinctrl subsystem
-before any gpio usage.
-
-For this, the gpio controller can register its pin range with pinctrl
-subsystem. There are two ways of doing it currently: with or without DT.
-
-For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
-
-For non-DT support, user can call gpiochip_add_pin_range() with appropriate
-parameters to register a range of gpio pins with a pinctrl driver. For this
-exact name string of pinctrl device has to be passed as one of the
-argument to this routine.
-
-
-What do these conventions omit?
-===============================
-One of the biggest things these conventions omit is pin multiplexing, since
-this is highly chip-specific and nonportable.  One platform might not need
-explicit multiplexing; another might have just two options for use of any
-given pin; another might have eight options per pin; another might be able
-to route a given GPIO to any one of several pins.  (Yes, those examples all
-come from systems that run Linux today.)
-
-Related to multiplexing is configuration and enabling of the pullups or
-pulldowns integrated on some platforms.  Not all platforms support them,
-or support them in the same way; and any given board might use external
-pullups (or pulldowns) so that the on-chip ones should not be used.
-(When a circuit needs 5 kOhm, on-chip 100 kOhm resistors won't do.)
-Likewise drive strength (2 mA vs 20 mA) and voltage (1.8V vs 3.3V) is a
-platform-specific issue, as are models like (not) having a one-to-one
-correspondence between configurable pins and GPIOs.
-
-There are other system-specific mechanisms that are not specified here,
-like the aforementioned options for input de-glitching and wire-OR output.
-Hardware may support reading or writing GPIOs in gangs, but that's usually
-configuration dependent:  for GPIOs sharing the same bank.  (GPIOs are
-commonly grouped in banks of 16 or 32, with a given SOC having several such
-banks.)  Some systems can trigger IRQs from output GPIOs, or read values
-from pins not managed as GPIOs.  Code relying on such mechanisms will
-necessarily be nonportable.
-
-Dynamic definition of GPIOs is not currently standard; for example, as
-a side effect of configuring an add-on board with some GPIO expanders.
-
-
-GPIO implementor's framework (OPTIONAL)
-=======================================
-As noted earlier, there is an optional implementation framework making it
-easier for platforms to support different kinds of GPIO controller using
-the same programming interface.  This framework is called "gpiolib".
-
-As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
-will be found there.  That will list all the controllers registered through
-this framework, and the state of the GPIOs currently in use.
-
-
-Controller Drivers: gpio_chip
------------------------------
-In this framework each GPIO controller is packaged as a "struct gpio_chip"
-with information common to each controller of that type:
-
- - methods to establish GPIO direction
- - methods used to access GPIO values
- - flag saying whether calls to its methods may sleep
- - optional debugfs dump method (showing extra state like pullup config)
- - label for diagnostics
-
-There is also per-instance data, which may come from device.platform_data:
-the number of its first GPIO, and how many GPIOs it exposes.
-
-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.
-
-
-Platform Support
-----------------
-To support this framework, a platform's Kconfig will "select" either
-ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
-and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
-three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
-
-It may also provide a custom value for ARCH_NR_GPIOS, so that it better
-reflects the number of GPIOs in actual use on that platform, without
-wasting static table space.  (It should count both built-in/SoC GPIOs and
-also ones on GPIO expanders.
-
-ARCH_REQUIRE_GPIOLIB means that the gpiolib code will always get compiled
-into the kernel on that architecture.
-
-ARCH_WANT_OPTIONAL_GPIOLIB means the gpiolib code defaults to off and the user
-can enable it and build it into the kernel optionally.
-
-If neither of these options are selected, the platform does not support
-GPIOs through GPIO-lib and the code cannot be enabled by the user.
-
-Trivial implementations of those functions can directly use framework
-code, which always dispatches through the gpio_chip:
-
-  #define gpio_get_value       __gpio_get_value
-  #define gpio_set_value       __gpio_set_value
-  #define gpio_cansleep                __gpio_cansleep
-
-Fancier implementations could instead define those as inline functions with
-logic optimizing access to specific SOC-based GPIOs.  For example, if the
-referenced GPIO is the constant "12", getting or setting its value could
-cost as little as two or three instructions, never sleeping.  When such an
-optimization is not possible those calls must delegate to the framework
-code, costing at least a few dozen instructions.  For bitbanged I/O, such
-instruction savings can be significant.
-
-For SOCs, platform-specific code defines and registers gpio_chip instances
-for each bank of on-chip GPIOs.  Those GPIOs should be numbered/labeled to
-match chip vendor documentation, and directly match board schematics.  They
-may well start at zero and go up to a platform-specific limit.  Such GPIOs
-are normally integrated into platform initialization to make them always be
-available, from arch_initcall() or earlier; they can often serve as IRQs.
-
-
-Board Support
--------------
-For external GPIO controllers -- such as I2C or SPI expanders, ASICs, multi
-function devices, FPGAs or CPLDs -- most often board-specific code handles
-registering controller devices and ensures that their drivers know what GPIO
-numbers to use with gpiochip_add().  Their numbers often start right after
-platform-specific GPIOs.
-
-For example, board setup code could create structures identifying the range
-of GPIOs that chip will expose, and passes them to each GPIO expander chip
-using platform_data.  Then the chip driver's probe() routine could pass that
-data to gpiochip_add().
-
-Initialization order can be important.  For example, when a device relies on
-an I2C-based GPIO, its probe() routine should only be called after that GPIO
-becomes available.  That may mean the device should not be registered until
-calls for that GPIO can work.  One way to address such dependencies is for
-such gpio_chip controllers to provide setup() and teardown() callbacks to
-board specific code; those board specific callbacks would register devices
-once all the necessary resources are available, and remove them later when
-the GPIO controller device becomes unavailable.
-
-
-Sysfs Interface for Userspace (OPTIONAL)
-========================================
-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 gpio_export(unsigned gpio, bool direction_may_change);
-
-       /* reverse gpio_export() */
-       void gpio_unexport();
-
-       /* create a sysfs link to an exported GPIO node */
-       int gpio_export_link(struct device *dev, const char *name,
-               unsigned gpio)
-
-       /* change the polarity of a GPIO node in sysfs */
-       int gpio_sysfs_set_active_low(unsigned gpio, int value);
-
-After a kernel driver requests a GPIO, it may only be made available in
-the sysfs interface by gpio_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, gpio_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 gpio_sysfs_set_active_low() to hide GPIO line polarity
-differences between boards from user space.  This only affects the
-sysfs interface.  Polarity change can be done both before and after
-gpio_export(), and previously enabled poll(2) support for either
-rising or falling edge will be reconfigured to follow this setting.
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-legacy.txt b/Documentation/gpio/gpio-legacy.txt
new file mode 100644 (file)
index 0000000..6f83fa9
--- /dev/null
@@ -0,0 +1,775 @@
+GPIO Interfaces
+
+This provides an overview of GPIO access conventions on Linux.
+
+These calls use the gpio_* naming prefix.  No other calls should use that
+prefix, or the related __gpio_* prefix.
+
+
+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 busses.
+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 writeprotect status, driving
+a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
+watchdog, sensing a switch, and so on.
+
+
+GPIO conventions
+================
+Note that this is called a "convention" because you don't need to do it this
+way, and it's no crime if you don't.  There **are** cases where portability
+is not the main issue; GPIOs are often used for the kind of board-specific
+glue logic that may even change between board revisions, and can't ever be
+used on a board that's wired differently.  Only least-common-denominator
+functionality can be very portable.  Other features are platform-specific,
+and that can be critical for glue logic.
+
+Plus, this doesn't require any implementation framework, just an interface.
+One platform might implement it as simple inline functions accessing chip
+registers; another might implement it by delegating through abstractions
+used for several very different kinds of GPIO controller.  (There is some
+optional code supporting such an implementation strategy, described later
+in this document, but drivers acting as clients to the GPIO interface must
+not care how it's implemented.)
+
+That said, if the convention is supported on their platform, drivers should
+use it when possible.  Platforms must select ARCH_REQUIRE_GPIOLIB or
+ARCH_WANT_OPTIONAL_GPIOLIB in their Kconfig.  Drivers that can't work without
+standard GPIO calls should have Kconfig entries which depend on GPIOLIB.  The
+GPIO calls are available, either as "real code" or as optimized-away stubs,
+when drivers use the include file:
+
+       #include <linux/gpio.h>
+
+If you stick to this convention then it'll be easier for other developers to
+see what your code is doing, and help maintain it.
+
+Note that these operations include I/O barriers on platforms which need to
+use them; drivers don't need to add them explicitly.
+
+
+Identifying GPIOs
+-----------------
+GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
+reserves "negative" numbers for other purposes like marking signals as
+"not available on this board", or indicating faults.  Code that doesn't
+touch the underlying hardware treats these integers as opaque cookies.
+
+Platforms define how they use those integers, and usually #define symbols
+for the GPIO lines so that board-specific setup code directly corresponds
+to the relevant schematics.  In contrast, drivers should only use GPIO
+numbers passed to them from that setup code, using platform_data to hold
+board-specific pin configuration data (along with other board specific
+data they need).  That avoids portability problems.
+
+So for example one platform uses numbers 32-159 for GPIOs; while another
+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.
+
+If you want to initialize a structure with an invalid GPIO number, use
+some negative number (perhaps "-EINVAL"); that will never be valid.  To
+test if such number from such a structure could reference a GPIO, you
+may use this predicate:
+
+       int gpio_is_valid(int number);
+
+A number that's not valid will be rejected by calls which may request
+or free GPIOs (see below).  Other numbers may also be rejected; for
+example, a number might be valid but temporarily unused on a given board.
+
+Whether a platform supports multiple GPIO controllers is a platform-specific
+implementation issue, as are whether that support can leave "holes" in the space
+of GPIO numbers, and whether new controllers can be added at runtime.  Such issues
+can affect things including whether adjacent GPIO numbers are both valid.
+
+Using GPIOs
+-----------
+The first thing a system should do with a GPIO is allocate it, using
+the gpio_request() call; see later.
+
+One of the next things to do with a GPIO, often in board setup code when
+setting up a platform_device using the GPIO, is mark its direction:
+
+       /* set as input or output, returning 0 or negative errno */
+       int gpio_direction_input(unsigned gpio);
+       int gpio_direction_output(unsigned gpio, int value);
+
+The return value is zero for success, else a negative errno.  It should
+be checked, since the get/set calls don't have error returns and since
+misconfiguration is possible.  You should normally issue these calls from
+a task context.  However, for spinlock-safe GPIOs it's 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.
+
+For compatibility with legacy interfaces to GPIOs, setting the direction
+of a GPIO implicitly requests that GPIO (see below) if it has not been
+requested already.  That compatibility is being removed from the optional
+gpiolib framework.
+
+Setting the direction can fail if the GPIO number is invalid, or when
+that particular GPIO can't be used in that mode.  It's generally a bad
+idea to rely on boot firmware to have set the direction correctly, since
+it probably wasn't validated to do more than boot Linux.  (Similarly,
+that board setup code probably needs to multiplex that pin as a GPIO,
+and configure pullups/pulldowns appropriately.)
+
+
+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
+(nonthreaded) IRQ handlers and similar contexts.
+
+Use the following calls to access such GPIOs,
+for which gpio_cansleep() will always return false (see below):
+
+       /* GPIO INPUT:  return zero or nonzero */
+       int gpio_get_value(unsigned gpio);
+
+       /* GPIO OUTPUT */
+       void gpio_set_value(unsigned gpio, 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 have no error returns because "invalid GPIO" should have
+been reported earlier from gpio_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.
+
+Platform-specific implementations are encouraged to optimize the two
+calls to access the GPIO value in cases where the GPIO number (and for
+output, value) are constant.  It's normal for them to need only a couple
+of instructions in such cases (reading or writing a hardware register),
+and not to need spinlocks.  Such optimized calls can make bitbanging
+applications a lot more efficient (in both space and time) than spending
+dozens of instructions on subroutine calls.
+
+
+GPIO access that may sleep
+--------------------------
+Some GPIO controllers must be accessed using message based busses 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 (which requires a valid GPIO number,
+which should have been previously allocated with gpio_request):
+
+       int gpio_cansleep(unsigned gpio);
+
+To access such GPIOs, a different set of accessors is defined:
+
+       /* GPIO INPUT:  return zero or nonzero, might sleep */
+       int gpio_get_value_cansleep(unsigned gpio);
+
+       /* GPIO OUTPUT, might sleep */
+       void gpio_set_value_cansleep(unsigned gpio, 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.
+
+  ** IN ADDITION ** calls to setup and configure such GPIOs must be made
+from contexts which may sleep, since they may need to access the GPIO
+controller chip too:  (These setup calls are usually made from board
+setup or driver probe/teardown code, so this is an easy constraint.)
+
+       gpio_direction_input()
+       gpio_direction_output()
+       gpio_request()
+
+##     gpio_request_one()
+##     gpio_request_array()
+##     gpio_free_array()
+
+       gpio_free()
+       gpio_set_debounce()
+
+
+
+Claiming and Releasing GPIOs
+----------------------------
+To help catch system configuration errors, two calls are defined.
+
+       /* request GPIO, returning 0 or negative errno.
+        * non-null labels may be useful for diagnostics.
+        */
+       int gpio_request(unsigned gpio, const char *label);
+
+       /* release previously-claimed GPIO */
+       void gpio_free(unsigned gpio);
+
+Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
+GPIOs that have already been claimed with that call.  The return value of
+gpio_request() must be checked.  You should normally issue these calls from
+a task context.  However, for spinlock-safe GPIOs it's OK to request GPIOs
+before tasking is enabled, as part of early board setup.
+
+These calls serve two basic purposes.  One is marking the signals which
+are actually in use as GPIOs, for better diagnostics; systems may have
+several hundred potential GPIOs, but often only a dozen are used on any
+given board.  Another is to catch conflicts, identifying errors when
+(a) two or more drivers wrongly think they have exclusive use of that
+signal, or (b) something wrongly believes it's safe to remove drivers
+needed to manage a signal that's in active use.  That is, requesting a
+GPIO can serve as a kind of lock.
+
+Some platforms may also use knowledge about what GPIOs are active for
+power management, such as by powering down unused chip sectors and, more
+easily, gating off unused clocks.
+
+For GPIOs that use pins known to the pinctrl subsystem, that subsystem should
+be informed of their use; a gpiolib driver's .request() operation may call
+pinctrl_request_gpio(), and a gpiolib driver's .free() operation may call
+pinctrl_free_gpio(). The pinctrl subsystem allows a pinctrl_request_gpio()
+to succeed concurrently with a pin or pingroup being "owned" by a device for
+pin multiplexing.
+
+Any programming of pin multiplexing hardware that is needed to route the
+GPIO signal to the appropriate pin should occur within a GPIO driver's
+.direction_input() or .direction_output() operations, and occur after any
+setup of an output GPIO's value. This allows a glitch-free migration from a
+pin's special function to GPIO. This is sometimes required when using a GPIO
+to implement a workaround on signals typically driven by a non-GPIO HW block.
+
+Some platforms allow some or all GPIO signals to be routed to different pins.
+Similarly, other aspects of the GPIO or pin may need to be configured, such as
+pullup/pulldown. Platform software should arrange that any such details are
+configured prior to gpio_request() being called for those GPIOs, e.g. using
+the pinctrl subsystem's mapping table, so that GPIO users need not be aware
+of these details.
+
+Also note that it's your responsibility to have stopped using a GPIO
+before you free it.
+
+Considering in most cases GPIOs are actually configured right after they
+are claimed, three additional calls are defined:
+
+       /* request a single GPIO, with initial configuration specified by
+        * 'flags', identical to gpio_request() wrt other arguments and
+        * return value
+        */
+       int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+
+       /* request multiple GPIOs in a single call
+        */
+       int gpio_request_array(struct gpio *array, size_t num);
+
+       /* release multiple GPIOs in a single call
+        */
+       void gpio_free_array(struct gpio *array, size_t num);
+
+where 'flags' is currently defined to specify the following properties:
+
+       * GPIOF_DIR_IN          - to configure direction as input
+       * GPIOF_DIR_OUT         - to configure direction as output
+
+       * GPIOF_INIT_LOW        - as output, set initial level to LOW
+       * GPIOF_INIT_HIGH       - as output, set initial level to HIGH
+       * GPIOF_OPEN_DRAIN      - gpio pin is open drain type.
+       * GPIOF_OPEN_SOURCE     - gpio pin is open source type.
+
+       * GPIOF_EXPORT_DIR_FIXED        - export gpio to sysfs, keep direction
+       * GPIOF_EXPORT_DIR_CHANGEABLE   - also export, allow changing direction
+
+since GPIOF_INIT_* are only valid when configured as output, so group valid
+combinations as:
+
+       * GPIOF_IN              - configure as input
+       * GPIOF_OUT_INIT_LOW    - configured as output, initial level LOW
+       * GPIOF_OUT_INIT_HIGH   - configured as output, initial level HIGH
+
+When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is
+open drain type. Such pins will not be driven to 1 in output mode. It is
+require to connect pull-up on such pins. By enabling this flag, gpio lib will
+make the direction to input when it is asked to set value of 1 in output mode
+to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode.
+
+When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is
+open source type. Such pins will not be driven to 0 in output mode. It is
+require to connect pull-down on such pin. By enabling this flag, gpio lib will
+make the direction to input when it is asked to set value of 0 in output mode
+to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode.
+
+In the future, these flags can be extended to support more properties.
+
+Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
+introduced to encapsulate all three fields as:
+
+       struct gpio {
+               unsigned        gpio;
+               unsigned long   flags;
+               const char      *label;
+       };
+
+A typical example of usage:
+
+       static struct gpio leds_gpios[] = {
+               { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */
+               { 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* default to OFF */
+               { 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* default to OFF */
+               { 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* default to OFF */
+               { ... },
+       };
+
+       err = gpio_request_one(31, GPIOF_IN, "Reset Button");
+       if (err)
+               ...
+
+       err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+       if (err)
+               ...
+
+       gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+
+
+GPIOs mapped to IRQs
+--------------------
+GPIO numbers are unsigned integers; so are IRQ numbers.  These make up
+two logically distinct namespaces (GPIO 0 need not use IRQ 0).  You can
+map between them using calls like:
+
+       /* map GPIO numbers to IRQ numbers */
+       int gpio_to_irq(unsigned gpio);
+
+       /* map IRQ numbers to GPIO numbers (avoid using this) */
+       int irq_to_gpio(unsigned irq);
+
+Those return either the corresponding number in the other namespace, or
+else a negative errno code if the mapping can't be done.  (For example,
+some GPIOs can't be used as IRQs.)  It is an unchecked error to use a GPIO
+number that wasn't set up as an input using gpio_direction_input(), or
+to use an IRQ number that didn't originally come from gpio_to_irq().
+
+These two mapping calls are expected to cost on the order of a single
+addition or subtraction.  They're not allowed to sleep.
+
+Non-error values returned from gpio_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.
+
+Non-error values returned from irq_to_gpio() would most commonly be used
+with gpio_get_value(), for example to initialize or update driver state
+when the IRQ is edge-triggered.  Note that some platforms don't support
+this reverse mapping, so you should avoid using it.
+
+
+Emulating Open Drain Signals
+----------------------------
+Sometimes shared signals need to use "open drain" signaling, where only the
+low signal level is actually driven.  (That term applies to CMOS transistors;
+"open collector" is used for TTL.)  A pullup resistor causes the high 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 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:  gpio_direction_output(gpio, 0) ... this drives the signal
+       and overrides the pullup.
+
+ HIGH: gpio_direction_input(gpio) ... this turns off the output,
+       so the pullup (or some other device) controls the signal.
+
+If you are "driving" the signal high but gpio_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.
+
+
+GPIO controllers and the pinctrl subsystem
+------------------------------------------
+
+A GPIO controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with an optional gpio feature. We have already covered the
+case where e.g. a GPIO controller need to reserve a pin or set the
+direction of a pin by calling any of:
+
+pinctrl_request_gpio()
+pinctrl_free_gpio()
+pinctrl_gpio_direction_input()
+pinctrl_gpio_direction_output()
+
+But how does the pin control subsystem cross-correlate the GPIO
+numbers (which are a global business) to a certain pin on a certain
+pin controller?
+
+This is done by registering "ranges" of pins, which are essentially
+cross-reference tables. These are described in
+Documentation/pinctrl.txt
+
+While the pin allocation is totally managed by the pinctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
+to request the corresponding pin to be prepared by the pinctrl subsystem
+before any gpio usage.
+
+For this, the gpio controller can register its pin range with pinctrl
+subsystem. There are two ways of doing it currently: with or without DT.
+
+For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
+
+For non-DT support, user can call gpiochip_add_pin_range() with appropriate
+parameters to register a range of gpio pins with a pinctrl driver. For this
+exact name string of pinctrl device has to be passed as one of the
+argument to this routine.
+
+
+What do these conventions omit?
+===============================
+One of the biggest things these conventions omit is pin multiplexing, since
+this is highly chip-specific and nonportable.  One platform might not need
+explicit multiplexing; another might have just two options for use of any
+given pin; another might have eight options per pin; another might be able
+to route a given GPIO to any one of several pins.  (Yes, those examples all
+come from systems that run Linux today.)
+
+Related to multiplexing is configuration and enabling of the pullups or
+pulldowns integrated on some platforms.  Not all platforms support them,
+or support them in the same way; and any given board might use external
+pullups (or pulldowns) so that the on-chip ones should not be used.
+(When a circuit needs 5 kOhm, on-chip 100 kOhm resistors won't do.)
+Likewise drive strength (2 mA vs 20 mA) and voltage (1.8V vs 3.3V) is a
+platform-specific issue, as are models like (not) having a one-to-one
+correspondence between configurable pins and GPIOs.
+
+There are other system-specific mechanisms that are not specified here,
+like the aforementioned options for input de-glitching and wire-OR output.
+Hardware may support reading or writing GPIOs in gangs, but that's usually
+configuration dependent:  for GPIOs sharing the same bank.  (GPIOs are
+commonly grouped in banks of 16 or 32, with a given SOC having several such
+banks.)  Some systems can trigger IRQs from output GPIOs, or read values
+from pins not managed as GPIOs.  Code relying on such mechanisms will
+necessarily be nonportable.
+
+Dynamic definition of GPIOs is not currently standard; for example, as
+a side effect of configuring an add-on board with some GPIO expanders.
+
+
+GPIO implementor's framework (OPTIONAL)
+=======================================
+As noted earlier, there is an optional implementation framework making it
+easier for platforms to support different kinds of GPIO controller using
+the same programming interface.  This framework is called "gpiolib".
+
+As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
+will be found there.  That will list all the controllers registered through
+this framework, and the state of the GPIOs currently in use.
+
+
+Controller Drivers: gpio_chip
+-----------------------------
+In this framework each GPIO controller is packaged as a "struct gpio_chip"
+with information common to each controller of that type:
+
+ - methods to establish GPIO direction
+ - methods used to access GPIO values
+ - flag saying whether calls to its methods may sleep
+ - optional debugfs dump method (showing extra state like pullup config)
+ - label for diagnostics
+
+There is also per-instance data, which may come from device.platform_data:
+the number of its first GPIO, and how many GPIOs it exposes.
+
+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.
+
+
+Platform Support
+----------------
+To support this framework, a platform's Kconfig will "select" either
+ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
+and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
+three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
+
+It may also provide a custom value for ARCH_NR_GPIOS, so that it better
+reflects the number of GPIOs in actual use on that platform, without
+wasting static table space.  (It should count both built-in/SoC GPIOs and
+also ones on GPIO expanders.
+
+ARCH_REQUIRE_GPIOLIB means that the gpiolib code will always get compiled
+into the kernel on that architecture.
+
+ARCH_WANT_OPTIONAL_GPIOLIB means the gpiolib code defaults to off and the user
+can enable it and build it into the kernel optionally.
+
+If neither of these options are selected, the platform does not support
+GPIOs through GPIO-lib and the code cannot be enabled by the user.
+
+Trivial implementations of those functions can directly use framework
+code, which always dispatches through the gpio_chip:
+
+  #define gpio_get_value       __gpio_get_value
+  #define gpio_set_value       __gpio_set_value
+  #define gpio_cansleep                __gpio_cansleep
+
+Fancier implementations could instead define those as inline functions with
+logic optimizing access to specific SOC-based GPIOs.  For example, if the
+referenced GPIO is the constant "12", getting or setting its value could
+cost as little as two or three instructions, never sleeping.  When such an
+optimization is not possible those calls must delegate to the framework
+code, costing at least a few dozen instructions.  For bitbanged I/O, such
+instruction savings can be significant.
+
+For SOCs, platform-specific code defines and registers gpio_chip instances
+for each bank of on-chip GPIOs.  Those GPIOs should be numbered/labeled to
+match chip vendor documentation, and directly match board schematics.  They
+may well start at zero and go up to a platform-specific limit.  Such GPIOs
+are normally integrated into platform initialization to make them always be
+available, from arch_initcall() or earlier; they can often serve as IRQs.
+
+
+Board Support
+-------------
+For external GPIO controllers -- such as I2C or SPI expanders, ASICs, multi
+function devices, FPGAs or CPLDs -- most often board-specific code handles
+registering controller devices and ensures that their drivers know what GPIO
+numbers to use with gpiochip_add().  Their numbers often start right after
+platform-specific GPIOs.
+
+For example, board setup code could create structures identifying the range
+of GPIOs that chip will expose, and passes them to each GPIO expander chip
+using platform_data.  Then the chip driver's probe() routine could pass that
+data to gpiochip_add().
+
+Initialization order can be important.  For example, when a device relies on
+an I2C-based GPIO, its probe() routine should only be called after that GPIO
+becomes available.  That may mean the device should not be registered until
+calls for that GPIO can work.  One way to address such dependencies is for
+such gpio_chip controllers to provide setup() and teardown() callbacks to
+board specific code; those board specific callbacks would register devices
+once all the necessary resources are available, and remove them later when
+the GPIO controller device becomes unavailable.
+
+
+Sysfs Interface for Userspace (OPTIONAL)
+========================================
+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 gpio_export(unsigned gpio, bool direction_may_change);
+
+       /* reverse gpio_export() */
+       void gpio_unexport();
+
+       /* create a sysfs link to an exported GPIO node */
+       int gpio_export_link(struct device *dev, const char *name,
+               unsigned gpio)
+
+       /* change the polarity of a GPIO node in sysfs */
+       int gpio_sysfs_set_active_low(unsigned gpio, int value);
+
+After a kernel driver requests a GPIO, it may only be made available in
+the sysfs interface by gpio_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, gpio_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 gpio_sysfs_set_active_low() to hide GPIO line polarity
+differences between boards from user space.  This only affects the
+sysfs interface.  Polarity change can be done both before and after
+gpio_export(), and previously enabled poll(2) support for either
+rising or falling edge will be reconfigured to follow this setting.
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 f21edb9834137ac91a9d1e6789c612ef07deb8c1..f72e0d1e0da852ac3e89e97f8bd0c22055d66608 100644 (file)
@@ -34,7 +34,7 @@ SPI slave functions are usually not interoperable between vendors
   - It may also be used to stream data in either direction (half duplex),
     or both of them at the same time (full duplex).
 
-  - Some devices may use eight bit words.  Others may different word
+  - Some devices may use eight bit words.  Others may use different word
     lengths, such as streams of 12-bit or 20-bit digital samples.
 
   - Words are usually sent with their most significant bit (MSB) first,
@@ -121,7 +121,7 @@ active.  So the master must set the clock to inactive before selecting
 a slave, and the slave can tell the chosen polarity by sampling the
 clock level when its select line goes active.  That's why many devices
 support for example both modes 0 and 3:  they don't care about polarity,
-and alway clock data in/out on rising clock edges.
+and always clock data in/out on rising clock edges.
 
 
 How do these driver programming interfaces work?
@@ -139,7 +139,7 @@ a command and then reading its response.
 
 There are two types of SPI driver, here called:
 
-  Controller drivers ... controllers may be built in to System-On-Chip
+  Controller drivers ... controllers may be built into System-On-Chip
        processors, and often support both Master and Slave roles.
        These drivers touch hardware registers and may use DMA.
        Or they can be PIO bitbangers, needing just GPIO pins.
@@ -548,7 +548,7 @@ SPI MASTER METHODS
     DEPRECATED METHODS
 
     master->transfer(struct spi_device *spi, struct spi_message *message)
-       This must not sleep. Its responsibility is arrange that the
+       This must not sleep. Its responsibility is to arrange that the
        transfer happens and its complete() callback is issued. The two
        will normally happen later, after other transfers complete, and
        if the controller is idle it will need to be kickstarted. This
index 8285ed4676b6388502be84ddde71d1e201827ce8..31a046213274e06e63e26da0514ede7ebc7c4443 100644 (file)
@@ -783,7 +783,7 @@ F:  arch/arm/boot/dts/sama*.dts
 F:     arch/arm/boot/dts/sama*.dtsi
 
 ARM/CALXEDA HIGHBANK ARCHITECTURE
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-highbank/
@@ -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>
@@ -1371,6 +1368,9 @@ T:        git git://git.xilinx.com/linux-xlnx.git
 S:     Supported
 F:     arch/arm/mach-zynq/
 F:     drivers/cpuidle/cpuidle-zynq.c
+N:     zynq
+N:     xilinx
+F:     drivers/clocksource/cadence_ttc_timer.c
 
 ARM SMMU DRIVER
 M:     Will Deacon <will.deacon@arm.com>
@@ -1934,7 +1934,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 +2138,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>
@@ -2821,8 +2828,10 @@ F:       include/uapi/drm/
 
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
+M:     Jani Nikula <jani.nikula@linux.intel.com>
 L:     intel-gfx@lists.freedesktop.org
 L:     dri-devel@lists.freedesktop.org
+Q:     http://patchwork.freedesktop.org/project/intel-gfx/
 T:     git git://people.freedesktop.org/~danvet/drm-intel
 S:     Supported
 F:     drivers/gpu/drm/i915/
@@ -3759,9 +3768,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 +3840,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 +4055,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 +4481,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 +5285,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 +5926,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 +6006,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/
@@ -6223,7 +6261,7 @@ F:        drivers/i2c/busses/i2c-ocores.c
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -6235,11 +6273,11 @@ K:      of_get_property
 K:     of_match_table
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 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 +6487,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 +7451,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 +9595,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..eeec740776f3548d2ffa871b52d34a881e2f77e4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc8
 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 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 9db5047812f3d6c05a36643abbea0e1fb33e8195..177becde7a268bdcee91be7b049567d17daf9809 100644 (file)
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x10800000 0x1000>;
                        interrupts = <0 33 0>;
-                       clocks = <&clock 271>;
+                       clocks = <&clock 346>;
                        clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
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 64205d453260d12ec1e2d43c424fab1c3251788a..71e5fc7cfb18f489f3adadb20c6f8049421fb079 100644 (file)
@@ -58,7 +58,7 @@
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index f3d96d9325737fba399dc5e6613d223e03fcb7a1..be068db960ee0006ac1aa25a4e69b95265404844 100644 (file)
@@ -701,7 +701,7 @@ $code.=<<___;
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index 3c597c222ef278a8eb170a4169b5e54dcc158ac0..fbeb39c869e9fdcedace1d61688247c14141cab3 100644 (file)
@@ -329,7 +329,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  */
 #define ioremap(cookie,size)           __arm_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_cache(cookie,size)     __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)                __arm_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap                                __arm_iounmap
 
index 9ecccc865046a2c257277cd03a8f607ed5e0217d..8756e4bcdba0609ff789a4f1efaa551faa39ed98 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
@@ -350,7 +347,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
 #define ARCH_PFN_OFFSET                PHYS_PFN_OFFSET
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+#define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \
+                                       && pfn_valid(__pa(kaddr) >> PAGE_SHIFT) )
 
 #endif
 
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 75579a9d6f76cba3cc84ad61d01ed103269378bd..3759cacdd7f8601322b98ffed6598d97ee8bd016 100644 (file)
@@ -117,6 +117,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
        return __set_phys_to_machine(pfn, mfn);
 }
 
-#define xen_remap(cookie, size) ioremap_cached((cookie), (size));
+#define xen_remap(cookie, size) ioremap_cache((cookie), (size));
 
 #endif /* _ASM_ARM_XEN_PAGE_H */
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..6eda3bf85c52123dc75fb04fe46f0eb197c78d62 100644 (file)
 #include <asm/system_misc.h>
 #include <asm/opcodes.h>
 
-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+static const char *handler[]= {
+       "prefetch abort",
+       "data abort",
+       "address exception",
+       "interrupt",
+       "undefined instruction",
+};
 
 void *vectors_page;
 
@@ -509,9 +515,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 9ee78f7b4990751386cf7f29337ec075297349dd..782f6c71fa0a6c761269cfc4b74fc6cdd0839e75 100644 (file)
@@ -96,11 +96,12 @@ static struct irqaction footbridge_timer_irq = {
 void __init footbridge_timer_init(void)
 {
        struct clock_event_device *ce = &ckevt_dc21285;
+       unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
 
-       clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
+       clocksource_register_hz(&cksrc_dc21285, rate);
 
        setup_irq(ce->irq, &footbridge_timer_irq);
 
        ce->cpumask = cpumask_of(smp_processor_id());
-       clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
+       clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
 }
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 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
index 958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8..8ea87bd45c330abd37df9eba0b30b8f4efc8dc47 100644 (file)
@@ -483,7 +483,7 @@ static struct platform_device lcdc0_device = {
        .id             = 0,
        .dev    = {
                .platform_data  = &lcdc0_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -580,7 +580,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -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 fe689b7fdc9e715ecd724edcc746913010627fb4..bc40b853ffd3cff2204bdfdc283863a9577f51bc 100644 (file)
@@ -334,7 +334,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
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 af06753eb8092500de41707ac68216bd3ed244a0..e721d2ccceaef8c1d57bd0d671fa097a2c0f539a 100644 (file)
@@ -409,7 +409,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -499,7 +499,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
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 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 6d5ba9afb16a4409d50dbdbc03d08c83642df9b4..3387e60e4ea381c579725774ebab8d587eeded0c 100644 (file)
@@ -175,16 +175,16 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
                unsigned long i;
                if (cache_is_vipt_nonaliasing()) {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_atomic(page);
+                               void *addr = kmap_atomic(page + i);
                                __cpuc_flush_dcache_area(addr, PAGE_SIZE);
                                kunmap_atomic(addr);
                        }
                } else {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_high_get(page);
+                               void *addr = kmap_high_get(page + i);
                                if (addr) {
                                        __cpuc_flush_dcache_area(addr, PAGE_SIZE);
-                                       kunmap_high(page);
+                                       kunmap_high(page + i);
                                }
                        }
                }
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 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 f0e2784e7ccacd6c6d0856ce87d1f1d26e81c083..2f9b751878ba86bf6cc32cfdadd9b7847ad158d5 100644 (file)
@@ -125,42 +125,38 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma
 void mark_rodata_ro(void);
 #endif
 
-#ifdef CONFIG_PA8X00
-/* Only pa8800, pa8900 needs this */
-
 #include <asm/kmap_types.h>
 
 #define ARCH_HAS_KMAP
 
-void kunmap_parisc(void *addr);
-
 static inline void *kmap(struct page *page)
 {
        might_sleep();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void kunmap(struct page *page)
 {
-       kunmap_parisc(page_address(page));
+       flush_kernel_dcache_page_addr(page_address(page));
 }
 
 static inline void *kmap_atomic(struct page *page)
 {
        pagefault_disable();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void __kunmap_atomic(void *addr)
 {
-       kunmap_parisc(addr);
+       flush_kernel_dcache_page_addr(addr);
        pagefault_enable();
 }
 
 #define kmap_atomic_prot(page, prot)   kmap_atomic(page)
 #define kmap_atomic_pfn(pfn)   kmap_atomic(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
-#endif
 
 #endif /* _PARISC_CACHEFLUSH_H */
 
index b7adb2ac049c0e6b72817dee3df92d124c612e42..c53fc63149e8312437fe4109e8070495ba39d90a 100644 (file)
@@ -28,9 +28,8 @@ struct page;
 
 void clear_page_asm(void *page);
 void copy_page_asm(void *to, void *from);
-void clear_user_page(void *vto, unsigned long vaddr, struct page *pg);
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-                          struct page *pg);
+#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
+#define copy_user_page(vto, vfrom, vaddr, page) copy_page_asm(vto, vfrom)
 
 /* #define CONFIG_PARISC_TMPALIAS */
 
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 c035673209f732f0850aaa4dc98d2d49eee3b74c..a72545554a3154c254eace0648a769d4df645b25 100644 (file)
@@ -388,41 +388,6 @@ void flush_kernel_dcache_page_addr(void *addr)
 }
 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
 
-void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
-{
-       clear_page_asm(vto);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(clear_user_page);
-
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-       struct page *pg)
-{
-       /* Copy using kernel mapping.  No coherency is needed
-          (all in kmap/kunmap) on machines that don't support
-          non-equivalent aliasing.  However, the `from' page
-          needs to be flushed before it can be accessed through
-          the kernel mapping. */
-       preempt_disable();
-       flush_dcache_page_asm(__pa(vfrom), vaddr);
-       preempt_enable();
-       copy_page_asm(vto, vfrom);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(copy_user_page);
-
-#ifdef CONFIG_PA8X00
-
-void kunmap_parisc(void *addr)
-{
-       if (parisc_requires_coherency())
-               flush_kernel_dcache_page_addr(addr);
-}
-EXPORT_SYMBOL(kunmap_parisc);
-#endif
-
 void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 {
        unsigned long flags;
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 4177b62240c2440ff19f6089cb84cd5b9e0d27a0..a618dfc13e4c8f88a5ff70b88325fd39675c9e8a 100644 (file)
@@ -58,7 +58,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
                        reg = <0xA000 0x1000>;
                };
 
+               // disable USB1 port
+               // TODO:
+               // correct pinmux config and fix USB3320 ulpi dependency
+               // before re-enabling it
                usb@3000 {
                        compatible = "fsl,mpc5121-usb2-dr";
                        reg = <0x3000 0x400>;
                        interrupts = <43 0x8>;
                        dr_mode = "host";
                        phy_type = "ulpi";
+                       status = "disabled";
                };
 
                // 5125 PSCs are not 52xx or 5121 PSC compatible
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 894662a5d4d5c5aa25f43e30653609d80d901774..243ce69ad685ffd335041537e6f0b33b0aafe3df 100644 (file)
@@ -284,7 +284,7 @@ do_kvm_##n:                                                         \
        subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
        beq-    1f;                                                        \
        ld      r1,PACAKSAVE(r13);      /* kernel stack to use          */ \
-1:     cmpdi   cr1,r1,0;               /* check if r1 is in userspace  */ \
+1:     cmpdi   cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace  */ \
        blt+    cr1,3f;                 /* abort if it is               */ \
        li      r1,(n);                 /* will be reloaded later       */ \
        sth     r1,PACA_TRAP_SAVE(r13);                                    \
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 5f1b1e3c21374d5a1833ed00c9af9d5c06a35123..8296381ae43294e679976f6a82d3bb936d64921f 100644 (file)
@@ -4,13 +4,18 @@
 #ifdef __KERNEL__
 
 /*
- * The PowerPC can do unaligned accesses itself in big endian mode.
+ * The PowerPC can do unaligned accesses itself based on its endian mode.
  */
 #include <linux/unaligned/access_ok.h>
 #include <linux/unaligned/generic.h>
 
+#ifdef __LITTLE_ENDIAN__
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
+#else
 #define get_unaligned  __get_unaligned_be
 #define put_unaligned  __put_unaligned_be
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UNALIGNED_H */
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 2ae41aba40530f7facf916f6ce101ad3196a7363..4f0946de2d5c917540f6f51a50c13640011fea8c 100644 (file)
@@ -80,6 +80,7 @@ END_FTR_SECTION(0, 1)
         * of the function that the cpu should jump to to continue
         * initialization.
         */
+       .balign 8
        .globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
        .llong  0x0
@@ -470,6 +471,7 @@ _STATIC(__after_prom_start)
        mtctr   r8
        bctr
 
+.balign 8
 p_end: .llong  _end - _stext
 
 4:     /* Now copy the rest of the kernel up to _end */
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 d73a5901490018486fed19115fce46d88084f701..596a285c07554d65dfd561367a52ffed47aba55d 100644 (file)
@@ -9,6 +9,14 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 
+#ifdef __BIG_ENDIAN__
+#define sLd sld                /* Shift towards low-numbered address. */
+#define sHd srd                /* Shift towards high-numbered address. */
+#else
+#define sLd srd                /* Shift towards low-numbered address. */
+#define sHd sld                /* Shift towards high-numbered address. */
+#endif
+
        .align  7
 _GLOBAL(__copy_tofrom_user)
 BEGIN_FTR_SECTION
@@ -118,10 +126,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 24:    ld      r9,0(r4)        /* 3+2n loads, 2+2n stores */
 25:    ld      r0,8(r4)
-       sld     r6,r9,r10
+       sLd     r6,r9,r10
 26:    ldu     r9,16(r4)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        or      r7,r7,r6
        blt     cr6,79f
 27:    ld      r0,8(r4)
@@ -129,35 +137,35 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 28:    ld      r0,0(r4)        /* 4+2n loads, 3+2n stores */
 29:    ldu     r9,8(r4)
-       sld     r8,r0,r10
+       sLd     r8,r0,r10
        addi    r3,r3,-8
        blt     cr6,5f
 30:    ld      r0,8(r4)
-       srd     r12,r9,r11
-       sld     r6,r9,r10
+       sHd     r12,r9,r11
+       sLd     r6,r9,r10
 31:    ldu     r9,16(r4)
        or      r12,r8,r12
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        addi    r3,r3,16
        beq     cr6,78f
 
 1:     or      r7,r7,r6
 32:    ld      r0,8(r4)
 76:    std     r12,8(r3)
-2:     srd     r12,r9,r11
-       sld     r6,r9,r10
+2:     sHd     r12,r9,r11
+       sLd     r6,r9,r10
 33:    ldu     r9,16(r4)
        or      r12,r8,r12
 77:    stdu    r7,16(r3)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        bdnz    1b
 
 78:    std     r12,8(r3)
        or      r7,r7,r6
 79:    std     r7,16(r3)
-5:     srd     r12,r9,r11
+5:     sHd     r12,r9,r11
        or      r12,r8,r12
 80:    std     r12,24(r3)
        bne     6f
@@ -165,23 +173,38 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        blr
 6:     cmpwi   cr1,r5,8
        addi    r3,r3,32
-       sld     r9,r9,r10
+       sLd     r9,r9,r10
        ble     cr1,7f
 34:    ld      r0,8(r4)
-       srd     r7,r0,r11
+       sHd     r7,r0,r11
        or      r9,r7,r9
 7:
        bf      cr7*4+1,1f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,32
+#endif
 94:    stw     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,32
+#endif
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,16
+#endif
 95:    sth     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,16
+#endif
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,8
+#endif
 96:    stb     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,8
+#endif
 3:     li      r3,0
        blr
 
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 02245cee78183852d52f3a907023dcd9a63529bf..d7ddcee7feb8bc8084d18be32f348263c8de6e0e 100644 (file)
@@ -36,7 +36,6 @@
 #include "powernv.h"
 #include "pci.h"
 
-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;
 
 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
                ioda_eeh_nb_init = 1;
        }
 
-       /* We needn't HUB diag-data on PHB3 */
-       if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
-               hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-               if (!hub_diag) {
-                       pr_err("%s: Out of memory !\n", __func__);
-                       return -ENOMEM;
-               }
-       }
-
 #ifdef CONFIG_DEBUG_FS
        if (phb->dbgfs) {
                debugfs_create_file("err_injct_outbound", 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoP7IOCErrorData *data;
+       struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
        long rc;
 
-       data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
+       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
                           __func__, phb->hub_id, rc);
@@ -820,14 +809,15 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose)
        struct OpalIoPhbErrorCommon *common;
        long rc;
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, common, PAGE_SIZE);
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
                            __func__, hose->global_number, rc);
                return;
        }
 
+       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
        switch (common->ioType) {
        case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
                ioda_eeh_p7ioc_phb_diag(hose, common);
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 911c24ef033e0ae207036e5d5cab8bceaf07e14a..1ed8d5f40f5ad1423f78c9ae7fdac42abac4376d 100644 (file)
@@ -172,11 +172,13 @@ struct pnv_phb {
                } ioda;
        };
 
-       /* PHB status structure */
+       /* PHB and hub status structure */
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoP7IOCErrorData     hub_diag;
        } diag;
+
 };
 
 extern struct pci_ops pnv_pci_ops;
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..e9f3125325266ff8b93f13c009003d3d4aa335de 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
@@ -135,7 +135,6 @@ config S390
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16 if 32BIT
        select HAVE_VIRT_CPU_ACCOUNTING
-       select INIT_ALL_POSSIBLE
        select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
        select OLD_SIGACTION
@@ -347,14 +346,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 ac9bed8e103fa741f85b3aecc64fcc9a18511c82..16077939409622fc946b943f4556d91cc272211c 100644 (file)
@@ -31,6 +31,7 @@ extern void smp_yield(void);
 extern void smp_stop_cpu(void);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
+extern void smp_fill_possible_mask(void);
 
 #else /* CONFIG_SMP */
 
@@ -50,6 +51,7 @@ static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_yield(void) { }
 static inline void smp_stop_cpu(void) { }
+static inline void smp_fill_possible_mask(void) { }
 
 #endif /* CONFIG_SMP */
 
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 4444875266ee028bdcc4d43604a4dea591a1a47c..0f3d44ecbfc6d5cd66541a0fe4c651acdf6a8336 100644 (file)
@@ -1023,6 +1023,7 @@ void __init setup_arch(char **cmdline_p)
        setup_vmcoreinfo();
        setup_lowcore();
 
+       smp_fill_possible_mask();
         cpu_init();
        s390_init_cpu_topology();
 
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 dc4a534650604a972967ab5dedd2c1b7155c29ad..958704798f4a8e91ff898149b8d6379a39cede13 100644 (file)
@@ -721,18 +721,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
        return 0;
 }
 
-static int __init setup_possible_cpus(char *s)
-{
-       int max, cpu;
+static unsigned int setup_possible_cpus __initdata;
 
-       if (kstrtoint(s, 0, &max) < 0)
-               return 0;
-       init_cpu_possible(cpumask_of(0));
-       for (cpu = 1; cpu < max && cpu < nr_cpu_ids; cpu++)
-               set_cpu_possible(cpu, true);
+static int __init _setup_possible_cpus(char *s)
+{
+       get_option(&s, &setup_possible_cpus);
        return 0;
 }
-early_param("possible_cpus", setup_possible_cpus);
+early_param("possible_cpus", _setup_possible_cpus);
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -775,6 +771,17 @@ void __noreturn cpu_die(void)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+void __init smp_fill_possible_mask(void)
+{
+       unsigned int possible, cpu;
+
+       possible = setup_possible_cpus;
+       if (!possible)
+               possible = MACHINE_IS_VM ? 64 : nr_cpu_ids;
+       for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++)
+               set_cpu_possible(cpu, true);
+}
+
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        /* request the 0x1201 emergency signal external interrupt */
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 800f064b0da7c9a32c3910ecefdfb3e6979d7f9b..069607209a3075c6f4ff2c62fe91b7eb1d99c8aa 100644 (file)
@@ -75,6 +75,7 @@ void zpci_event_availability(void *data)
                if (!zdev || zdev->state == ZPCI_FN_STATE_CONFIGURED)
                        break;
                zdev->state = ZPCI_FN_STATE_CONFIGURED;
+               zdev->fh = ccdf->fh;
                ret = zpci_enable_device(zdev);
                if (ret)
                        break;
@@ -101,6 +102,7 @@ void zpci_event_availability(void *data)
                if (pdev)
                        pci_stop_and_remove_bus_device(pdev);
 
+               zdev->fh = ccdf->fh;
                zpci_disable_device(zdev);
                zdev->state = ZPCI_FN_STATE_STANDBY;
                break;
index 2a0a596ebf67d948663df3009d1ca14c8b09dabc..d77f2f6c7ff0761de1b51f09eb8926923c817681 100644 (file)
@@ -20,6 +20,11 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(empty_zero_page);
+#ifdef CONFIG_FLATMEM
+/* need in pfn_valid macro */
+EXPORT_SYMBOL(min_low_pfn);
+EXPORT_SYMBOL(max_low_pfn);
+#endif
 
 #define DECLARE_EXPORT(name)           \
        extern void name(void);EXPORT_SYMBOL(name)
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 e562d3caee57457a3b188f13b2959d47a7f835b4..ad7e178337f12f2f753f66ec2a9c26dae65c9f68 100644 (file)
@@ -262,8 +262,8 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long);
 extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
-#define __copy_to_user_inatomic ___copy_to_user
-#define __copy_from_user_inatomic ___copy_from_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 struct pt_regs;
 extern unsigned long compute_effective_address(struct pt_regs *,
index 070ed141aac79728da15f406289219a9c385fe27..76663b019eb5207f389655dac5133afce6e553aa 100644 (file)
@@ -854,7 +854,7 @@ int dma_supported(struct device *dev, u64 device_mask)
                return 1;
 
 #ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return pci64_dma_supported(to_pci_dev(dev), device_mask);
 #endif
 
index 2096468de9b27f7dd2bb54f17e3b308f8d359836..e7e215dfa86668750c9490331d94b288ab78857c 100644 (file)
@@ -666,10 +666,9 @@ EXPORT_SYMBOL(dma_ops);
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-#ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return 1;
-#endif
+
        return 0;
 }
 EXPORT_SYMBOL(dma_supported);
index 60b19f50c80a8f9d7f31b4b4105ed4fcded6a5ca..b45fe3fb4d2cfbc7999d34a1b25baf9bc0278c2e 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
 #include <linux/ftrace.h>
+#include <linux/context_tracking.h>
 
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
index b66a5338231e965252fef5f23234141bb2fc8f85..b085311dcd0ea9f81840e1fc2550c4f870e984eb 100644 (file)
@@ -123,11 +123,12 @@ void smp_callin(void)
                rmb();
 
        set_cpu_online(cpuid, true);
-       local_irq_enable();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
 
+       local_irq_enable();
+
        cpu_startup_entry(CPUHP_ONLINE);
 }
 
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
diff --git a/arch/x86/crypto/ablk_helper.c b/arch/x86/crypto/ablk_helper.c
deleted file mode 100644 (file)
index 43282fe..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Shared async block cipher helpers
- *
- * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
- *
- * Based on aesni-intel_glue.c by:
- *  Copyright (C) 2008, Intel Corp.
- *    Author: Huang Ying <ying.huang@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
- * USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/crypto.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <crypto/algapi.h>
-#include <crypto/cryptd.h>
-#include <asm/i387.h>
-#include <asm/crypto/ablk_helper.h>
-
-int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
-                unsigned int key_len)
-{
-       struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
-       struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base;
-       int err;
-
-       crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-       crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm)
-                                   & CRYPTO_TFM_REQ_MASK);
-       err = crypto_ablkcipher_setkey(child, key, key_len);
-       crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child)
-                                   & CRYPTO_TFM_RES_MASK);
-       return err;
-}
-EXPORT_SYMBOL_GPL(ablk_set_key);
-
-int __ablk_encrypt(struct ablkcipher_request *req)
-{
-       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
-       struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
-       struct blkcipher_desc desc;
-
-       desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
-       desc.info = req->info;
-       desc.flags = 0;
-
-       return crypto_blkcipher_crt(desc.tfm)->encrypt(
-               &desc, req->dst, req->src, req->nbytes);
-}
-EXPORT_SYMBOL_GPL(__ablk_encrypt);
-
-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()) {
-               struct ablkcipher_request *cryptd_req =
-                       ablkcipher_request_ctx(req);
-
-               memcpy(cryptd_req, req, sizeof(*req));
-               ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
-
-               return crypto_ablkcipher_encrypt(cryptd_req);
-       } else {
-               return __ablk_encrypt(req);
-       }
-}
-EXPORT_SYMBOL_GPL(ablk_encrypt);
-
-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()) {
-               struct ablkcipher_request *cryptd_req =
-                       ablkcipher_request_ctx(req);
-
-               memcpy(cryptd_req, req, sizeof(*req));
-               ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
-
-               return crypto_ablkcipher_decrypt(cryptd_req);
-       } else {
-               struct blkcipher_desc desc;
-
-               desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
-               desc.info = req->info;
-               desc.flags = 0;
-
-               return crypto_blkcipher_crt(desc.tfm)->decrypt(
-                       &desc, req->dst, req->src, req->nbytes);
-       }
-}
-EXPORT_SYMBOL_GPL(ablk_decrypt);
-
-void ablk_exit(struct crypto_tfm *tfm)
-{
-       struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       cryptd_free_ablkcipher(ctx->cryptd_tfm);
-}
-EXPORT_SYMBOL_GPL(ablk_exit);
-
-int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name)
-{
-       struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct cryptd_ablkcipher *cryptd_tfm;
-
-       cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0);
-       if (IS_ERR(cryptd_tfm))
-               return PTR_ERR(cryptd_tfm);
-
-       ctx->cryptd_tfm = cryptd_tfm;
-       tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
-               crypto_ablkcipher_reqsize(&cryptd_tfm->base);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ablk_init_common);
-
-int ablk_init(struct crypto_tfm *tfm)
-{
-       char drv_name[CRYPTO_MAX_ALG_NAME];
-
-       snprintf(drv_name, sizeof(drv_name), "__driver-%s",
-                                       crypto_tfm_alg_driver_name(tfm));
-
-       return ablk_init_common(tfm, drv_name);
-}
-EXPORT_SYMBOL_GPL(ablk_init);
-
-MODULE_LICENSE("GPL");
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)
diff --git a/arch/x86/include/asm/crypto/ablk_helper.h b/arch/x86/include/asm/crypto/ablk_helper.h
deleted file mode 100644 (file)
index 4f93df5..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Shared async block cipher helpers
- */
-
-#ifndef _CRYPTO_ABLK_HELPER_H
-#define _CRYPTO_ABLK_HELPER_H
-
-#include <linux/crypto.h>
-#include <linux/kernel.h>
-#include <crypto/cryptd.h>
-
-struct async_helper_ctx {
-       struct cryptd_ablkcipher *cryptd_tfm;
-};
-
-extern int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
-                       unsigned int key_len);
-
-extern int __ablk_encrypt(struct ablkcipher_request *req);
-
-extern int ablk_encrypt(struct ablkcipher_request *req);
-
-extern int ablk_decrypt(struct ablkcipher_request *req);
-
-extern void ablk_exit(struct crypto_tfm *tfm);
-
-extern int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name);
-
-extern int ablk_init(struct crypto_tfm *tfm);
-
-#endif /* _CRYPTO_ABLK_HELPER_H */
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..1673940cf9c35169d808a71ef31c031d5c8a390d 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);
@@ -1346,6 +1350,10 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                return;
        }
 
+       if (!kvm_vcpu_is_bsp(apic->vcpu))
+               value &= ~MSR_IA32_APICBASE_BSP;
+       vcpu->arch.apic_base = value;
+
        /* update jump label if enable bit changes */
        if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
                if (value & MSR_IA32_APICBASE_ENABLE)
@@ -1355,10 +1363,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                recalculate_apic_map(vcpu->kvm);
        }
 
-       if (!kvm_vcpu_is_bsp(apic->vcpu))
-               value &= ~MSR_IA32_APICBASE_BSP;
-
-       vcpu->arch.apic_base = value;
        if ((old_value ^ value) & X2APIC_ENABLE) {
                if (value & X2APIC_ENABLE) {
                        u32 id = kvm_apic_id(apic);
@@ -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 b2fe1c252f35f92e3b6707406998738a9275c8d2..da7837e1349da8ac4ac06468fb2f05e798e136f1 100644 (file)
@@ -8283,8 +8283,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
        kvm_set_cr4(vcpu, vmcs12->host_cr4);
 
-       if (nested_cpu_has_ept(vmcs12))
-               nested_ept_uninit_mmu_context(vcpu);
+       nested_ept_uninit_mmu_context(vcpu);
 
        kvm_set_cr3(vcpu, vmcs12->host_cr3);
        kvm_mmu_reset_context(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
diff --git a/crypto/ablk_helper.c b/crypto/ablk_helper.c
new file mode 100644 (file)
index 0000000..ffe7278
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Shared async block cipher helpers
+ *
+ * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * Based on aesni-intel_glue.c by:
+ *  Copyright (C) 2008, Intel Corp.
+ *    Author: Huang Ying <ying.huang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <linux/kernel.h>
+#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 <crypto/ablk_helper.h>
+#include <asm/simd.h>
+
+int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
+                unsigned int key_len)
+{
+       struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+       struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base;
+       int err;
+
+       crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+       crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm)
+                                   & CRYPTO_TFM_REQ_MASK);
+       err = crypto_ablkcipher_setkey(child, key, key_len);
+       crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child)
+                                   & CRYPTO_TFM_RES_MASK);
+       return err;
+}
+EXPORT_SYMBOL_GPL(ablk_set_key);
+
+int __ablk_encrypt(struct ablkcipher_request *req)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+       struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+       struct blkcipher_desc desc;
+
+       desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
+       desc.info = req->info;
+       desc.flags = 0;
+
+       return crypto_blkcipher_crt(desc.tfm)->encrypt(
+               &desc, req->dst, req->src, req->nbytes);
+}
+EXPORT_SYMBOL_GPL(__ablk_encrypt);
+
+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 (!may_use_simd()) {
+               struct ablkcipher_request *cryptd_req =
+                       ablkcipher_request_ctx(req);
+
+               *cryptd_req = *req;
+               ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
+
+               return crypto_ablkcipher_encrypt(cryptd_req);
+       } else {
+               return __ablk_encrypt(req);
+       }
+}
+EXPORT_SYMBOL_GPL(ablk_encrypt);
+
+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 (!may_use_simd()) {
+               struct ablkcipher_request *cryptd_req =
+                       ablkcipher_request_ctx(req);
+
+               *cryptd_req = *req;
+               ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
+
+               return crypto_ablkcipher_decrypt(cryptd_req);
+       } else {
+               struct blkcipher_desc desc;
+
+               desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
+               desc.info = req->info;
+               desc.flags = 0;
+
+               return crypto_blkcipher_crt(desc.tfm)->decrypt(
+                       &desc, req->dst, req->src, req->nbytes);
+       }
+}
+EXPORT_SYMBOL_GPL(ablk_decrypt);
+
+void ablk_exit(struct crypto_tfm *tfm)
+{
+       struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       cryptd_free_ablkcipher(ctx->cryptd_tfm);
+}
+EXPORT_SYMBOL_GPL(ablk_exit);
+
+int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name)
+{
+       struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct cryptd_ablkcipher *cryptd_tfm;
+
+       cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0);
+       if (IS_ERR(cryptd_tfm))
+               return PTR_ERR(cryptd_tfm);
+
+       ctx->cryptd_tfm = cryptd_tfm;
+       tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
+               crypto_ablkcipher_reqsize(&cryptd_tfm->base);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ablk_init_common);
+
+int ablk_init(struct crypto_tfm *tfm)
+{
+       char drv_name[CRYPTO_MAX_ALG_NAME];
+
+       snprintf(drv_name, sizeof(drv_name), "__driver-%s",
+                                       crypto_tfm_alg_driver_name(tfm));
+
+       return ablk_init_common(tfm, drv_name);
+}
+EXPORT_SYMBOL_GPL(ablk_init);
+
+MODULE_LICENSE("GPL");
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 8711e3797165fa73fd0c401cedbb54c61eb68e4a..3c2e4aa529c479e92090c8862deaadcf0a8645e5 100644 (file)
@@ -207,7 +207,7 @@ static int acpi_ac_probe(struct platform_device *pdev)
                goto end;
 
        result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac);
        if (result) {
                power_supply_unregister(&ac->charger);
                goto end;
@@ -255,7 +255,7 @@ static int acpi_ac_remove(struct platform_device *pdev)
                return -EINVAL;
 
        acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler);
 
        ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
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 fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68..5876a49dfd386a4653325d99fcc69aa8452b12e1 100644 (file)
@@ -62,6 +62,7 @@ MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
 MODULE_DESCRIPTION("ACPI Battery Driver");
 MODULE_LICENSE("GPL");
 
+static int battery_bix_broken_package;
 static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -416,7 +417,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
                return -ENODEV;
        }
-       if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+
+       if (battery_bix_broken_package)
+               result = extract_package(battery, buffer.pointer,
+                               extended_info_offsets + 1,
+                               ARRAY_SIZE(extended_info_offsets) - 1);
+       else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
                result = extract_package(battery, buffer.pointer,
                                extended_info_offsets,
                                ARRAY_SIZE(extended_info_offsets));
@@ -754,6 +760,17 @@ static int battery_notify(struct notifier_block *nb,
        return 0;
 }
 
+static struct dmi_system_id bat_dmi_table[] = {
+       {
+               .ident = "NEC LZ750/LS",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
+               },
+       },
+       {},
+};
+
 static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
@@ -846,6 +863,9 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 {
        if (acpi_disabled)
                return;
+
+       if (dmi_check_system(bat_dmi_table))
+               battery_bix_broken_package = 1;
        acpi_bus_register_driver(&acpi_battery_driver);
 }
 
index bba9b72e25f8235e6d12593bdd16bb378c7af25a..0710004055c809f3059cde2337373503666fd96f 100644 (file)
@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data)
 }
 EXPORT_SYMBOL(acpi_bus_get_private_data);
 
+void acpi_bus_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       if (adev)
+               adev->flags.no_hotplug = true;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
+
 static void acpi_print_osc_error(acpi_handle handle,
        struct acpi_osc_context *context, char *error)
 {
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..e3a92a6da39ae258cf9a4094f4293799e378271b 100644 (file)
@@ -427,6 +427,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
+                        PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9170 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
@@ -435,6 +438,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 +1241,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 +1257,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 fe3ca0989b14cac2e712ef2778f2a1b7e528c85b..1ad2f62d34b98fd0b41be9a239827e1634327c54 100644 (file)
@@ -83,6 +83,10 @@ static struct pci_driver sis_pci_driver = {
        .id_table               = sis_pci_tbl,
        .probe                  = sis_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static struct scsi_host_template sis_sht = {
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..83a598ebb65a4ab7699d1dcebe1b44b42ea8ae5a 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;
 }
@@ -387,10 +425,7 @@ static void null_del_dev(struct nullb *nullb)
        list_del_init(&nullb->list);
 
        del_gendisk(nullb->disk);
-       if (queue_mode == NULL_Q_MQ)
-               blk_mq_free_queue(nullb->q);
-       else
-               blk_cleanup_queue(nullb->q);
+       blk_cleanup_queue(nullb->q);
        put_disk(nullb->disk);
        kfree(nullb);
 }
@@ -417,13 +452,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 +489,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 +534,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)
@@ -534,10 +575,7 @@ static int null_add_dev(void)
        disk = nullb->disk = alloc_disk_node(1, home_node);
        if (!disk) {
 queue_fail:
-               if (queue_mode == NULL_Q_MQ)
-                       blk_mq_free_queue(nullb->q);
-               else
-                       blk_cleanup_queue(nullb->q);
+               blk_cleanup_queue(nullb->q);
                cleanup_queues(nullb);
 err:
                kfree(nullb);
@@ -579,7 +617,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 6bfc1bb318f6399397ca8f169cc07fd98b46256d..dceb85f8d9a8251ed115e06af348692898f6a400 100644 (file)
@@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
        { USB_DEVICE(0x0930, 0x0219) },
+       { USB_DEVICE(0x0930, 0x0220) },
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x13d3, 0x3393) },
        { USB_DEVICE(0x0489, 0xe04e) },
@@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index c0ff34f2d2df577efffe902562f9578690ea4e39..3980fd18f6eaeeb129fe543728f19231df80bd59 100644 (file)
@@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
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 8e562dc656016cd9c4dbeaaa3dac0a96a02d0f26..e1f3337a0cf9f7d7fa223a86e84282765d915108 100644 (file)
@@ -27,15 +27,18 @@ static char *tpm_device_name = "TPM";
 static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
                                void **return_value)
 {
-       acpi_status status;
+       acpi_status status = AE_OK;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-       if (strstr(buffer.pointer, context) != NULL) {
-               *return_value = handle;
+
+       if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) {
+               if (strstr(buffer.pointer, context) != NULL) {
+                       *return_value = handle;
+                       status = AE_CTRL_TERMINATE;
+               }
                kfree(buffer.pointer);
-               return AE_CTRL_TERMINATE;
        }
-       return AE_OK;
+
+       return status;
 }
 
 static inline void ppi_assign_params(union acpi_object params[4],
index 8d3009e44fba40d4fba82825bd59d98febf53984..5543b7df8e16c736c210407a5d837ffb32ab3beb 100644 (file)
@@ -87,7 +87,7 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
        return 0;
 }
 
-static unsigned int _get_val(struct clk_divider *divider, u8 div)
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return div;
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 39b40aaede2b36a3bd92546ff344420b480fb569..68e515d093d864ca9cc704d6f90a441695e67a6d 100644 (file)
@@ -26,17 +26,17 @@ static struct clk_onecell_data clk_data;
 #define ASS_CLK_DIV 0x4
 #define ASS_CLK_GATE 0x8
 
+/* list of all parent clock list */
+static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
+static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
+
+#ifdef CONFIG_PM_SLEEP
 static unsigned long reg_save[][2] = {
        {ASS_CLK_SRC,  0},
        {ASS_CLK_DIV,  0},
        {ASS_CLK_GATE, 0},
 };
 
-/* list of all parent clock list */
-static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
-static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
-
-#ifdef CONFIG_PM_SLEEP
 static int exynos_audss_clk_suspend(void)
 {
        int i;
index ad5ff50c5f281a5e1c31c498c78c5a717aa464de..1a7c1b929c690b03b2b24a1423da55a97b66aa00 100644 (file)
@@ -39,7 +39,7 @@
 #define SRC_TOP1               0xc214
 #define SRC_CAM                        0xc220
 #define SRC_TV                 0xc224
-#define SRC_MFC                        0xcc28
+#define SRC_MFC                        0xc228
 #define SRC_G3D                        0xc22c
 #define E4210_SRC_IMAGE                0xc230
 #define SRC_LCD0               0xc234
index adf32343c9f9c408f5b8bc7c78a6ce3bc66c27a7..e52359cf9b6fe76db63b787717f003454d89e12e 100644 (file)
@@ -25,6 +25,7 @@
 #define MPLL_LOCK              0x4000
 #define MPLL_CON0              0x4100
 #define SRC_CORE1              0x4204
+#define GATE_IP_ACP            0x8800
 #define CPLL_LOCK              0x10020
 #define EPLL_LOCK              0x10030
 #define VPLL_LOCK              0x10040
@@ -75,7 +76,6 @@
 #define SRC_CDREX              0x20200
 #define PLL_DIV2_SEL           0x20a24
 #define GATE_IP_DISP1          0x10928
-#define GATE_IP_ACP            0x10000
 
 /* list of PLLs to be registered */
 enum exynos5250_plls {
@@ -120,7 +120,8 @@ enum exynos5250_clks {
        spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
        hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
        tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
-       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, mdma0,
+       smmu_mdma0,
 
        /* mux clocks */
        mout_hdmi = 1024,
@@ -354,8 +355,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
        GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
        GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
-       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
-       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 1, 0, 0),
        GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
        GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
        GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -406,7 +407,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
        GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
        GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
-       GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+       GATE(sysreg, "sysreg", "aclk66",
+                       GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
        GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0),
        GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
        GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
@@ -492,6 +494,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
        GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
        GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+       GATE(mdma0, "mdma0", "aclk266", GATE_IP_ACP, 1, 0, 0),
+       GATE(smmu_mdma0, "smmu_mdma0", "aclk266", GATE_IP_ACP, 5, 0, 0),
 };
 
 static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
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..8d19f7c06010c364ff6ee758c15096c252f9f4bd 100644 (file)
@@ -828,14 +828,17 @@ 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;
 
        /* set default policy */
        ret = cpufreq_set_policy(policy, &new_policy);
-       policy->user_policy.policy = policy->policy;
-       policy->user_policy.governor = policy->governor;
-
        if (ret) {
                pr_debug("setting policy failed\n");
                if (cpufreq_driver->exit)
@@ -845,8 +848,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 +879,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 +924,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 +1005,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;
                }
@@ -994,15 +1013,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-       if (frozen)
-               /* Restore the saved policy when doing light-weight init */
-               policy = cpufreq_policy_restore(cpu);
-       else
+       /*
+        * Restore the saved policy when doing light-weight init and fall back
+        * to the full init if that fails.
+        */
+       policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
+       if (!policy) {
+               frozen = false;
                policy = cpufreq_policy_alloc();
-
-       if (!policy)
-               goto nomem_out;
-
+               if (!policy)
+                       goto nomem_out;
+       }
 
        /*
         * In the resume path, since we restore a saved policy, the assignment
@@ -1047,8 +1068,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
         */
        cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 
-       policy->user_policy.min = policy->min;
-       policy->user_policy.max = policy->max;
+       if (!frozen) {
+               policy->user_policy.min = policy->min;
+               policy->user_policy.max = policy->max;
+       }
 
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                     CPUFREQ_START, policy);
@@ -1079,6 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 
        cpufreq_init_policy(policy);
 
+       if (!frozen) {
+               policy->user_policy.policy = policy->policy;
+               policy->user_policy.governor = policy->governor;
+       }
+
        kobject_uevent(&policy->kobj, KOBJ_ADD);
        up_read(&cpufreq_rwsem);
 
@@ -1096,7 +1124,13 @@ err_get_freq:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 err_set_policy_cpu:
+       if (frozen) {
+               /* Do not leave stale fallback data behind. */
+               per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
+               cpufreq_policy_put_kobj(policy);
+       }
        cpufreq_policy_free(policy);
+
 nomem_out:
        up_read(&cpufreq_rwsem);
 
@@ -1118,7 +1152,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 +1160,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 +1226,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 +1248,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 +1277,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 5f1cbae369611062c18ee50982ffa5c6f724d30f..d51f17ed691e023196bbd7e56a3341d4025ce092 100644 (file)
@@ -581,7 +581,8 @@ static void intel_pstate_timer_func(unsigned long __data)
 }
 
 #define ICPU(model, policy) \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy }
+       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\
+                       (unsigned long)&policy }
 
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x2a, core_params),
@@ -614,6 +615,11 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu = all_cpu_data[cpunum];
 
        intel_pstate_get_cpu_pstates(cpu);
+       if (!cpu->pstate.current_pstate) {
+               all_cpu_data[cpunum] = NULL;
+               kfree(cpu);
+               return -ENODATA;
+       }
 
        cpu->cpu = cpunum;
 
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 36795639df0da2d828c784b61c82a728037f6e1c..6e51114057d0963605ef1dfc80b231946e1b88f7 100644 (file)
@@ -65,7 +65,7 @@ static struct cpuidle_driver calxeda_idle_driver = {
        .state_count = 2,
 };
 
-static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
+static int calxeda_cpuidle_probe(struct platform_device *pdev)
 {
        return cpuidle_register(&calxeda_idle_driver, NULL);
 }
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..f757a0f428bde807a8e5402af8404e98314c2bf8 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))
+       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);
-       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;
 }
@@ -1418,14 +1410,12 @@ static const struct platform_device_info ixp_dev_info __initdata = {
 static int __init ixp_module_init(void)
 {
        int num = ARRAY_SIZE(ixp4xx_algos);
-       int i, err ;
+       int i, err;
 
        pdev = platform_device_register_full(&ixp_dev_info);
        if (IS_ERR(pdev))
                return PTR_ERR(pdev);
 
-       dev = &pdev->dev;
-
        spin_lock_init(&desc_lock);
        spin_lock_init(&emerg_lock);
 
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..ef63b9058f3c09d9d9dea56096bc5edda6d3b125 100644 (file)
@@ -912,7 +912,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 +1054,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 1a49c777607c50d313482f3ead21c19572a1cf8d..87529181efccb9851467cc04be04bd91fecb15b3 100644 (file)
@@ -817,7 +817,15 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
        dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, dma_src)) {
+               dev_err(dev, "mapping src buffer failed\n");
+               goto free_resources;
+       }
        dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+       if (dma_mapping_error(dev, dma_dest)) {
+               dev_err(dev, "mapping dest buffer failed\n");
+               goto unmap_src;
+       }
        flags = DMA_PREP_INTERRUPT;
        tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
                                                   IOAT_TEST_SIZE, flags);
@@ -855,8 +863,9 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
 unmap_dma:
-       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
        dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+unmap_src:
+       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
 free_resources:
        dma->device_free_chan_resources(dma_chan);
 out:
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 cdf0483b8f2dfb8f746b786fd6bf84b0d5f6657b..536632f6479c6966029022614f2bf863974256b4 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;
 
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..d3c3b5b15824ee8bb927a7b1a382582309b31376 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));
 }
 
 /**
@@ -904,14 +906,12 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
                WARN_ON(readq(&gtt_entries[i-1])
                        != gen8_pte_encode(addr, level, true));
 
-#if 0 /* TODO: Still needed on GEN8? */
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
         * have finished.
         */
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-#endif
 }
 
 /*
@@ -1239,6 +1239,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..769b864465a989201339870db2eb122770886c72 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);
@@ -10541,11 +10541,20 @@ static struct intel_quirk intel_quirks[] = {
        /* Sony Vaio Y cannot use SSC on LVDS */
        { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
 
-       /*
-        * All GM45 Acer (and its brands eMachines and Packard Bell) laptops
-        * seem to use inverted backlight PWM.
-        */
-       { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness },
+       /* Acer Aspire 5734Z must invert backlight brightness */
+       { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
+
+       /* Acer/eMachines G725 */
+       { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
+
+       /* Acer/eMachines e725 */
+       { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
+
+       /* Acer/Packard Bell NCL20 */
+       { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
+
+       /* Acer Aspire 4736Z */
+       { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
 
        /* Dell XPS13 HD Sandy Bridge */
        { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
@@ -11036,8 +11045,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 +11053,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 +11135,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 48f06378d3f9d5f9e09e03291a11d6e26527f674..2ea5568b6cf59be811fa6777612eca8b8180736b 100644 (file)
@@ -104,11 +104,8 @@ nouveau_subdev_create_(struct nouveau_object *parent,
 
        if (parent) {
                struct nouveau_device *device = nv_device(parent);
-               int subidx = nv_hclass(subdev) & 0xff;
-
                subdev->debug = nouveau_dbgopt(device->dbgopt, subname);
                subdev->mmio  = nv_subdev(device)->mmio;
-               device->subdev[subidx] = *pobject;
        }
 
        return 0;
index 9135b25a29d09a4e82e57e1c9a1a27608eee6a99..dd01c6c435d6e2e01ecb92ccbd57cf09e7346660 100644 (file)
@@ -268,6 +268,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
                if (ret)
                        return ret;
 
+               device->subdev[i] = devobj->subdev[i];
+
                /* note: can't init *any* subdevs until devinit has been run
                 * due to not knowing exactly what the vbios init tables will
                 * mess with.  devinit also can't be run until all of its
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 8d06eef2b9ee02f7b3d895c8d7a37bfd6e022924..dbc5e33de94f8b6caebbab7319d3bfb7117c57f2 100644 (file)
@@ -161,7 +161,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_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 434bb4b0fa2e650a130a98cc940f5ca7727cfeac..5c8a63dc506aafcfbbe5088ede75ed635d0ba8a4 100644 (file)
@@ -334,7 +334,7 @@ nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds)
        while ((mthd = &mthds[i++]) && (init = mthd->init)) {
                u32  addr = 0x80000000 | mthd->oclass;
                for (data = 0; init->count; init++) {
-                       if (data != init->data) {
+                       if (init == mthd->init || data != init->data) {
                                nv_wr32(priv, 0x40448c, init->data);
                                data = init->data;
                        }
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 8541aa382ff224136d8c1cedff00db0595a753c2..d89dbdf39b0db501159a873eeb5ada0612a3ba35 100644 (file)
@@ -75,6 +75,11 @@ struct nouveau_fb {
 static inline struct nouveau_fb *
 nouveau_fb(void *obj)
 {
+       /* fbram uses this before device subdev pointer is valid */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_FB)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB];
 }
 
index 420908cb82b613bbc97fbccb9b123f3449926100..df1b1b42309337cb14c79b503497e49bf80ee49b 100644 (file)
@@ -365,13 +365,13 @@ static u16
 init_script(struct nouveau_bios *bios, int index)
 {
        struct nvbios_init init = { .bios = bios };
-       u16 data;
+       u16 bmp_ver = bmp_version(bios), data;
 
-       if (bmp_version(bios) && bmp_version(bios) < 0x0510) {
-               if (index > 1)
+       if (bmp_ver && bmp_ver < 0x0510) {
+               if (index > 1 || bmp_ver < 0x0100)
                        return 0x0000;
 
-               data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18);
+               data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);
                return nv_ro16(bios, data + (index * 2));
        }
 
@@ -1294,7 +1294,11 @@ init_jump(struct nvbios_init *init)
        u16 offset = nv_ro16(bios, init->offset + 1);
 
        trace("JUMP\t0x%04x\n", offset);
-       init->offset = offset;
+
+       if (init_exec(init))
+               init->offset = offset;
+       else
+               init->offset += 3;
 }
 
 /**
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 6828d81ed7b99daea875ffd06c4dd399d4aa05dd..900fae01793e7884ee8033a11d6c247cbeb36678 100644 (file)
@@ -447,6 +447,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        if (ret)
                goto done;
 
+       info->offset = ntfy->node->offset;
+
 done:
        if (ret)
                nouveau_abi16_ntfy_fini(chan, ntfy);
index 95c740454049ad1b4a4cf23c2bc63d7038c7a362..ba0183fb84f3b871a4815552021174e870f780e8 100644 (file)
@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
        bool dsm_detected;
        bool optimus_detected;
        acpi_handle dhandle;
+       acpi_handle other_handle;
        acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
@@ -260,9 +261,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
        if (!dhandle)
                return false;
 
-       if (!acpi_has_method(dhandle, "_DSM"))
+       if (!acpi_has_method(dhandle, "_DSM")) {
+               nouveau_dsm_priv.other_handle = dhandle;
                return false;
-
+       }
        if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
@@ -338,6 +340,16 @@ static bool nouveau_dsm_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
                        acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when _DSM is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
+               acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
                ret = true;
        }
 
index 7809d92183c4236c9f1f937ea6cde6a39e780063..25ea82f8def3cb883a06aef6e9da59ea4cbffaf7 100644 (file)
@@ -608,8 +608,9 @@ 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;
+               goto fail_free;
 
        if (new_bo != old_bo) {
                ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
@@ -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..0b9621c9aeea3b25da6bad8b121bfc3c3236ddcc 100644 (file)
@@ -1143,31 +1143,53 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        }
 
        if (tiling_flags & RADEON_TILING_MACRO) {
-               if (rdev->family >= CHIP_BONAIRE)
-                       tmp = rdev->config.cik.tile_config;
-               else if (rdev->family >= CHIP_TAHITI)
-                       tmp = rdev->config.si.tile_config;
-               else if (rdev->family >= CHIP_CAYMAN)
-                       tmp = rdev->config.cayman.tile_config;
-               else
-                       tmp = rdev->config.evergreen.tile_config;
+               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
-               switch ((tmp & 0xf0) >> 4) {
-               case 0: /* 4 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
-                       break;
-               case 1: /* 8 banks */
-               default:
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
-                       break;
-               case 2: /* 16 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
-                       break;
+               /* Set NUM_BANKS. */
+               if (rdev->family >= CHIP_BONAIRE) {
+                       unsigned tileb, index, num_banks, tile_split_bytes;
+
+                       /* Calculate the macrotile mode index. */
+                       tile_split_bytes = 64 << tile_split;
+                       tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+                       tileb = min(tile_split_bytes, tileb);
+
+                       for (index = 0; tileb > 64; index++) {
+                               tileb >>= 1;
+                       }
+
+                       if (index >= 16) {
+                               DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+                                         target_fb->bits_per_pixel, tile_split);
+                               return -EINVAL;
+                       }
+
+                       num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
+               } else {
+                       /* SI and older. */
+                       if (rdev->family >= CHIP_TAHITI)
+                               tmp = rdev->config.si.tile_config;
+                       else if (rdev->family >= CHIP_CAYMAN)
+                               tmp = rdev->config.cayman.tile_config;
+                       else
+                               tmp = rdev->config.evergreen.tile_config;
+
+                       switch ((tmp & 0xf0) >> 4) {
+                       case 0: /* 4 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+                               break;
+                       case 1: /* 8 banks */
+                       default:
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+                               break;
+                       case 2: /* 16 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+                               break;
+                       }
                }
 
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-
-               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
                fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
                fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
                fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
@@ -1180,23 +1202,18 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
        if (rdev->family >= CHIP_BONAIRE) {
-               u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
-               u32 num_rb = rdev->config.cik.max_backends_per_se;
-               if (num_pipe_configs > 8)
-                       num_pipe_configs = 8;
-               if (num_pipe_configs == 8)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
-               else if (num_pipe_configs == 4) {
-                       if (num_rb == 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
-                       else if (num_rb < 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
-               } else if (num_pipe_configs == 2)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
+               /* Read the pipe config from the 2D TILED SCANOUT mode.
+                * It should be the same for the other modes too, but not all
+                * modes set the pipe config field. */
+               u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
+
+               fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
        } 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 b43a3a3c90671911a4eaa0a7c5a260c42118df41..e950fabd7f5e474ab3e60371f669e31805077785 100644 (file)
@@ -3057,7 +3057,7 @@ static u32 cik_create_bitmask(u32 bit_width)
  * Returns the disabled RB bitmask.
  */
 static u32 cik_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -3071,7 +3071,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
@@ -3088,7 +3088,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
  */
 static void cik_setup_rb(struct radeon_device *rdev,
                         u32 se_num, u32 sh_per_se,
-                        u32 max_rb_num)
+                        u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -3098,7 +3098,7 @@ static void cik_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        cik_select_se_sh(rdev, i, j);
-                       data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        if (rdev->family == CHIP_HAWAII)
                                disabled_rbs |= data << ((i * sh_per_se + j) * HAWAII_RB_BITMAP_WIDTH_PER_SH);
                        else
@@ -3108,12 +3108,14 @@ static void cik_setup_rb(struct radeon_device *rdev,
        cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.cik.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                cik_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
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..45e1f447bc794c677a8e83830fd318585c2d7f7e 100644 (file)
@@ -1940,7 +1940,7 @@ struct si_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -1970,7 +1970,7 @@ struct cik_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -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 9d302eaeea1587b6fdb5439119b6f45c0de961db..485848f889f55c9f4b86bf61bd8c019e2ad96a27 100644 (file)
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv {
        bool atpx_detected;
        /* handle for device - and atpx */
        acpi_handle dhandle;
+       acpi_handle other_handle;
        struct radeon_atpx atpx;
 } radeon_atpx_priv;
 
@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
                return false;
 
        status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
-       if (ACPI_FAILURE(status))
+       if (ACPI_FAILURE(status)) {
+               radeon_atpx_priv.other_handle = dhandle;
                return false;
-
+       }
        radeon_atpx_priv.dhandle = dhandle;
        radeon_atpx_priv.atpx.handle = atpx_handle;
        return true;
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
                       acpi_method_name);
                radeon_atpx_priv.atpx_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when ATPX is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
+               acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
                return true;
        }
        return false;
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..db39ea36bf22fc396da63e5a157adf42e752e712 100644 (file)
  *   2.33.0 - Add SI tiling mode array query
  *   2.34.0 - Add CIK tiling mode array query
  *   2.35.0 - Add CIK macrotile mode array query
+ *   2.36.0 - Fix CIK DCE tiling setup
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       35
+#define KMS_DRIVER_MINOR       36
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -508,15 +509,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 +578,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 55d0b474bd371ae83f1cea0ec08d30504b371816..21d593c0ecaf4e7e0ec85ab9b7bf53fafd0f2a87 100644 (file)
@@ -461,6 +461,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_SI_CP_DMA_COMPUTE:
                *value = 1;
                break;
+       case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
+               if (rdev->family >= CHIP_BONAIRE) {
+                       *value = rdev->config.cik.backend_enable_mask;
+               } else if (rdev->family >= CHIP_TAHITI) {
+                       *value = rdev->config.si.backend_enable_mask;
+               } else {
+                       DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+               }
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
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 373d088bac66db910291045424e075921d39d202..b9c0529b4a2e1e9d8f69e51f6742d023492a0040 100644 (file)
@@ -473,7 +473,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                return -EINVAL;
        }
 
-       if ((start >> 28) != (end >> 28)) {
+       if ((start >> 28) != ((end - 1) >> 28)) {
                DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
                          start, end);
                return -EINVAL;
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..85e1edfaa3bed0814e262378ae0a7558834936d3 100644 (file)
@@ -2811,7 +2811,7 @@ static void si_setup_spi(struct radeon_device *rdev,
 }
 
 static u32 si_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -2825,14 +2825,14 @@ static u32 si_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = si_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
 
 static void si_setup_rb(struct radeon_device *rdev,
                        u32 se_num, u32 sh_per_se,
-                       u32 max_rb_num)
+                       u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -2842,19 +2842,21 @@ static void si_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        si_select_se_sh(rdev, i, j);
-                       data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
                }
        }
        si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.si.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                si_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
@@ -3882,8 +3884,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..797ed29a36ea7969765e90641d15f3a66e982db3 100644 (file)
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[] __initdata = {
+static struct cpuidle_state nehalem_cstates[] = {
        {
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[] __initdata = {
+static struct cpuidle_state snb_cstates[] = {
        {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[] __initdata = {
+static struct cpuidle_state ivb_cstates[] = {
        {
                .name = "C1-IVB",
                .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[] __initdata = {
+static struct cpuidle_state hsw_cstates[] = {
        {
                .name = "C1-HSW",
                .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[] __initdata = {
+static struct cpuidle_state atom_cstates[] = {
        {
                .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
@@ -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[] = {
        {
                .name = "C1-AVN",
                .desc = "MWAIT 0x00",
@@ -340,10 +340,12 @@ 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 },
+       {
+               .enter = NULL }
 };
 
 /**
@@ -377,6 +379,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 12fef76c791c524454bd9a0c48d5b4a967ac19af..45126879ad28a2149351232a1f9c4a2551f06c09 100644 (file)
@@ -524,50 +524,6 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-#define VLAN_NONE 0xfff
-#define FILTER_SEL_VLAN_NONE 0xffff
-#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
-#define FILTER_SEL_WIDTH_VIN_P_FC \
-       (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
-#define FILTER_SEL_WIDTH_TAG_P_FC \
-       (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
-
-static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
-                                 struct l2t_entry *l2t)
-{
-       unsigned int ntuple = 0;
-       u32 viid;
-
-       switch (dev->rdev.lldi.filt_mode) {
-
-       /* default filter mode */
-       case HW_TPL_FR_MT_PR_IV_P_FC:
-               if (l2t->vlan == VLAN_NONE)
-                       ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
-               else {
-                       ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
-                       ntuple |= 1 << FILTER_SEL_WIDTH_TAG_P_FC;
-               }
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       case HW_TPL_FR_MT_PR_OV_P_FC: {
-               viid = cxgb4_port_viid(l2t->neigh->dev);
-
-               ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
-               ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
-               ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       }
-       default:
-               break;
-       }
-       return ntuple;
-}
-
 static int send_connect(struct c4iw_ep *ep)
 {
        struct cpl_act_open_req *req;
@@ -641,8 +597,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req->local_ip = la->sin_addr.s_addr;
                        req->peer_ip = ra->sin_addr.s_addr;
                        req->opt0 = cpu_to_be64(opt0);
-                       req->params = cpu_to_be32(select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t));
+                       req->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req->opt2 = cpu_to_be32(opt2);
                } else {
                        req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
@@ -662,9 +619,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req6->peer_ip_lo = *((__be64 *)
                                                (ra6->sin6_addr.s6_addr + 8));
                        req6->opt0 = cpu_to_be64(opt0);
-                       req6->params = cpu_to_be32(
-                                       select_ntuple(ep->com.dev, ep->dst,
-                                                     ep->l2t));
+                       req6->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req6->opt2 = cpu_to_be32(opt2);
                }
        } else {
@@ -681,8 +638,9 @@ static int send_connect(struct c4iw_ep *ep)
                        t5_req->peer_ip = ra->sin_addr.s_addr;
                        t5_req->opt0 = cpu_to_be64(opt0);
                        t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
-                                               select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t)));
+                                                    cxgb4_select_ntuple(
+                                            ep->com.dev->rdev.lldi.ports[0],
+                                            ep->l2t)));
                        t5_req->opt2 = cpu_to_be32(opt2);
                } else {
                        t5_req6 = (struct cpl_t5_act_open_req6 *)
@@ -703,7 +661,9 @@ static int send_connect(struct c4iw_ep *ep)
                                                (ra6->sin6_addr.s6_addr + 8));
                        t5_req6->opt0 = cpu_to_be64(opt0);
                        t5_req6->params = (__force __be64)cpu_to_be32(
-                               select_ntuple(ep->com.dev, ep->dst, ep->l2t));
+                                                       cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        t5_req6->opt2 = cpu_to_be32(opt2);
                }
        }
@@ -1630,7 +1590,8 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
        memset(req, 0, sizeof(*req));
        req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
        req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
-       req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
+       req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
+                                    ep->com.dev->rdev.lldi.ports[0],
                                     ep->l2t));
        sin = (struct sockaddr_in *)&ep->com.local_addr;
        req->le.lport = sin->sin_port;
@@ -2938,7 +2899,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        /*
         * Allocate a server TID.
         */
-       if (dev->rdev.lldi.enable_fw_ofld_conn)
+       if (dev->rdev.lldi.enable_fw_ofld_conn &&
+           ep->com.local_addr.ss_family == AF_INET)
                ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
                                             cm_id->local_addr.ss_family, ep);
        else
@@ -3323,9 +3285,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        /*
         * Calculate the server tid from filter hit index from cpl_rx_pkt.
         */
-       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val)
-                                         - dev->rdev.lldi.tids->sftid_base
-                                         + dev->rdev.lldi.tids->nstids;
+       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
 
        lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
        if (!lep) {
@@ -3397,7 +3357,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        window = (__force u16) htons((__force u16)tcph->window);
 
        /* Calcuate filter portion for LE region. */
-       filter = (__force unsigned int) cpu_to_be32(select_ntuple(dev, dst, e));
+       filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
+                                                   dev->rdev.lldi.ports[0],
+                                                   e));
 
        /*
         * Synthesize the cpl_pass_accept_req. We have everything except the
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 c29b5c8388331458bb2a2caf85580d76031f1dcb..cdc7df4fdb8aedea8c9026de82d774e5f5fe502b 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>      /* For ARPHRD_xxx */
 #include <linux/module.h>
 #include <net/rtnetlink.h>
 #include "ipoib.h"
@@ -103,7 +104,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
-       if (!pdev)
+       if (!pdev || pdev->type != ARPHRD_INFINIBAND)
                return -ENODEV;
 
        ppriv = netdev_priv(pdev);
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 846ccdd905b19b66872762fd05db29ea0552a8cb..d2965e4b32243a90f40db55a7722c3229d4edb3a 100644 (file)
@@ -1871,6 +1871,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
                break;
 
        case EV_ABS:
+               input_alloc_absinfo(dev);
+               if (!dev->absinfo)
+                       return;
+
                __set_bit(code, dev->absbit);
                break;
 
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 75762d6ff3ba70934190bb2fe70ef6d6135d49c5..aa127ba392a45cbabe9f95180876543dd6441865 100644 (file)
@@ -455,7 +455,18 @@ static void zforce_complete(struct zforce_ts *ts, int cmd, int result)
        }
 }
 
-static irqreturn_t zforce_interrupt(int irq, void *dev_id)
+static irqreturn_t zforce_irq(int irq, void *dev_id)
+{
+       struct zforce_ts *ts = dev_id;
+       struct i2c_client *client = ts->client;
+
+       if (ts->suspended && device_may_wakeup(&client->dev))
+               pm_wakeup_event(&client->dev, 500);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 {
        struct zforce_ts *ts = dev_id;
        struct i2c_client *client = ts->client;
@@ -465,12 +476,10 @@ static irqreturn_t zforce_interrupt(int irq, void *dev_id)
        u8 *payload;
 
        /*
-        * When suspended, emit a wakeup signal if necessary and return.
+        * When still suspended, return.
         * Due to the level-interrupt we will get re-triggered later.
         */
        if (ts->suspended) {
-               if (device_may_wakeup(&client->dev))
-                       pm_wakeup_event(&client->dev, 500);
                msleep(20);
                return IRQ_HANDLED;
        }
@@ -763,8 +772,8 @@ static int zforce_probe(struct i2c_client *client,
         * Therefore we can trigger the interrupt anytime it is low and do
         * not need to limit it to the interrupt edge.
         */
-       ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                       zforce_interrupt,
+       ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                       zforce_irq, zforce_irq_thread,
                                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                        input_dev->name, ts);
        if (ret) {
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 497bd026c2378eec6e781df68d007c135be4c1f7..4a48255281887e8c03f9dbacccf404f4f9c52476 100644 (file)
@@ -1643,10 +1643,6 @@ setup_hfcpci(struct IsdnCard *card)
        int i;
        struct pci_dev *tmp_hfcpci = NULL;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
index f6ab63aa699590278531ba9ae6ceabe75ba90813..33eeb4602c7e7131078d78d97b24f09971b8396e 100644 (file)
@@ -290,10 +290,6 @@ int setup_telespci(struct IsdnCard *card)
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, telespci_revision);
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
index 05188351711d2d80f5ac8cd0a006159b732b2c90..a97263e902ffc6b927db6b935cb290902909f21e 100644 (file)
@@ -244,18 +244,12 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -427,15 +421,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5521_load_engine(chip);
+       ret = lp5521_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5521_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 6b553d9f4266d570eec78a2180eee9b56194d62c..fd9ab5f61441c50716620138bf55b175c2ac1045 100644 (file)
@@ -337,18 +337,12 @@ static int lp5523_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -548,15 +542,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5523_load_engine_and_select_page(chip);
+       ret = lp5523_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5523_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
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 11e20afbdcacb7d31e49798db6d2dfbf0504afd8..705698fd2c7ed0f8f5e4fcada7b060627352be05 100644 (file)
@@ -1228,8 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)
 
        pcr->remove_pci = true;
 
-       cancel_delayed_work(&pcr->carddet_work);
-       cancel_delayed_work(&pcr->idle_work);
+       /* Disable interrupts at the pcr level */
+       spin_lock_irq(&pcr->lock);
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+       spin_unlock_irq(&pcr->lock);
+
+       cancel_delayed_work_sync(&pcr->carddet_work);
+       cancel_delayed_work_sync(&pcr->idle_work);
 
        mfd_remove_devices(&pcidev->dev);
 
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 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 d210d131fef255da97e7d277574ac80f01a66341..0f55589a56b815af4c00bc521c504db468774fa5 100644 (file)
@@ -73,7 +73,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        info->map.cached =
-               ioremap_cached(info->map.phys, info->map.size);
+               ioremap_cache(info->map.phys, info->map.size);
        if (!info->map.cached)
                printk(KERN_WARNING "Failed to ioremap cached %s\n",
                       info->map.name);
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 187b1b7772ef1b873303fc46998a591137bec7b7..4ced59436558e65a723df9975e8302fcec2cbb62 100644 (file)
@@ -2201,20 +2201,25 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                (__get_link_speed(port) << 1);
        pr_debug("Port %d changed speed\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2229,20 +2234,25 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                __get_duplex(port);
        pr_debug("Port %d changed duplex\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2258,15 +2268,21 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
-       // on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
-       // on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+       __get_state_machine_lock(port);
+       /* on link down we are zeroing duplex and speed since
+        * some of the adaptors(ce1000.lan) report full duplex/speed
+        * instead of N/A(duplex) / 0(speed).
+        *
+        * on link up we are forcing recheck on the duplex and speed since
+        * some of he adaptors(ce1000.lan) report.
+        */
        if (link == BOND_LINK_UP) {
                port->is_enabled = true;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
@@ -2282,10 +2298,15 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
                port->actor_oper_port_key = (port->actor_admin_port_key &=
                                             ~AD_SPEED_KEY_BITS);
        }
-       //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       pr_debug("Port %d changed link status to %s",
+               port->actor_port_number,
+               (link == BOND_LINK_UP) ? "UP" : "DOWN");
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /*
index 4dd5ee2a34cc68c4222f4c4115beedaee8b187d2..4b8c58b0ec243575bbc17a547f7370b8d0b26d54 100644 (file)
@@ -3732,7 +3732,8 @@ static inline int bond_slave_override(struct bonding *bond,
 }
 
 
-static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
@@ -4110,7 +4111,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 +4148,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 +4200,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 b2ffad1304d221ef54e60cd1a82138a4d8344975..248baf6273fb76a2b179c50fe068aeddff51a42e 100644 (file)
@@ -565,6 +565,8 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        /* Make sure pointer to data buffer is set */
        wmb();
 
+       skb_tx_timestamp(skb);
+
        *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len);
 
        /* Increment index to point to the next BD */
@@ -579,8 +581,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
 
        arc_reg_set(priv, R_STATUS, TXPL_MASK);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index a36a760ada28af64272a5132a60648c543963bed..29801750f239b247389c7040f6616f9b79d14983 100644 (file)
@@ -145,9 +145,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
         * Mask some pcie error bits
         */
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
-       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
-       data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
-       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       if (pos) {
+               pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
+               data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
+               pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       }
        /* clear error status */
        pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,
                        PCI_EXP_DEVSTA_NFED |
index a1f66e2c9a8694c9d83471dd63f6659d431840eb..ec6119089b82b8445cd573d961378c70b28632e5 100644 (file)
@@ -520,10 +520,12 @@ struct bnx2x_fastpath {
 #define BNX2X_FP_STATE_IDLE                  0
 #define BNX2X_FP_STATE_NAPI            (1 << 0)    /* NAPI owns this FP */
 #define BNX2X_FP_STATE_POLL            (1 << 1)    /* poll owns this FP */
-#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 2)    /* NAPI yielded this FP */
-#define BNX2X_FP_STATE_POLL_YIELD      (1 << 3)    /* poll yielded this FP */
+#define BNX2X_FP_STATE_DISABLED                (1 << 2)
+#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 3)    /* NAPI yielded this FP */
+#define BNX2X_FP_STATE_POLL_YIELD      (1 << 4)    /* poll yielded this FP */
+#define BNX2X_FP_OWNED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
 #define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD)
-#define BNX2X_FP_LOCKED        (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
+#define BNX2X_FP_LOCKED        (BNX2X_FP_OWNED | BNX2X_FP_STATE_DISABLED)
 #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD)
        /* protect state */
        spinlock_t lock;
@@ -613,7 +615,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = true;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        if (fp->state & BNX2X_FP_LOCKED) {
                WARN_ON(fp->state & BNX2X_FP_STATE_NAPI);
                fp->state |= BNX2X_FP_STATE_NAPI_YIELD;
@@ -622,7 +624,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
                /* we don't care if someone yielded */
                fp->state = BNX2X_FP_STATE_NAPI;
        }
-       spin_unlock(&fp->lock);
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -631,14 +633,16 @@ static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = false;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        WARN_ON(fp->state &
                (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD));
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
-       spin_unlock(&fp->lock);
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -669,7 +673,9 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
        spin_unlock_bh(&fp->lock);
        return rc;
 }
@@ -677,9 +683,23 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 /* true if a socket is polling, even if it did not get the lock */
 static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
-       WARN_ON(!(fp->state & BNX2X_FP_LOCKED));
+       WARN_ON(!(fp->state & BNX2X_FP_OWNED));
        return fp->state & BNX2X_FP_USER_PEND;
 }
+
+/* false if fp is currently owned */
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       int rc = true;
+
+       spin_lock_bh(&fp->lock);
+       if (fp->state & BNX2X_FP_OWNED)
+               rc = false;
+       fp->state |= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
+
+       return rc;
+}
 #else
 static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp)
 {
@@ -709,6 +729,10 @@ static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
        return false;
 }
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       return true;
+}
 #endif /* CONFIG_NET_RX_BUSY_POLL */
 
 /* Use 2500 as a mini-jumbo MTU for FCoE */
@@ -1250,7 +1274,10 @@ struct bnx2x_slowpath {
         * Therefore, if they would have been defined in the same union,
         * data can get corrupted.
         */
-       struct afex_vif_list_ramrod_data func_afex_rdata;
+       union {
+               struct afex_vif_list_ramrod_data        viflist_data;
+               struct function_update_data             func_update;
+       } func_afex_rdata;
 
        /* used by dmae command executer */
        struct dmae_command             dmae[MAX_DMAE_C];
@@ -2499,4 +2526,6 @@ void bnx2x_set_local_cmng(struct bnx2x *bp);
 #define MCPR_SCRATCH_BASE(bp) \
        (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
 
+#define E1H_MAX_MF_SB_COUNT (HC_SB_MAX_SB_E1X/(E1HVN_MAX * PORT_MAX))
+
 #endif /* bnx2x.h */
index ec96130533cc54630c3f26f6253e58b5a0f5a7cf..bf811565ee245a0472cffc0ea5f70b30da053beb 100644 (file)
@@ -160,6 +160,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        struct sk_buff *skb = tx_buf->skb;
        u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
        int nbd;
+       u16 split_bd_len = 0;
 
        /* prefetch skb end pointer to speedup dev_kfree_skb() */
        prefetch(&skb->end);
@@ -167,10 +168,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        DP(NETIF_MSG_TX_DONE, "fp[%d]: pkt_idx %d  buff @(%p)->skb %p\n",
           txdata->txq_index, idx, tx_buf, skb);
 
-       /* unmap first bd */
        tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
-       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
-                        BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
        nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
@@ -188,12 +186,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        --nbd;
        bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
 
-       /* ...and the TSO split header bd since they have no mapping */
+       /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */
        if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
+               tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
+               split_bd_len = BD_UNMAP_LEN(tx_data_bd);
                --nbd;
                bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
        }
 
+       /* unmap first bd */
+       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
+                        BD_UNMAP_LEN(tx_start_bd) + split_bd_len,
+                        DMA_TO_DEVICE);
+
        /* now free frags */
        while (nbd > 0) {
 
@@ -1790,26 +1795,22 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_rx_queue_cnic(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 static void bnx2x_napi_disable(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_eth_queue(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 void bnx2x_netif_start(struct bnx2x *bp)
@@ -1832,7 +1833,8 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
                bnx2x_napi_disable_cnic(bp);
 }
 
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
index da8fcaa74495475cb2c2c3984f3aa3cf85fc83ba..41f3ca5ad972b396498cbe5b7d7ad72ea9bdb1a7 100644 (file)
@@ -524,7 +524,8 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
 int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
                                        struct bnx2x_fastpath *fp,
index 20dcc02431cac441a8bf3076a7fe6db1abfb04e9..11fc79585491f484f7ffd56d7a2e8e876ebb8e79 100644 (file)
@@ -3865,6 +3865,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
        } else {
+               /* Enable Auto-Detect to support 1G over CL37 as well */
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x10);
+
+               /* Force cl48 sync_status LOW to avoid getting stuck in CL73
+                * parallel-detect loop when CL73 and CL37 are enabled.
+                */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI, 0x0800);
+               bnx2x_set_aer_mmd(params, phy);
+
                bnx2x_disable_kr2(params, vars, phy);
        }
 
@@ -8120,17 +8133,20 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                *edc_mode = EDC_MODE_ACTIVE_DAC;
                        else
                                check_limiting_mode = 1;
-               } else if (copper_module_type &
-                       SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
+               } else {
+                       *edc_mode = EDC_MODE_PASSIVE_DAC;
+                       /* Even in case PASSIVE_DAC indication is not set,
+                        * treat it as a passive DAC cable, since some cables
+                        * don't have this indication.
+                        */
+                       if (copper_module_type &
+                           SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
                                   "Passive Copper cable detected\n");
-                               *edc_mode =
-                                     EDC_MODE_PASSIVE_DAC;
-               } else {
-                       DP(NETIF_MSG_LINK,
-                          "Unknown copper-cable-type 0x%x !!!\n",
-                          copper_module_type);
-                       return -EINVAL;
+                       } else {
+                               DP(NETIF_MSG_LINK,
+                                  "Unknown copper-cable-type\n");
+                       }
                }
                break;
        }
@@ -10825,9 +10841,9 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                           (1<<11));
 
        if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-                       (phy->req_line_speed == SPEED_1000)) {
+            (phy->speed_cap_mask &
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+           (phy->req_line_speed == SPEED_1000)) {
                an_1000_val |= (1<<8);
                autoneg_val |= (1<<9 | 1<<12);
                if (phy->req_duplex == DUPLEX_FULL)
@@ -10843,30 +10859,32 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                        0x09,
                        &an_1000_val);
 
-       /* Set 100 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
-               an_10_100_val |= (1<<7);
-               /* Enable autoneg and restart autoneg for legacy speeds */
-               autoneg_val |= (1<<9 | 1<<12);
-
-               if (phy->req_duplex == DUPLEX_FULL)
-                       an_10_100_val |= (1<<8);
-               DP(NETIF_MSG_LINK, "Advertising 100M\n");
-       }
-
-       /* Set 10 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
-               an_10_100_val |= (1<<5);
-               autoneg_val |= (1<<9 | 1<<12);
-               if (phy->req_duplex == DUPLEX_FULL)
+       /* Advertise 10/100 link speed */
+       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
+                       an_10_100_val |= (1<<5);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
                        an_10_100_val |= (1<<6);
-               DP(NETIF_MSG_LINK, "Advertising 10M\n");
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+                       an_10_100_val |= (1<<7);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+                       an_10_100_val |= (1<<8);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+               }
        }
 
        /* Only 10/100 are allowed to work in FORCE mode */
@@ -13342,6 +13360,10 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
 
+       /* Do not touch the link in case physical link down */
+       if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+               return 1;
+
        /* a. Update shmem->link_status accordingly
         * b. Update link_vars->link_up
         */
@@ -13550,7 +13572,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
         */
        not_kr2_device = (((base_page & 0x8000) == 0) ||
                          (((base_page & 0x8000) &&
-                           ((next_page & 0xe0) == 0x2))));
+                           ((next_page & 0xe0) == 0x20))));
 
        /* In case KR2 is already disabled, check if we need to re-enable it */
        if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
index 814d0eca9b334ea86c862bc617a46f137f04d475..8b3107b2fcc13dd619ae08290f4467c47e8e67b7 100644 (file)
@@ -11447,9 +11447,9 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                }
        }
 
-       /* adjust igu_sb_cnt to MF for E1x */
-       if (CHIP_IS_E1x(bp) && IS_MF(bp))
-               bp->igu_sb_cnt /= E1HVN_MAX;
+       /* adjust igu_sb_cnt to MF for E1H */
+       if (CHIP_IS_E1H(bp) && IS_MF(bp))
+               bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, E1H_MAX_MF_SB_COUNT);
 
        /* port info */
        bnx2x_get_port_hwinfo(bp);
index 3efbb35267c853d576cc3a4d3104ec4ba1a18d1d..14ffb6e56e593d6a371e1036edf02ff7c193eb08 100644 (file)
@@ -7179,6 +7179,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX1_PCI_CTRL                       0x80ca
 #define MDIO_WC_REG_RX2_PCI_CTRL                       0x80da
 #define MDIO_WC_REG_RX3_PCI_CTRL                       0x80ea
+#define MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI             0x80fa
 #define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G          0x8104
 #define MDIO_WC_REG_XGXS_STATUS3                       0x8129
 #define MDIO_WC_REG_PAR_DET_10G_STATUS                 0x8130
index 32c92abf50949fa1494812ab9d3734a5a2f3db1f..18438a504d573082239fe53532035d5516ff2881 100644 (file)
@@ -2038,6 +2038,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        struct bnx2x_vlan_mac_ramrod_params p;
        struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
        struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+       unsigned long flags;
        int read_lock;
        int rc = 0;
 
@@ -2046,8 +2047,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        spin_lock_bh(&exeq->lock);
 
        list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
-               if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
-                   *vlan_mac_flags) {
+               flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        rc = exeq->remove(bp, exeq->owner, exeq_pos);
                        if (rc) {
                                BNX2X_ERR("Failed to remove command\n");
@@ -2080,7 +2082,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
                return read_lock;
 
        list_for_each_entry(pos, &o->head, link) {
-               if (pos->vlan_mac_flags == *vlan_mac_flags) {
+               flags = pos->vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
                        memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
                        rc = bnx2x_config_vlan_mac(bp, &p);
@@ -4382,8 +4386,11 @@ int bnx2x_config_rss(struct bnx2x *bp,
        struct bnx2x_raw_obj *r = &o->raw;
 
        /* Do nothing if only driver cleanup was requested */
-       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+               DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
+                  p->ramrod_flags);
                return 0;
+       }
 
        r->set_pending(r);
 
index 658f4e33abf9281d76e083873cb963c9b47b05f1..6a53c15c85a338c8efbb45ecf3348913272e038a 100644 (file)
@@ -266,6 +266,13 @@ enum {
        BNX2X_DONT_CONSUME_CAM_CREDIT,
        BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
 };
+/* When looking for matching filters, some flags are not interesting */
+#define BNX2X_VLAN_MAC_CMP_MASK        (1 << BNX2X_UC_LIST_MAC | \
+                                1 << BNX2X_ETH_MAC | \
+                                1 << BNX2X_ISCSI_ETH_MAC | \
+                                1 << BNX2X_NETQ_ETH_MAC)
+#define BNX2X_VLAN_MAC_CMP_FLAGS(flags) \
+       ((flags) & BNX2X_VLAN_MAC_CMP_MASK)
 
 struct bnx2x_vlan_mac_ramrod_params {
        /* Object to run the command from */
index 0216d592d0cee4b080a9d33d7776f632bf639453..e7845e5be1c76fb452d8ecb94943326844ab5eaa 100644 (file)
@@ -1209,6 +1209,11 @@ static void bnx2x_vfop_rxmode(struct bnx2x *bp, struct bnx2x_virtf *vf)
                /* next state */
                vfop->state = BNX2X_VFOP_RXMODE_DONE;
 
+               /* record the accept flags in vfdb so hypervisor can modify them
+                * if necessary
+                */
+               bnx2x_vfq(vf, ramrod->cl_id - vf->igu_base_id, accept_flags) =
+                       ramrod->rx_accept_flags;
                vfop->rc = bnx2x_config_rx_mode(bp, ramrod);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 op_err:
@@ -1224,39 +1229,43 @@ op_pending:
        return;
 }
 
+static void bnx2x_vf_prep_rx_mode(struct bnx2x *bp, u8 qid,
+                                 struct bnx2x_rx_mode_ramrod_params *ramrod,
+                                 struct bnx2x_virtf *vf,
+                                 unsigned long accept_flags)
+{
+       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
+
+       memset(ramrod, 0, sizeof(*ramrod));
+       ramrod->cid = vfq->cid;
+       ramrod->cl_id = vfq_cl_id(vf, vfq);
+       ramrod->rx_mode_obj = &bp->rx_mode_obj;
+       ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
+       ramrod->rx_accept_flags = accept_flags;
+       ramrod->tx_accept_flags = accept_flags;
+       ramrod->pstate = &vf->filter_state;
+       ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
+
+       set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
+       set_bit(RAMROD_RX, &ramrod->ramrod_flags);
+       set_bit(RAMROD_TX, &ramrod->ramrod_flags);
+
+       ramrod->rdata = bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
+       ramrod->rdata_mapping = bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+}
+
 int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp,
                          struct bnx2x_virtf *vf,
                          struct bnx2x_vfop_cmd *cmd,
                          int qid, unsigned long accept_flags)
 {
-       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
        struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
 
        if (vfop) {
                struct bnx2x_rx_mode_ramrod_params *ramrod =
                        &vf->op_params.rx_mode;
 
-               memset(ramrod, 0, sizeof(*ramrod));
-
-               /* Prepare ramrod parameters */
-               ramrod->cid = vfq->cid;
-               ramrod->cl_id = vfq_cl_id(vf, vfq);
-               ramrod->rx_mode_obj = &bp->rx_mode_obj;
-               ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
-
-               ramrod->rx_accept_flags = accept_flags;
-               ramrod->tx_accept_flags = accept_flags;
-               ramrod->pstate = &vf->filter_state;
-               ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
-
-               set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
-               set_bit(RAMROD_RX, &ramrod->ramrod_flags);
-               set_bit(RAMROD_TX, &ramrod->ramrod_flags);
-
-               ramrod->rdata =
-                       bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
-               ramrod->rdata_mapping =
-                       bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+               bnx2x_vf_prep_rx_mode(bp, qid, ramrod, vf, accept_flags);
 
                bnx2x_vfop_opset(BNX2X_VFOP_RXMODE_CONFIG,
                                 bnx2x_vfop_rxmode, cmd->done);
@@ -3114,6 +3123,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));
 
@@ -3197,13 +3211,16 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                bnx2x_iov_static_resc(bp, vf);
        }
 
-       /* prepare msix vectors in VF configuration space */
+       /* prepare msix vectors in VF configuration space - the value in the
+        * PCI configuration space should be the index of the last entry,
+        * namely one less than the actual size of the table
+        */
        for (vf_idx = first_vf; vf_idx < first_vf + req_vfs; vf_idx++) {
                bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
                REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
-                      num_vf_queues);
+                      num_vf_queues - 1);
                DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
-                  vf_idx, num_vf_queues);
+                  vf_idx, num_vf_queues - 1);
        }
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
@@ -3431,10 +3448,18 @@ out:
 
 int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
+       struct bnx2x_queue_state_params q_params = {NULL};
+       struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+       struct bnx2x_queue_update_params *update_params;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_rx_mode_ramrod_params rx_ramrod;
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
+       unsigned long vlan_mac_flags = 0;
+       unsigned long ramrod_flags = 0;
        struct bnx2x_virtf *vf = NULL;
-       struct pf_vf_bulletin_content *bulletin = NULL;
+       unsigned long accept_flags;
+       int rc;
 
        /* sanity and init */
        rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
@@ -3452,104 +3477,118 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
        /* update PF's copy of the VF's bulletin. No point in posting the vlan
         * to the VF since it doesn't have anything to do with it. But it useful
         * to store it here in case the VF is not up yet and we can only
-        * configure the vlan later when it does.
+        * configure the vlan later when it does. Treat vlan id 0 as remove the
+        * Host tag.
         */
-       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       if (vlan > 0)
+               bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       else
+               bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
        bulletin->vlan = vlan;
 
        /* is vf initialized and queue set up? */
-       q_logical_state =
-               bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj));
-       if (vf->state == VF_ENABLED &&
-           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
-               /* configure the vlan in device on this vf's queue */
-               unsigned long ramrod_flags = 0;
-               unsigned long vlan_mac_flags = 0;
-               struct bnx2x_vlan_mac_obj *vlan_obj =
-                       &bnx2x_leading_vfq(vf, vlan_obj);
-               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
-               struct bnx2x_queue_state_params q_params = {NULL};
-               struct bnx2x_queue_update_params *update_params;
+       if (vf->state != VF_ENABLED ||
+           bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
+           BNX2X_Q_LOGICAL_STATE_ACTIVE)
+               return rc;
 
-               rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-               if (rc)
-                       return rc;
-               memset(&ramrod_param, 0, sizeof(ramrod_param));
+       /* configure the vlan in device on this vf's queue */
+       vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
+       rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
+       if (rc)
+               return rc;
 
-               /* must lock vfpf channel to protect against vf flows */
-               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       /* must lock vfpf channel to protect against vf flows */
+       bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 
-               /* remove existing vlans */
-               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
-                                         &ramrod_flags);
-               if (rc) {
-                       BNX2X_ERR("failed to delete vlans\n");
-                       rc = -EINVAL;
-                       goto out;
-               }
+       /* remove existing vlans */
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                 &ramrod_flags);
+       if (rc) {
+               BNX2X_ERR("failed to delete vlans\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* need to remove/add the VF's accept_any_vlan bit */
+       accept_flags = bnx2x_leading_vfq(vf, accept_flags);
+       if (vlan)
+               clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+       else
+               set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+       bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
+                             accept_flags);
+       bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
+       bnx2x_config_rx_mode(bp, &rx_ramrod);
+
+       /* configure the new vlan to device */
+       memset(&ramrod_param, 0, sizeof(ramrod_param));
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       ramrod_param.vlan_mac_obj = vlan_obj;
+       ramrod_param.ramrod_flags = ramrod_flags;
+       set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+               &ramrod_param.user_req.vlan_mac_flags);
+       ramrod_param.user_req.u.vlan.vlan = vlan;
+       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+       if (rc) {
+               BNX2X_ERR("failed to configure vlan\n");
+               rc =  -EINVAL;
+               goto out;
+       }
 
-               /* send queue update ramrod to configure default vlan and silent
-                * vlan removal
+       /* send queue update ramrod to configure default vlan and silent
+        * vlan removal
+        */
+       __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+       q_params.cmd = BNX2X_Q_CMD_UPDATE;
+       q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
+       update_params = &q_params.params.update;
+       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                 &update_params->update_flags);
+       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                 &update_params->update_flags);
+       if (vlan == 0) {
+               /* if vlan is 0 then we want to leave the VF traffic
+                * untagged, and leave the incoming traffic untouched
+                * (i.e. do not remove any vlan tags).
+                */
+               __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                           &update_params->update_flags);
+               __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                           &update_params->update_flags);
+       } else {
+               /* configure default vlan to vf queue and set silent
+                * vlan removal (the vf remains unaware of this vlan).
                 */
-               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-               q_params.cmd = BNX2X_Q_CMD_UPDATE;
-               q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
-               update_params = &q_params.params.update;
-               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
                          &update_params->update_flags);
-               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
                          &update_params->update_flags);
+               update_params->def_vlan = vlan;
+               update_params->silent_removal_value =
+                       vlan & VLAN_VID_MASK;
+               update_params->silent_removal_mask = VLAN_VID_MASK;
+       }
 
-               if (vlan == 0) {
-                       /* if vlan is 0 then we want to leave the VF traffic
-                        * untagged, and leave the incoming traffic untouched
-                        * (i.e. do not remove any vlan tags).
-                        */
-                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                   &update_params->update_flags);
-                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                   &update_params->update_flags);
-               } else {
-                       /* configure the new vlan to device */
-                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-                       ramrod_param.vlan_mac_obj = vlan_obj;
-                       ramrod_param.ramrod_flags = ramrod_flags;
-                       ramrod_param.user_req.u.vlan.vlan = vlan;
-                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
-                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-                       if (rc) {
-                               BNX2X_ERR("failed to configure vlan\n");
-                               rc =  -EINVAL;
-                               goto out;
-                       }
-
-                       /* configure default vlan to vf queue and set silent
-                        * vlan removal (the vf remains unaware of this vlan).
-                        */
-                       update_params = &q_params.params.update;
-                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                 &update_params->update_flags);
-                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                 &update_params->update_flags);
-                       update_params->def_vlan = vlan;
-               }
+       /* Update the Queue state */
+       rc = bnx2x_queue_state_change(bp, &q_params);
+       if (rc) {
+               BNX2X_ERR("Failed to configure default VLAN\n");
+               goto out;
+       }
 
-               /* Update the Queue state */
-               rc = bnx2x_queue_state_change(bp, &q_params);
-               if (rc) {
-                       BNX2X_ERR("Failed to configure default VLAN\n");
-                       goto out;
-               }
 
-               /* clear the flag indicating that this VF needs its vlan
-                * (will only be set if the HV configured the Vlan before vf was
-                * up and we were called because the VF came up later
-                */
+       /* clear the flag indicating that this VF needs its vlan
+        * (will only be set if the HV configured the Vlan before vf was
+        * up and we were called because the VF came up later
+        */
 out:
-               vf->cfg_flags &= ~VF_CFG_VLAN;
-               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
-       }
+       vf->cfg_flags &= ~VF_CFG_VLAN;
+       bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
        return rc;
 }
 
index 1ff6a9366629ed88fe79a079391c92e95d1e9baf..8c213fa52174f918d4f445dae554b593b54845db 100644 (file)
@@ -74,6 +74,7 @@ struct bnx2x_vf_queue {
        /* VLANs object */
        struct bnx2x_vlan_mac_obj       vlan_obj;
        atomic_t vlan_count;            /* 0 means vlan-0 is set  ~ untagged */
+       unsigned long accept_flags;     /* last accept flags configured */
 
        /* Queue Slow-path State object */
        struct bnx2x_queue_sp_obj       sp_obj;
index efa8a151d78907d4b17d5f5dd07eaed9b1f2c02c..0756d7dabdd59ae0e58139e07081d9ba02ca5a10 100644 (file)
@@ -208,7 +208,7 @@ static int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id)
                return -EINVAL;
        }
 
-       BNX2X_ERR("valid ME register value: 0x%08x\n", me_reg);
+       DP(BNX2X_MSG_IOV, "valid ME register value: 0x%08x\n", me_reg);
 
        *vf_id = (me_reg & ME_REG_VF_NUM_MASK) >> ME_REG_VF_NUM_SHIFT;
 
@@ -1598,6 +1598,8 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
                if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
                        unsigned long accept = 0;
+                       struct pf_vf_bulletin_content *bulletin =
+                               BP_VF_BULLETIN(bp, vf->index);
 
                        /* covert VF-PF if mask to bnx2x accept flags */
                        if (msg->rx_mask & VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST)
@@ -1617,9 +1619,11 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                __set_bit(BNX2X_ACCEPT_BROADCAST, &accept);
 
                        /* A packet arriving the vf's mac should be accepted
-                        * with any vlan
+                        * with any vlan, unless a vlan has already been
+                        * configured.
                         */
-                       __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
+                       if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)))
+                               __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
 
                        /* set rx-mode */
                        rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd,
@@ -1710,6 +1714,21 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
                        goto response;
                }
        }
+       /* if vlan was set by hypervisor we don't allow guest to config vlan */
+       if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
+               int i;
+
+               /* search for vlan filters */
+               for (i = 0; i < filters->n_mac_vlan_filters; i++) {
+                       if (filters->filters[i].flags &
+                           VFPF_Q_FILTER_VLAN_TAG_VALID) {
+                               BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
+                                         vf->abs_vfid);
+                               vf->op_rc = -EPERM;
+                               goto response;
+                       }
+               }
+       }
 
        /* verify vf_qid */
        if (filters->vf_qid > vf_rxq_count(vf))
@@ -1805,6 +1824,9 @@ static void bnx2x_vf_mbx_update_rss(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf_op_params->rss_result_mask = rss_tlv->rss_result_mask;
 
        /* flags handled individually for backward/forward compatability */
+       vf_op_params->rss_flags = 0;
+       vf_op_params->ramrod_flags = 0;
+
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_DISABLED)
                __set_bit(BNX2X_RSS_MODE_DISABLED, &vf_op_params->rss_flags);
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_REGULAR)
index a9e068423ba0651414cc0c5b23f0eda6937a6c23..15a66e4b1f57a19d2d1e7feb31b557e3809fe6b0 100644 (file)
@@ -7622,7 +7622,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
 {
        u32 base = (u32) mapping & 0xffffffff;
 
-       return (base > 0xffffdcc0) && (base + len + 8 < base);
+       return base + len + 8 < base;
 }
 
 /* Test for TSO DMA buffers that cross into regions which are within MSS bytes
@@ -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..56e0415f8cdff396aca4d6462f2432278e258018 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__)
 
@@ -226,6 +228,25 @@ struct tp_params {
 
        uint32_t dack_re;            /* DACK timer resolution */
        unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
+
+       u32 vlan_pri_map;               /* cached TP_VLAN_PRI_MAP */
+       u32 ingress_config;             /* cached TP_INGRESS_CONFIG */
+
+       /* TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets.  This is a
+        * subset of the set of fields which may be present in the Compressed
+        * Filter Tuple portion of filters and TCP TCB connections.  The
+        * fields which are present are controlled by the TP_VLAN_PRI_MAP.
+        * Since a variable number of fields may or may not be present, their
+        * shifted field positions within the Compressed Filter Tuple may
+        * vary, or not even be present if the field isn't selected in
+        * TP_VLAN_PRI_MAP.  Since some of these fields are needed in various
+        * places we store their offsets here, or a -1 if the field isn't
+        * present.
+        */
+       int vlan_shift;
+       int vnic_shift;
+       int port_shift;
+       int protocol_shift;
 };
 
 struct vpd_params {
@@ -240,6 +261,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 +300,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 +308,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 +570,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 +754,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,8 +939,14 @@ 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_init_tp_params(struct adapter *adap);
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
 int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
index 8b929eeecd2d37cd3b41e32d57bd1fa50402a230..fff02ed1295e5ef7bab408cbe19c46dbd5eedd52 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,
@@ -3052,7 +2986,14 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
                stid += t->stid_base;
-               t->stids_in_use++;
+               /* IPv6 requires max of 520 bits or 16 cells in TCAM
+                * This is equivalent to 4 TIDs. With CLIP enabled it
+                * needs 2 TIDs.
+                */
+               if (family == PF_INET)
+                       t->stids_in_use++;
+               else
+                       t->stids_in_use += 4;
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -3078,7 +3019,8 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
        }
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
-               stid += t->stid_base;
+               stid -= t->nstids;
+               stid += t->sftid_base;
                t->stids_in_use++;
        }
        spin_unlock_bh(&t->stid_lock);
@@ -3090,14 +3032,24 @@ EXPORT_SYMBOL(cxgb4_alloc_sftid);
  */
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        spin_lock_bh(&t->stid_lock);
        if (family == PF_INET)
                __clear_bit(stid, t->stid_bmap);
        else
                bitmap_release_region(t->stid_bmap, stid, 2);
        t->stid_tab[stid].data = NULL;
-       t->stids_in_use--;
+       if (family == PF_INET)
+               t->stids_in_use--;
+       else
+               t->stids_in_use -= 4;
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -3200,6 +3152,7 @@ static int tid_init(struct tid_info *t)
        size_t size;
        unsigned int stid_bmap_size;
        unsigned int natids = t->natids;
+       struct adapter *adap = container_of(t, struct adapter, tids);
 
        stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
        size = t->ntids * sizeof(*t->tid_tab) +
@@ -3233,6 +3186,11 @@ static int tid_init(struct tid_info *t)
                t->afree = t->atid_tab;
        }
        bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
+       /* Reserve stid 0 for T4/T5 adapters */
+       if (!t->stid_base &&
+           (is_t4(adap->params.chip) || is_t5(adap->params.chip)))
+               __set_bit(0, t->stid_bmap);
+
        return 0;
 }
 
@@ -3419,7 +3377,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 +3546,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 +3666,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 +3711,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 +3720,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 +3747,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) >>
@@ -3797,7 +3755,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
                        (adap->fn * 4));
-       lli.filt_mode = adap->filter_mode;
+       lli.filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
                lli.tx_modq[i] = i;
@@ -4245,7 +4203,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        /* Check to make sure the filter requested is writable ...
@@ -4271,12 +4229,17 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
                        f->fs.val.lip[i] = val[i];
                        f->fs.mask.lip[i] = ~0;
                }
-               if (adap->filter_mode & F_PORT) {
+               if (adap->params.tp.vlan_pri_map & F_PORT) {
                        f->fs.val.iport = port;
                        f->fs.mask.iport = mask;
                }
        }
 
+       if (adap->params.tp.vlan_pri_map & F_PROTOCOL) {
+               f->fs.val.proto = IPPROTO_TCP;
+               f->fs.mask.proto = ~0;
+       }
+
        f->fs.dirsteer = 1;
        f->fs.iq = queue;
        /* Mark filter as locked */
@@ -4303,7 +4266,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        f = &adap->tids.ftid_tab[stid];
@@ -4483,7 +4446,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 +4631,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 +4651,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 +4667,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 +4744,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 +4804,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 +4811,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 +4821,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 +5070,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.
  */
@@ -5096,7 +5121,7 @@ static int adap_init0(struct adapter *adap)
        enum dev_state state;
        u32 params[7], val[7];
        struct fw_caps_config_cmd caps_cmd;
-       int reset = 1, j;
+       int reset = 1;
 
        /*
         * Contact FW, advertising Master capability (and potentially forcing
@@ -5123,44 +5148,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 +5280,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);
                                }
@@ -5428,21 +5463,11 @@ static int adap_init0(struct adapter *adap)
        /*
         * These are finalized by FW initialization, load their values now.
         */
-       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
-       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
-       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
        t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
        t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
                     adap->params.b_wnd);
 
-       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
-       for (j = 0; j < NCHAN; j++)
-               adap->params.tp.tx_modq[j] = j;
-
-       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
-                        &adap->filter_mode, 1,
-                        TP_VLAN_PRI_MAP);
-
+       t4_init_tp_params(adap);
        adap->flags |= FW_OK;
        return 0;
 
@@ -5787,7 +5812,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 +5935,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 +6089,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 +6141,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 6f21f2451c3052a24ecd2e8d8d16ee9bdf9996fe..4dd0a82533e442f8b330c5ede554359ea450a087 100644 (file)
@@ -131,7 +131,14 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
 
 static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
 }
 
index 29878098101eb07771626399a1c5050a9544d055..cb05be905defdceb0e2d0b76386dcd224169b5b0 100644 (file)
@@ -45,6 +45,7 @@
 #include "l2t.h"
 #include "t4_msg.h"
 #include "t4fw_api.h"
+#include "t4_regs.h"
 
 #define VLAN_NONE 0xfff
 
@@ -411,6 +412,40 @@ done:
 }
 EXPORT_SYMBOL(cxgb4_l2t_get);
 
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t)
+{
+       struct adapter *adap = netdev2adap(dev);
+       struct tp_params *tp = &adap->params.tp;
+       u64 ntuple = 0;
+
+       /* Initialize each of the fields which we care about which are present
+        * in the Compressed Filter Tuple.
+        */
+       if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
+               ntuple |= (F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
+
+       if (tp->port_shift >= 0)
+               ntuple |= (u64)l2t->lport << tp->port_shift;
+
+       if (tp->protocol_shift >= 0)
+               ntuple |= (u64)IPPROTO_TCP << tp->protocol_shift;
+
+       if (tp->vnic_shift >= 0) {
+               u32 viid = cxgb4_port_viid(dev);
+               u32 vf = FW_VIID_VIN_GET(viid);
+               u32 pf = FW_VIID_PFN_GET(viid);
+               u32 vld = FW_VIID_VIVLD_GET(viid);
+
+               ntuple |= (u64)(V_FT_VNID_ID_VF(vf) |
+                               V_FT_VNID_ID_PF(pf) |
+                               V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
+       }
+
+       return ntuple;
+}
+EXPORT_SYMBOL(cxgb4_select_ntuple);
+
 /*
  * Called when address resolution fails for an L2T entry to handle packets
  * on the arpq head.  If a packet specifies a failure handler it is invoked,
index 108c0f1fce1c4e5776b687538d741cd6f771a909..85eb5c71358d80ad91e21df648289047165dbf39 100644 (file)
@@ -98,7 +98,8 @@ int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
 struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
                                const struct net_device *physdev,
                                unsigned int priority);
-
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t);
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
 struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
 int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
index ac311f5f3eb9590d1d9b5fb3bb0a9c3f0fac5ce7..cc3511a5cd0c0f9ea54e0d186878821f3dad8096 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;
@@ -2581,7 +2581,7 @@ static int t4_sge_init_soft(struct adapter *adap)
        #undef READ_FL_BUF
 
        if (fl_small_pg != PAGE_SIZE ||
-           (fl_large_pg != 0 && (fl_large_pg <= fl_small_pg ||
+           (fl_large_pg != 0 && (fl_large_pg < fl_small_pg ||
                                  (fl_large_pg & (fl_large_pg-1)) != 0))) {
                dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n",
                        fl_small_pg, fl_large_pg);
@@ -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..e1413eacdbd20ab2233fd3217222bb76e6b779d1 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);
 
        /*
@@ -3746,6 +3808,109 @@ int t4_prep_adapter(struct adapter *adapter)
        return 0;
 }
 
+/**
+ *      t4_init_tp_params - initialize adap->params.tp
+ *      @adap: the adapter
+ *
+ *      Initialize various fields of the adapter's TP Parameters structure.
+ */
+int t4_init_tp_params(struct adapter *adap)
+{
+       int chan;
+       u32 v;
+
+       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
+       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
+       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
+
+       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+       for (chan = 0; chan < NCHAN; chan++)
+               adap->params.tp.tx_modq[chan] = chan;
+
+       /* Cache the adapter's Compressed Filter Mode and global Incress
+        * Configuration.
+        */
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.vlan_pri_map, 1,
+                        TP_VLAN_PRI_MAP);
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.ingress_config, 1,
+                        TP_INGRESS_CONFIG);
+
+       /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+        * shift positions of several elements of the Compressed Filter Tuple
+        * for this adapter which we need frequently ...
+        */
+       adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+       adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+       adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
+       adap->params.tp.protocol_shift = t4_filter_field_shift(adap,
+                                                              F_PROTOCOL);
+
+       /* If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+        * represents the presense of an Outer VLAN instead of a VNIC ID.
+        */
+       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
+               adap->params.tp.vnic_shift = -1;
+
+       return 0;
+}
+
+/**
+ *      t4_filter_field_shift - calculate filter field shift
+ *      @adap: the adapter
+ *      @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ *
+ *      Return the shift position of a filter field within the Compressed
+ *      Filter Tuple.  The filter field is specified via its selection bit
+ *      within TP_VLAN_PRI_MAL (filter mode).  E.g. F_VLAN.
+ */
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
+{
+       unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+       unsigned int sel;
+       int field_shift;
+
+       if ((filter_mode & filter_sel) == 0)
+               return -1;
+
+       for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
+               switch (filter_mode & sel) {
+               case F_FCOE:
+                       field_shift += W_FT_FCOE;
+                       break;
+               case F_PORT:
+                       field_shift += W_FT_PORT;
+                       break;
+               case F_VNIC_ID:
+                       field_shift += W_FT_VNIC_ID;
+                       break;
+               case F_VLAN:
+                       field_shift += W_FT_VLAN;
+                       break;
+               case F_TOS:
+                       field_shift += W_FT_TOS;
+                       break;
+               case F_PROTOCOL:
+                       field_shift += W_FT_PROTOCOL;
+                       break;
+               case F_ETHERTYPE:
+                       field_shift += W_FT_ETHERTYPE;
+                       break;
+               case F_MACMATCH:
+                       field_shift += W_FT_MACMATCH;
+                       break;
+               case F_MPSHITTYPE:
+                       field_shift += W_FT_MPSHITTYPE;
+                       break;
+               case F_FRAGMENTATION:
+                       field_shift += W_FT_FRAGMENTATION;
+                       break;
+               }
+       }
+       return field_shift;
+}
+
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
        u8 addr[6];
index ef146c0ba4814ef5abff64794075b9d5e806c62b..4082522d81408bf0a23cff8eaf9700bef14533a9 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 A_TP_TX_SCHED_PCMD 0x25
 
+#define S_VNIC    11
+#define V_VNIC(x) ((x) << S_VNIC)
+#define F_VNIC    V_VNIC(1U)
+
+#define S_FRAGMENTATION    9
+#define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION)
+#define F_FRAGMENTATION    V_FRAGMENTATION(1U)
+
+#define S_MPSHITTYPE    8
+#define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE)
+#define F_MPSHITTYPE    V_MPSHITTYPE(1U)
+
+#define S_MACMATCH    7
+#define V_MACMATCH(x) ((x) << S_MACMATCH)
+#define F_MACMATCH    V_MACMATCH(1U)
+
+#define S_ETHERTYPE    6
+#define V_ETHERTYPE(x) ((x) << S_ETHERTYPE)
+#define F_ETHERTYPE    V_ETHERTYPE(1U)
+
+#define S_PROTOCOL    5
+#define V_PROTOCOL(x) ((x) << S_PROTOCOL)
+#define F_PROTOCOL    V_PROTOCOL(1U)
+
+#define S_TOS    4
+#define V_TOS(x) ((x) << S_TOS)
+#define F_TOS    V_TOS(1U)
+
+#define S_VLAN    3
+#define V_VLAN(x) ((x) << S_VLAN)
+#define F_VLAN    V_VLAN(1U)
+
+#define S_VNIC_ID    2
+#define V_VNIC_ID(x) ((x) << S_VNIC_ID)
+#define F_VNIC_ID    V_VNIC_ID(1U)
+
 #define S_PORT    1
 #define V_PORT(x) ((x) << S_PORT)
 #define F_PORT    V_PORT(1U)
 
+#define S_FCOE    0
+#define V_FCOE(x) ((x) << S_FCOE)
+#define F_FCOE    V_FCOE(1U)
+
 #define NUM_MPS_CLS_SRAM_L_INSTANCES 336
 #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
 
 #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)
+
+/* TP_VLAN_PRI_MAP controls which subset of fields will be present in the
+ * Compressed Filter Tuple for LE filters.  Each bit set in TP_VLAN_PRI_MAP
+ * selects for a particular field being present.  These fields, when present
+ * in the Compressed Filter Tuple, have the following widths in bits.
+ */
+#define W_FT_FCOE                       1
+#define W_FT_PORT                       3
+#define W_FT_VNIC_ID                    17
+#define W_FT_VLAN                       17
+#define W_FT_TOS                        8
+#define W_FT_PROTOCOL                   8
+#define W_FT_ETHERTYPE                  16
+#define W_FT_MACMATCH                   9
+#define W_FT_MPSHITTYPE                 3
+#define W_FT_FRAGMENTATION              1
+
+/* Some of the Compressed Filter Tuple fields have internal structure.  These
+ * bit shifts/masks describe those structures.  All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD                   16
+#define V_FT_VLAN_VLD(x)                ((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD                   V_FT_VLAN_VLD(1U)
+
+#define S_FT_VNID_ID_VF                 0
+#define V_FT_VNID_ID_VF(x)              ((x) << S_FT_VNID_ID_VF)
+
+#define S_FT_VNID_ID_PF                 7
+#define V_FT_VNID_ID_PF(x)              ((x) << S_FT_VNID_ID_PF)
+
+#define S_FT_VNID_ID_VLD                16
+#define V_FT_VNID_ID_VLD(x)             ((x) << S_FT_VNID_ID_VLD)
+
 #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..4ccaf9af6fc90cde0d9d13490fa5753e480c543e 100644 (file)
@@ -104,6 +104,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE3_MAX_RSS_QS         16
 #define BE3_MAX_TX_QS          16
 #define BE3_MAX_EVT_QS         16
+#define BE3_SRIOV_MAX_EVT_QS   8
 
 #define MAX_RX_QS              32
 #define MAX_EVT_QS             32
@@ -480,7 +481,7 @@ struct be_adapter {
        struct list_head entry;
 
        u32 flash_status;
-       struct completion flash_compl;
+       struct completion et_cmd_compl;
 
        struct be_resources res;        /* resources available for the func */
        u16 num_vfs;                    /* Number of VFs provisioned by PF */
@@ -503,6 +504,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..94c35c8d799d9f1e4f4b9fd78121600ad600505e 100644 (file)
@@ -141,11 +141,17 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                subsystem = resp_hdr->subsystem;
        }
 
+       if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
+           subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
+               complete(&adapter->et_cmd_compl);
+               return 0;
+       }
+
        if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
             (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
            (subsystem == CMD_SUBSYSTEM_COMMON)) {
                adapter->flash_status = compl_status;
-               complete(&adapter->flash_compl);
+               complete(&adapter->et_cmd_compl);
        }
 
        if (compl_status == MCC_STATUS_SUCCESS) {
@@ -1032,6 +1038,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,
@@ -2010,6 +2023,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
                        0x3ea83c02, 0x4a110304};
        int status;
 
+       if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
+               return 0;
+
        if (mutex_lock_interruptible(&adapter->mbox_lock))
                return -1;
 
@@ -2153,7 +2169,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
                                         msecs_to_jiffies(60000)))
                status = -1;
        else
@@ -2248,8 +2264,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
-                       msecs_to_jiffies(40000)))
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
+                                        msecs_to_jiffies(40000)))
                status = -1;
        else
                status = adapter->flash_status;
@@ -2360,6 +2376,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_loopback_test *req;
+       struct be_cmd_resp_loopback_test *resp;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2374,8 +2391,8 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, NULL);
-       req->hdr.timeout = cpu_to_le32(4);
 
+       req->hdr.timeout = cpu_to_le32(15);
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
        req->dest_port = cpu_to_le32(port_num);
@@ -2383,12 +2400,15 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
        req->num_pkts = cpu_to_le32(num_pkts);
        req->loopback_type = cpu_to_le32(loopback_type);
 
-       status = be_mcc_notify_wait(adapter);
-       if (!status) {
-               struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
-               status = le32_to_cpu(resp->status);
-       }
+       be_mcc_notify(adapter);
+
+       spin_unlock_bh(&adapter->mcc_lock);
+
+       wait_for_completion(&adapter->et_cmd_compl);
+       resp = embedded_payload(wrb);
+       status = le32_to_cpu(resp->status);
 
+       return status;
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
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..bf40fdaecfa3e89b96fb90336cb26f909642de36 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);
                }
@@ -2736,13 +2744,16 @@ static int be_rx_qs_create(struct be_adapter *adapter)
                if (!BEx_chip(adapter))
                        adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 |
                                                RSS_ENABLE_UDP_IPV6;
+       } else {
+               /* Disable RSS, if only default RX Q is created */
+               adapter->rss_flags = RSS_ENABLE_NONE;
+       }
 
-               rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
-                                      128);
-               if (rc) {
-                       adapter->rss_flags = 0;
-                       return rc;
-               }
+       rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
+                              128);
+       if (rc) {
+               adapter->rss_flags = RSS_ENABLE_NONE;
+               return rc;
        }
 
        /* First time posting */
@@ -2932,28 +2943,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;
 }
@@ -3109,11 +3127,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
        bool use_sriov = false;
+       int max_vfs;
 
-       if (BE3_chip(adapter) && sriov_want(adapter)) {
-               int max_vfs;
+       max_vfs = pci_sriov_get_totalvfs(pdev);
 
-               max_vfs = pci_sriov_get_totalvfs(pdev);
+       if (BE3_chip(adapter) && sriov_want(adapter)) {
                res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
                use_sriov = res->max_vfs;
        }
@@ -3144,7 +3162,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
                                           BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
        res->max_rx_qs = res->max_rss_qs + 1;
 
-       res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1;
+       if (be_physfn(adapter))
+               res->max_evt_qs = (max_vfs > 0) ?
+                                       BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
+       else
+               res->max_evt_qs = 1;
 
        res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
        if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
@@ -3253,12 +3275,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 +3834,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) {
@@ -4190,7 +4212,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
 
-       init_completion(&adapter->flash_compl);
+       init_completion(&adapter->et_cmd_compl);
        pci_save_state(adapter->pdev);
        return 0;
 
@@ -4365,13 +4387,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 +4621,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 +4657,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..50bb71c663e20a010c9a4390c3d1c38726037c85 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;
@@ -432,6 +428,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(bdp, fep);
 
+       skb_tx_timestamp(skb);
+
        fep->cur_tx = bdp;
 
        if (fep->cur_tx == fep->dirty_tx)
@@ -440,8 +438,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* Trigger transmission start */
        writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
@@ -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 895450e9bb3cfe81d22f19148b4a52d9fc14352a..ff2d806eaef71bc2a7a861a8971c228cd6856e2a 100644 (file)
@@ -718,8 +718,11 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
        e1000_release_phy_80003es2lan(hw);
 
        /* Disable IBIST slave mode (far-end loopback) */
-       e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-                                       &kum_reg_data);
+       ret_val =
+           e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                           &kum_reg_data);
+       if (ret_val)
+               return ret_val;
        kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
        e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
                                         kum_reg_data);
index 8d3945ab7334840684db42ea6eefa9bafc52c061..c30d41d6e4260d4830c82ccb1dd6b0bcec3bfa1d 100644 (file)
@@ -6174,7 +6174,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int e1000_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -6193,7 +6193,7 @@ static int e1000_resume(struct device *dev)
 
        return __e1000_resume(pdev);
 }
-#endif /* CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_RUNTIME
 static int e1000_runtime_suspend(struct device *dev)
index da2be59505c06226b4cd79f9e8cc120945ca1d17..20e71f4ca4261f99694b04eccd3647906326239d 100644 (file)
@@ -1757,19 +1757,23 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                 * it across the board.
                 */
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
-               if (ret_val)
+               if (ret_val) {
                        /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               msleep(usec_interval / 1000);
+                       else
+                               udelay(usec_interval);
+               }
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & BMSR_LSTATUS)
                        break;
                if (usec_interval >= 1000)
-                       mdelay(usec_interval / 1000);
+                       msleep(usec_interval / 1000);
                else
                        udelay(usec_interval);
        }
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..5bcc870f8367f803c309f5c28115cded7284748c 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;
@@ -6827,12 +6827,20 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
        return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
 
-#ifdef IXGBE_FCOE
-static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
+                             void *accel_priv)
 {
+       struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
+#ifdef IXGBE_FCOE
        struct ixgbe_adapter *adapter;
        struct ixgbe_ring_feature *f;
        int txq;
+#endif
+
+       if (fwd_adapter)
+               return skb->queue_mapping + fwd_adapter->tx_base_queue;
+
+#ifdef IXGBE_FCOE
 
        /*
         * only execute the code below if protocol is FCoE
@@ -6858,9 +6866,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
                txq -= f->indices;
 
        return txq + f->offset;
+#else
+       return __netdev_pick_tx(dev, skb);
+#endif
 }
 
-#endif
 netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                          struct ixgbe_adapter *adapter,
                          struct ixgbe_ring *tx_ring)
@@ -7629,27 +7639,11 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
        kfree(fwd_adapter);
 }
 
-static netdev_tx_t ixgbe_fwd_xmit(struct sk_buff *skb,
-                                 struct net_device *dev,
-                                 void *priv)
-{
-       struct ixgbe_fwd_adapter *fwd_adapter = priv;
-       unsigned int queue;
-       struct ixgbe_ring *tx_ring;
-
-       queue = skb->queue_mapping + fwd_adapter->tx_base_queue;
-       tx_ring = fwd_adapter->real_adapter->tx_ring[queue];
-
-       return __ixgbe_xmit_frame(skb, dev, tx_ring);
-}
-
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
        .ndo_start_xmit         = ixgbe_xmit_frame,
-#ifdef IXGBE_FCOE
        .ndo_select_queue       = ixgbe_select_queue,
-#endif
        .ndo_set_rx_mode        = ixgbe_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbe_set_mac,
@@ -7689,7 +7683,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
        .ndo_dfwd_add_station   = ixgbe_fwd_add,
        .ndo_dfwd_del_station   = ixgbe_fwd_del,
-       .ndo_dfwd_start_xmit    = ixgbe_fwd_xmit,
 };
 
 /**
@@ -7986,10 +7979,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 d6f0c0d8cf11ddb395617e2749bbf25329cae42c..72084f70adbba84c5b3e4df8f890155c2643a13b 100644 (file)
@@ -291,7 +291,9 @@ static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
        int err;
+#ifdef CONFIG_PCI_IOV
        u32 current_flags = adapter->flags;
+#endif
 
        err = ixgbe_disable_sriov(adapter);
 
index 6a6c1f76d8e04406b1c6de12820a48a7d27337fd..ec94a20d709952d1f678f69ac7778205f75e8ffe 100644 (file)
@@ -619,7 +619,8 @@ ltq_etop_set_multicast_list(struct net_device *dev)
 }
 
 static u16
-ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     void *accel_priv)
 {
        /* we are currently only using the first queue */
        return 0;
index 7354960b583bc83b45a8aadd001c03c456912f81..c4eeb69a5beee6f4e4214746b9c958c614e64beb 100644 (file)
@@ -92,6 +92,12 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
                        if (time_is_before_jiffies(end))
                                ++timedout;
                } else {
+                       /* wait_event_timeout does not guarantee a delay of at
+                        * least one whole jiffie, so timeout must be no less
+                        * than two.
+                        */
+                       if (timeout < 2)
+                               timeout = 2;
                        wait_event_timeout(dev->smi_busy_wait,
                                           orion_mdio_smi_is_done(dev),
                                           timeout);
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 f54ebd5a1702457524bf5fc6918fbdf191a5d73f..a7fcd593b2dbb397bdf3d2a810ff42f71d0806b6 100644 (file)
@@ -592,7 +592,8 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
        }
 }
 
-u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        u16 rings_p_up = priv->num_tx_rings_p_up;
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 f3758de59c05f5adeb195661814ff4041b405c4a..d5758adceaa2f264b74d83e99f8091b7e1ead948 100644 (file)
@@ -714,7 +714,8 @@ int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
-u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
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 7692dfd4f262db9045f285aadc194c1713fb724a..cc68657f05368d5642b62091bc6dbec1bc00bd1c 100644 (file)
@@ -1604,13 +1604,13 @@ netxen_process_lro(struct netxen_adapter *adapter,
        u32 seq_number;
        u8 vhdr_len = 0;
 
-       if (unlikely(ring > adapter->max_rds_rings))
+       if (unlikely(ring >= adapter->max_rds_rings))
                return NULL;
 
        rds_ring = &recv_ctx->rds_rings[ring];
 
        index = netxen_get_lro_sts_refhandle(sts_data0);
-       if (unlikely(index > rds_ring->num_desc))
+       if (unlikely(index >= rds_ring->num_desc))
                return NULL;
 
        buffer = &rds_ring->rx_buf_arr[index];
index 631ea0ac1cd89c47bddb863c56f04c28469bd745..f2a7c7166e2408a747dd03ef0fc456ba6121486c 100644 (file)
@@ -487,6 +487,7 @@ struct qlcnic_hardware_context {
        struct qlcnic_mailbox *mailbox;
        u8 extend_lb_time;
        u8 phys_port_id[ETH_ALEN];
+       u8 lb_mode;
 };
 
 struct qlcnic_adapter_stats {
@@ -578,6 +579,8 @@ struct qlcnic_host_tx_ring {
        dma_addr_t phys_addr;
        dma_addr_t hw_cons_phys_addr;
        struct netdev_queue *txq;
+       /* Lock to protect Tx descriptors cleanup */
+       spinlock_t tx_clean_lock;
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -808,6 +811,7 @@ struct qlcnic_mac_list_s {
 
 #define QLCNIC_ILB_MODE                0x1
 #define QLCNIC_ELB_MODE                0x2
+#define QLCNIC_LB_MODE_MASK    0x3
 
 #define QLCNIC_LINKEVENT       0x1
 #define QLCNIC_LB_RESPONSE     0x2
@@ -1093,7 +1097,6 @@ struct qlcnic_adapter {
        struct qlcnic_filter_hash rx_fhash;
        struct list_head vf_mc_list;
 
-       spinlock_t tx_clean_lock;
        spinlock_t mac_learn_lock;
        /* spinlock for catching rcv filters for eswitch traffic */
        spinlock_t rx_mac_learn_lock;
@@ -1708,6 +1711,7 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
 void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);
+void qlcnic_update_stats(struct qlcnic_adapter *);
 
 /* Adapter hardware abstraction */
 struct qlcnic_hardware_ops {
index b1cb0ffb15c70d1970f3cbebab28ff7f8e8530ce..f776f99f79155ea42d3371b7e9aadcc901421898 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);
 }
@@ -1704,12 +1684,6 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
-       /* Make sure carrier is off and queue is stopped during loopback */
-       if (netif_running(netdev)) {
-               netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
-       }
-
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2141,6 +2115,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
        ahw->link_autoneg = MSB(MSW(data[3]));
        ahw->module_type = MSB(LSW(data[3]));
        ahw->has_link_events = 1;
+       ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
        qlcnic_advert_link_change(adapter, link_status);
 }
 
@@ -3754,6 +3729,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 +3786,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..6b08194aa0d4900f8e29a4c5eca433f1d1709d9c 100644 (file)
@@ -167,27 +167,35 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 #define QLCNIC_TEST_LEN        ARRAY_SIZE(qlcnic_gstrings_test)
 
-static inline int qlcnic_82xx_statistics(void)
+static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_device_gstrings_stats) +
-              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
-static inline int qlcnic_83xx_statistics(void)
+static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
               ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
-              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
+              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
 static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
 {
-       if (qlcnic_82xx_check(adapter))
-               return qlcnic_82xx_statistics();
-       else if (qlcnic_83xx_check(adapter))
-               return qlcnic_83xx_statistics();
-       else
-               return -1;
+       int len = -1;
+
+       if (qlcnic_82xx_check(adapter)) {
+               len = qlcnic_82xx_statistics(adapter);
+               if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+                       len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
+       } else if (qlcnic_83xx_check(adapter)) {
+               len = qlcnic_83xx_statistics(adapter);
+       }
+
+       return len;
 }
 
 #define        QLCNIC_TX_INTR_NOT_CONFIGURED   0X78563412
@@ -667,30 +675,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;
@@ -925,18 +928,13 @@ static int qlcnic_eeprom_test(struct net_device *dev)
 
 static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 {
-       int len;
 
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        switch (sset) {
        case ETH_SS_TEST:
                return QLCNIC_TEST_LEN;
        case ETH_SS_STATS:
-               len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN;
-               if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-                   qlcnic_83xx_check(adapter))
-                       return len;
-               return qlcnic_82xx_statistics();
+               return qlcnic_dev_statistics_len(adapter);
        default:
                return -EOPNOTSUPP;
        }
@@ -948,6 +946,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 +979,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;
@@ -1270,7 +1270,7 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
        return data;
 }
 
-static void qlcnic_update_stats(struct qlcnic_adapter *adapter)
+void qlcnic_update_stats(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;
index e9c21e5d0ca95c7cc08df0c5f29cca2f7b473ba4..c4262c23ed7c77b009f6c5cebf233a54ebfd685b 100644 (file)
@@ -134,6 +134,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
        struct qlcnic_skb_frag *buffrag;
        int i, j;
 
+       spin_lock(&tx_ring->tx_clean_lock);
+
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -157,6 +159,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
                }
                cmd_buf++;
        }
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 }
 
 void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
index 0149c94953474e6ad0ffd56b93cc440c67e77687..ad1531ae3aa8f8e3cda7f56c36bb12ec46694464 100644 (file)
@@ -687,17 +687,15 @@ 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) {
+               /* Do not advertise Link up if the port is in loopback mode */
+               if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode)
+                       return;
+
                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);
        }
 }
 
@@ -784,7 +782,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct qlcnic_skb_frag *frag;
 
-       if (!spin_trylock(&adapter->tx_clean_lock))
+       if (!spin_trylock(&tx_ring->tx_clean_lock))
                return 1;
 
        sw_consumer = tx_ring->sw_consumer;
@@ -813,8 +811,9 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
                        break;
        }
 
+       tx_ring->sw_consumer = sw_consumer;
+
        if (count && netif_running(netdev)) {
-               tx_ring->sw_consumer = sw_consumer;
                smp_mb();
                if (netif_tx_queue_stopped(tx_ring->txq) &&
                    netif_carrier_ok(netdev)) {
@@ -840,7 +839,8 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
         */
        hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
        done = (sw_consumer == hw_consumer);
-       spin_unlock(&adapter->tx_clean_lock);
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 
        return done;
 }
index 05c1eef8df1325359ef1bf73df8344492a95876d..550791b8fbae98404f4be790520d0c4985871802 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;
        }
 
@@ -1755,7 +1756,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (qlcnic_sriov_vf_check(adapter))
                qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
        smp_mb();
-       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
        adapter->ahw->linkup = 0;
        netif_tx_disable(netdev);
@@ -1776,7 +1776,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
        for (ring = 0; ring < adapter->drv_tx_rings; ring++)
                qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
-       spin_unlock(&adapter->tx_clean_lock);
 }
 
 /* Usage: During suspend and firmware recovery module */
@@ -1940,7 +1939,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;
 
@@ -2172,6 +2170,7 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
                }
                memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
                tx_ring->cmd_buf_arr = cmd_buf_arr;
+               spin_lock_init(&tx_ring->tx_clean_lock);
        }
 
        if (qlcnic_83xx_check(adapter) ||
@@ -2299,7 +2298,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        rwlock_init(&adapter->ahw->crb_lock);
        mutex_init(&adapter->ahw->mem_lock);
 
-       spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
 
        qlcnic_register_dcb(adapter);
@@ -2782,6 +2780,9 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct net_device_stats *stats = &netdev->stats;
 
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               qlcnic_update_stats(adapter);
+
        stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
        stats->tx_packets = adapter->stats.xmitfinished;
        stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
index 686f460b15022b4b2b7759ad29493a64a1f84592..024f8161d2fe1cccd0e97cc2a1eccd67371b8ab4 100644 (file)
@@ -75,7 +75,6 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
        num_vfs = sriov->num_vfs;
        max = num_vfs + 1;
        info->bit_offsets = 0xffff;
-       info->max_tx_ques = res->num_tx_queues / max;
        info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
        num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC;
 
@@ -86,6 +85,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_mac_filters = temp;
                info->min_tx_bw = 0;
                info->max_tx_bw = MAX_BW;
+               info->max_tx_ques = res->num_tx_queues - sriov->num_vfs;
        } else {
                id = qlcnic_sriov_func_to_index(adapter, func);
                if (id < 0)
@@ -95,6 +95,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_bw = vp->max_tx_bw;
                info->max_rx_ucast_mac_filters = num_vf_macs;
                info->max_tx_mac_filters = num_vf_macs;
+               info->max_tx_ques = QLCNIC_SINGLE_RING;
        }
 
        info->max_rx_ip_addr = res->num_destip / max;
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 8a7a23a84ac5c3b6a7b7d4979e8c5866097895a5..797b56a0efc4a4e7ab1ff5c9af1f0e50f29e9d17 100644 (file)
@@ -622,17 +622,15 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
                return -EOPNOTSUPP;
 
-       if (netif_msg_hw(priv)) {
-               if (priv->dma_cap.time_stamp) {
-                       pr_debug("IEEE 1588-2002 Time Stamp supported\n");
-                       priv->adv_ts = 0;
-               }
-               if (priv->dma_cap.atime_stamp && priv->extend_desc) {
-                       pr_debug
-                           ("IEEE 1588-2008 Advanced Time Stamp supported\n");
-                       priv->adv_ts = 1;
-               }
-       }
+       priv->adv_ts = 0;
+       if (priv->dma_cap.atime_stamp && priv->extend_desc)
+               priv->adv_ts = 1;
+
+       if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
+               pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+
+       if (netif_msg_hw(priv) && priv->adv_ts)
+               pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
 
        priv->hw->ptp = &stmmac_ptp;
        priv->hwts_tx_en = 0;
index b8b0eeed0f92bb68f34e1dac22e1f072faec77ce..7680581ebe12fe58a60de42b419467e3f2f065f7 100644 (file)
@@ -56,7 +56,7 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
 
        priv->hw->ptp->config_addend(priv->ioaddr, addend);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
@@ -91,7 +91,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
 
        priv->hw->ptp->adjust_systime(priv->ioaddr, sec, nsec, neg_adj);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
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..5330fd298705e06181b7d1a2a1557e0cea27e85c 100644 (file)
@@ -740,6 +740,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
                /* set speed_in input in case RMII mode is used in 100Mbps */
                if (phy->speed == 100)
                        mac_control |= BIT(15);
+               else if (phy->speed == 10)
+                       mac_control |= BIT(18); /* In Band mode */
 
                *link = true;
        } else {
@@ -1151,6 +1153,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 +1205,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 +1825,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                }
 
                i++;
+               if (i == data->slaves)
+                       break;
        }
 
        return 0;
@@ -1983,9 +1994,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)) {
@@ -2091,7 +2108,7 @@ static int cpsw_probe(struct platform_device *pdev)
        while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
                for (i = res->start; i <= res->end; i++) {
                        if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
-                                            dev_name(priv->dev), priv)) {
+                                            dev_name(&pdev->dev), priv)) {
                                dev_err(priv->dev, "error attaching irq\n");
                                goto clean_ale_ret;
                        }
@@ -2155,8 +2172,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 628b736e5ae776fcf00333bed8c355e4b518314e..0e9fb3301b1136e333cdd3d9bc62bcacc89dd4bb 100644 (file)
@@ -2080,7 +2080,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 }
 
 /* Return subqueue id on this core (one per core). */
-static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
+                                void *accel_priv)
 {
        return smp_processor_id();
 }
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 3169252613faae400904201fa5ad9f1a7decf1cf..5d78c1d08abd60fcc6bcee5dea5ab178a2a166da 100644 (file)
@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HDLCDRVCTL_CALIBRATE:
                if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
+               if (bi.data.calibrate > INT_MAX / s->par.bitrate)
+                       return -EINVAL;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
                return 0;
 
index 1971411574db1c7ae2dd6549490ab6975e816cd1..61dd2447e1bb4eedb5d8e6b72abcf21e9f273afb 100644 (file)
@@ -1057,6 +1057,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
 
        case SIOCYAMGCFG:
+               memset(&yi, 0, sizeof(yi));
                yi.cfg.mask = 0xffffffff;
                yi.cfg.iobase = yp->iobase;
                yi.cfg.irq = yp->irq;
index 524f713f60170b2d5632bbac6958ae0529a80b1c..71baeb3ed905cfa9ed930ab9f7ac63c3edd206b7 100644 (file)
@@ -261,9 +261,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        struct sk_buff *skb;
 
        net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
-       if (!net) {
-               netdev_err(net, "got receive callback but net device"
-                       " not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED) {
                packet->status = NVSP_STAT_FAIL;
                return 0;
        }
@@ -327,7 +325,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);
@@ -436,19 +433,11 @@ static int netvsc_probe(struct hv_device *dev,
        SET_ETHTOOL_OPS(net, &ethtool_ops);
        SET_NETDEV_DEV(net, &dev->device);
 
-       ret = register_netdev(net);
-       if (ret != 0) {
-               pr_err("Unable to register netdev.\n");
-               free_netdev(net);
-               goto out;
-       }
-
        /* Notify the netvsc driver of the new device */
        device_info.ring_size = ring_size;
        ret = rndis_filter_device_add(dev, &device_info);
        if (ret != 0) {
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               unregister_netdev(net);
                free_netdev(net);
                hv_set_drvdata(dev, NULL);
                return ret;
@@ -457,7 +446,13 @@ static int netvsc_probe(struct hv_device *dev,
 
        netif_carrier_on(net);
 
-out:
+       ret = register_netdev(net);
+       if (ret != 0) {
+               pr_err("Unable to register netdev.\n");
+               rndis_filter_device_remove(dev);
+               free_netdev(net);
+       }
+
        return ret;
 }
 
index acf93798dc675929394e82ffed96cd1616c3a31d..bc8faaec33f5afb0bbf7efdd88cd082122c3cc7f 100644 (file)
@@ -299,7 +299,7 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 
        if (vlan->fwd_priv) {
                skb->dev = vlan->lowerdev;
-               ret = dev_hard_start_xmit(skb, skb->dev, NULL, vlan->fwd_priv);
+               ret = dev_queue_xmit_accel(skb, vlan->fwd_priv);
        } else {
                ret = macvlan_queue_xmit(skb, dev);
        }
@@ -338,6 +338,8 @@ static const struct header_ops macvlan_hard_header_ops = {
        .cache_update   = eth_header_cache_update,
 };
 
+static struct rtnl_link_ops macvlan_link_ops;
+
 static int macvlan_open(struct net_device *dev)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
@@ -353,7 +355,8 @@ static int macvlan_open(struct net_device *dev)
                goto hash_add;
        }
 
-       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD &&
+           dev->rtnl_link_ops == &macvlan_link_ops) {
                vlan->fwd_priv =
                      lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
 
@@ -362,10 +365,8 @@ static int macvlan_open(struct net_device *dev)
                 */
                if (IS_ERR_OR_NULL(vlan->fwd_priv)) {
                        vlan->fwd_priv = NULL;
-               } else {
-                       dev->features &= ~NETIF_F_LLTX;
+               } else
                        return 0;
-               }
        }
 
        err = -EBUSY;
@@ -690,8 +691,18 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
                                              netdev_features_t features)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
+       netdev_features_t mask;
+
+       features |= NETIF_F_ALL_FOR_ALL;
+       features &= (vlan->set_features | ~MACVLAN_FEATURES);
+       mask = features;
+
+       features = netdev_increment_features(vlan->lowerdev->features,
+                                            features,
+                                            mask);
+       features |= NETIF_F_LLTX;
 
-       return features & (vlan->set_features | ~MACVLAN_FEATURES);
+       return features;
 }
 
 static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -1019,9 +1030,8 @@ static int macvlan_device_event(struct notifier_block *unused,
                break;
        case NETDEV_FEAT_CHANGE:
                list_for_each_entry(vlan, &port->vlans, list) {
-                       vlan->dev->features = dev->features & MACVLAN_FEATURES;
                        vlan->dev->gso_max_size = dev->gso_max_size;
-                       netdev_features_change(vlan->dev);
+                       netdev_update_features(vlan->dev);
                }
                break;
        case NETDEV_UNREGISTER:
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 36c6994436b7ce7edb9ff9a0d9725c1aa09a4407..98434b84f0415ef2bfd635ba9dc4bc2f7a9ea762 100644 (file)
@@ -565,10 +565,8 @@ int phy_start_interrupts(struct phy_device *phydev)
        int err = 0;
 
        atomic_set(&phydev->irq_disable, 0);
-       if (request_irq(phydev->irq, phy_interrupt,
-                               IRQF_SHARED,
-                               "phy_interrupt",
-                               phydev) < 0) {
+       if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
+                       phydev) < 0) {
                pr_warn("%s: Can't get IRQ %d (PHY)\n",
                        phydev->bus->name, phydev->irq);
                phydev->irq = PHY_POLL;
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..b75ae5bde6734c1c70b196c00a841d84f0f984dd 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;
 }
 
@@ -1643,7 +1647,8 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 782e38bfc1eeea38215492aee5aaa587cc534525..ecec8029c5e84c557374817429c29a505f699c0d 100644 (file)
@@ -348,7 +348,8 @@ unlock:
  * different rxq no. here. If we could not get rxhash, then we would
  * hope the rxq no. may help here.
  */
-static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct tun_struct *tun = netdev_priv(dev);
        struct tun_flow_entry *e;
@@ -1184,7 +1185,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 +1249,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 +1265,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 +1359,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 85e4a01670f06e207609299ecacd035df3e098f3..47b0f732b0b10d21a07d4567e778efcbe4a7fddb 100644 (file)
@@ -276,12 +276,12 @@ config USB_NET_CDC_MBIM
          module will be called cdc_mbim.
 
 config USB_NET_DM9601
-       tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+       tristate "Davicom DM96xx based USB 10/100 ethernet devices"
        depends on USB_USBNET
        select CRC32
        help
-         This option adds support for Davicom DM9601 based USB 1.1
-         10/100 Ethernet adapters.
+         This option adds support for Davicom DM9601/DM9620/DM9621A
+         based USB 10/100 Ethernet adapters.
 
 config USB_NET_SR9700
        tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
index c6867f926cffc18a981c7682e5493ae36924d988..14aa48fa8d7e5610087aee24b5eb0e493593cd83 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ * Davicom DM96xx USB 10/100Mbps ethernet devices
  *
  * Peter Korsgaard <jacmet@sunsite.dk>
  *
@@ -364,7 +364,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
+
+       /* dm9620/21a require room for 4 byte padding, even in dm9601
+        * mode, so we need +1 to be able to receive full size
+        * ethernet frames.
+        */
+       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
 
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = dm9601_mdio_read;
@@ -468,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
                                       gfp_t flags)
 {
-       int len;
+       int len, pad;
 
        /* format:
           b1: packet length low
@@ -476,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
           b3..n: packet data
        */
 
-       len = skb->len;
+       len = skb->len + DM_TX_OVERHEAD;
+
+       /* workaround for dm962x errata with tx fifo getting out of
+        * sync if a USB bulk transfer retry happens right after a
+        * packet with odd / maxpacket length by adding up to 3 bytes
+        * padding.
+        */
+       while ((len & 1) || !(len % dev->maxpacket))
+               len++;
 
-       if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+       len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
+       pad = len - skb->len;
+
+       if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
                struct sk_buff *skb2;
 
-               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
                dev_kfree_skb_any(skb);
                skb = skb2;
                if (!skb)
@@ -490,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 
        __skb_push(skb, DM_TX_OVERHEAD);
 
-       /* usbnet adds padding if length is a multiple of packet size
-          if so, adjust length value in header */
-       if ((skb->len % dev->maxpacket) == 0)
-               len++;
+       if (pad) {
+               memset(skb->data + skb->len, 0, pad);
+               __skb_put(skb, pad);
+       }
 
        skb->data[0] = len;
        skb->data[1] = len >> 8;
@@ -543,7 +559,7 @@ static int dm9601_link_reset(struct usbnet *dev)
 }
 
 static const struct driver_info dm9601_info = {
-       .description    = "Davicom DM9601 USB Ethernet",
+       .description    = "Davicom DM96xx USB 10/100 Ethernet",
        .flags          = FLAG_ETHER | FLAG_LINK_INTR,
        .bind           = dm9601_bind,
        .rx_fixup       = dm9601_rx_fixup,
@@ -594,6 +610,10 @@ static const struct usb_device_id products[] = {
         USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
         .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
        {},                     // END
 };
 
@@ -612,5 +632,5 @@ static struct usb_driver dm9601_driver = {
 module_usb_driver(dm9601_driver);
 
 MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
 MODULE_LICENSE("GPL");
index 86292e6aaf4955c4412ead6579f74e6848bcd089..1a482344b3f507e97486059d56280dfd3f23d37c 100644 (file)
@@ -185,7 +185,6 @@ enum rx_ctrl_state{
 #define BM_REQUEST_TYPE (0xa1)
 #define B_NOTIFICATION  (0x20)
 #define W_VALUE         (0x0)
-#define W_INDEX         (0x2)
 #define W_LENGTH        (0x2)
 
 #define B_OVERRUN       (0x1<<6)
@@ -1487,6 +1486,7 @@ static void tiocmget_intr_callback(struct urb *urb)
        struct uart_icount *icount;
        struct hso_serial_state_notification *serial_state_notification;
        struct usb_device *usb;
+       int if_num;
 
        /* Sanity checks */
        if (!serial)
@@ -1495,15 +1495,24 @@ static void tiocmget_intr_callback(struct urb *urb)
                handle_usb_error(status, __func__, serial->parent);
                return;
        }
+
+       /* tiocmget is only supported on HSO_PORT_MODEM */
        tiocmget = serial->tiocmget;
        if (!tiocmget)
                return;
+       BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
+
        usb = serial->parent->usb;
+       if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+
+       /* wIndex should be the USB interface number of the port to which the
+        * notification applies, which should always be the Modem port.
+        */
        serial_state_notification = &tiocmget->serial_state_notification;
        if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
            serial_state_notification->bNotification != B_NOTIFICATION ||
            le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
-           le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+           le16_to_cpu(serial_state_notification->wIndex) != if_num ||
            le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
                dev_warn(&usb->dev,
                         "hso received invalid serial state notification\n");
index 03832d3780aa6134059dc4768bb7614d71075b82..f54637828574f6b4af868d978288d4920aa3061a 100644 (file)
@@ -117,7 +117,6 @@ enum {
 struct mcs7830_data {
        u8 multi_filter[8];
        u8 config;
-       u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -561,26 +560,16 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
        u8 *buf = urb->transfer_buffer;
        bool link, link_changed;
-       struct mcs7830_data *data = mcs7830_get_data(dev);
 
        if (urb->actual_length < 16)
                return;
 
-       link = !(buf[1] & 0x20);
+       link = !(buf[1] == 0x20);
        link_changed = netif_carrier_ok(dev->net) != link;
        if (link_changed) {
-               data->link_counter++;
-               /*
-                  track link state 20 times to guard against erroneous
-                  link state changes reported sometimes by the chip
-                */
-               if (data->link_counter > 20) {
-                       data->link_counter = 0;
-                       usbnet_link_change(dev, link, 0);
-                       netdev_dbg(dev->net, "Link Status is: %d\n", link);
-               }
-       } else
-               data->link_counter = 0;
+               usbnet_link_change(dev, link, 0);
+               netdev_dbg(dev->net, "Link Status is: %d\n", link);
+       }
 }
 
 static const struct driver_info moschip_info = {
index 7bab4de658a91d9fb1231f5e45461a268efc8487..5d776447d9c33e2da56b622a2537536cf950ca0c 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;
@@ -1752,16 +1797,17 @@ static int virtnet_restore(struct virtio_device *vdev)
        if (err)
                return err;
 
-       if (netif_running(vi->dev))
+       if (netif_running(vi->dev)) {
+               for (i = 0; i < vi->curr_queue_pairs; i++)
+                       if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                               schedule_delayed_work(&vi->refill, 0);
+
                for (i = 0; i < vi->max_queue_pairs; i++)
                        virtnet_napi_enable(&vi->rq[i]);
+       }
 
        netif_device_attach(vi->dev);
 
-       for (i = 0; i < vi->curr_queue_pairs; i++)
-               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
-                       schedule_delayed_work(&vi->refill, 0);
-
        mutex_lock(&vi->config_lock);
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
index 0358c07f7669142034e089660425a8fdb88236e2..ed384fee76ac9ffa12eff0563864424f95ab2d01 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 */
@@ -2440,7 +2440,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                /* update header length based on lower device */
                dev->hard_header_len = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       }
+       } else if (use_ipv6)
+               vxlan->flags |= VXLAN_F_IPV6;
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
index 8d78253c26cee6f459121e7e8ef5c3e0e44b8b2a..a366d6b4626f5fdd0bcf04b1d6b9c6063a70afbd 100644 (file)
@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S2, isr2);
+                               isr &= ~AR_ISR_BCNMISC;
+                       }
                }
 
-               isr = REG_READ(ah, AR_ISR_RAC);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+                       isr = REG_READ(ah, AR_ISR_RAC);
+
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                        *masked |= ATH9K_INT_TX;
 
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
+                       if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                               s0_s = REG_READ(ah, AR_ISR_S0_S);
+                               s1_s = REG_READ(ah, AR_ISR_S1_S);
+                       } else {
+                               s0_s = REG_READ(ah, AR_ISR_S0);
+                               REG_WRITE(ah, AR_ISR_S0, s0_s);
+                               s1_s = REG_READ(ah, AR_ISR_S1);
+                               REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+                               isr &= ~(AR_ISR_TXOK |
+                                        AR_ISR_TXDESC |
+                                        AR_ISR_TXERR |
+                                        AR_ISR_TXEOL);
+                       }
+
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
@@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                *masked |= mask2;
        }
 
-       if (AR_SREV_9100(ah))
-               return true;
-
-       if (isr & AR_ISR_GENTMR) {
+       if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
                u32 s5_s;
 
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                       s5_s = REG_READ(ah, AR_ISR_S5_S);
+               } else {
+                       s5_s = REG_READ(ah, AR_ISR_S5);
+               }
+
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
@@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
+
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                       REG_WRITE(ah, AR_ISR_S5, s5_s);
+                       isr &= ~AR_ISR_GENTMR;
+               }
        }
 
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+               REG_WRITE(ah, AR_ISR, isr);
+               REG_READ(ah, AR_ISR);
+       }
+
+       if (AR_SREV_9100(ah))
+               return true;
+
        if (sync_cause) {
                ath9k_debug_sync_cause(common, sync_cause);
                fatal_int =
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 9a2657fdd9ccd4ec62f96f8a639182e2ded29fec..608d739d13782233db4271f9248c3472601b1a5f 100644 (file)
@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        struct ath9k_vif_iter_data *iter_data = data;
        int i;
 
-       for (i = 0; i < ETH_ALEN; i++)
-               iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       if (iter_data->hw_macaddr != NULL) {
+               for (i = 0; i < ETH_ALEN; i++)
+                       iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       } else {
+               iter_data->hw_macaddr = mac;
+       }
 }
 
-static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
                                     struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
        struct ath9k_vif_iter_data iter_data;
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
-       iter_data.hw_macaddr = common->macaddr;
+       iter_data.hw_macaddr = NULL;
        memset(&iter_data.mask, 0xff, ETH_ALEN);
 
        if (vif)
@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
                ath9k_htc_bssid_iter, &iter_data);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+
+       if (iter_data.hw_macaddr)
+               memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+
        ath_hw_setbssidmask(common);
 }
 
@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;
@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 
        ath9k_htc_set_opmode(priv);
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        /*
         * Stop ANI only if there are no associated station interfaces.
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 74f452c7b1667c47a65506a077042f2b0668c3a8..21aa09e0e825df1161a4fcca3753ca08e9632558 100644 (file)
@@ -965,8 +965,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(ah);
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
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..e6272546395a982d6d3e6e23239eaddc1bc3bf60 100644 (file)
@@ -353,6 +353,33 @@ 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(0x095A, 0x5012, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5400, 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, 0x9110, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9310, 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(0x095A, 0x5190, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5590, 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..a1b32ee9594a6b9b899caa03cea53f3d9a0ddf90 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",
@@ -2003,7 +2011,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
           (hwsim_flags & HWSIM_TX_STAT_ACK)) {
                if (skb->len >= 16) {
                        hdr = (struct ieee80211_hdr *) skb->data;
-                       mac80211_hwsim_monitor_ack(txi->rate_driver_data[0],
+                       mac80211_hwsim_monitor_ack(data2->channel,
                                                   hdr->addr2);
                }
                txi->flags |= IEEE80211_TX_STAT_ACK;
index 78e8a6666cc6edad81bd87c98dcf0353af371866..8bb8988c435cf04b0280aef69d4e9d01acc24fee 100644 (file)
@@ -746,7 +746,8 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 }
 
 static u16
-mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        skb->priority = cfg80211_classify8021d(skb);
        return mwifiex_1d_to_wmm_queue[skb->priority];
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 0f494444bcd1d90b457b927d704bf77abe0592ca..5a53195d016b61da57f3198ad1f616343e1ebd3d 100644 (file)
@@ -740,6 +740,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
        };
        int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
+       if (rtlpci->driver_is_goingto_unload)
+               return;
        /*RX NORMAL PKT */
        while (count--) {
                /*rx descriptor */
@@ -1636,6 +1638,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
         */
        set_hal_stop(rtlhal);
 
+       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->disable_interrupt(hw);
        cancel_work_sync(&rtlpriv->works.lps_change_work);
 
@@ -1653,7 +1656,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        ppsc->rfchange_inprogress = true;
        spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
 
-       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->hw_disable(hw);
        /* some things are not needed if firmware not available */
        if (!rtlpriv->max_fw_size)
index 08ae01b41c832d7144bdeceb70b976adaf281d4c..c47794b9d42f9bfd71d2761a48f8429a8b4633c5 100644 (file)
@@ -101,6 +101,13 @@ struct xenvif_rx_meta {
 
 #define MAX_PENDING_REQS 256
 
+/* It's possible for an skb to have a maximal number of frags
+ * but still be less than MAX_BUFFER_OFFSET in size. Thus the
+ * worst-case number of copy operations is MAX_SKB_FRAGS per
+ * ring slot.
+ */
+#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
+
 struct xenvif {
        /* Unique identifier for this interface. */
        domid_t          domid;
@@ -143,13 +150,13 @@ struct xenvif {
         */
        RING_IDX rx_req_cons_peek;
 
-       /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
-        * head/fragment page uses 2 copy operations because it
-        * straddles two buffers in the frontend.
-        */
-       struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
-       struct xenvif_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+       /* This array is allocated seperately as it is large */
+       struct gnttab_copy *grant_copy_op;
 
+       /* We create one meta structure per ring request we consume, so
+        * the maximum number is the same as the ring size.
+        */
+       struct xenvif_rx_meta meta[XEN_NETIF_RX_RING_SIZE];
 
        u8               fe_dev_addr[6];
 
index 2329cccf1fa6dd15f65c4dc30c54c62cce0551a7..fff8cddfed816d3479fac57a6f91b4d827272033 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
 
 #include <xen/events.h>
 #include <asm/xen/hypercall.h>
@@ -307,6 +308,15 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        SET_NETDEV_DEV(dev, parent);
 
        vif = netdev_priv(dev);
+
+       vif->grant_copy_op = vmalloc(sizeof(struct gnttab_copy) *
+                                    MAX_GRANT_COPY_OPS);
+       if (vif->grant_copy_op == NULL) {
+               pr_warn("Could not allocate grant copy space for %s\n", name);
+               free_netdev(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+
        vif->domid  = domid;
        vif->handle = handle;
        vif->can_sg = 1;
@@ -368,11 +378,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 +421,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 +473,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)
@@ -483,6 +497,7 @@ void xenvif_free(struct xenvif *vif)
 
        unregister_netdev(vif->dev);
 
+       vfree(vif->grant_copy_op);
        free_netdev(vif->dev);
 
        module_put(THIS_MODULE);
index 919b6509455cfbaf45ba63c7d8b378fa13a8e758..78425554a537579b01378b99295913c1706f0b0a 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;
@@ -607,7 +608,7 @@ void xenvif_rx_action(struct xenvif *vif)
        if (!npo.copy_prod)
                return;
 
-       BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
+       BUG_ON(npo.copy_prod > MAX_GRANT_COPY_OPS);
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
@@ -1148,75 +1149,99 @@ 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;
 
-       off = sizeof(struct iphdr);
+       fragment = false;
 
-       header_size = skb->network_header + off + MAX_IPOPTLEN;
-       maybe_pull_tail(skb, header_size);
+       err = maybe_pull_tail(skb,
+                             sizeof(struct iphdr),
+                             MAX_IP_HDR_LEN);
+       if (err < 0)
+               goto out;
 
-       off = iph->ihl * 4;
+       if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
+               fragment = true;
 
-       switch (iph->protocol) {
-       case IPPROTO_TCP:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
-                       goto out;
+       off = ip_hdrlen(skb);
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
+       err = -EPROTO;
+
+       if (fragment)
+               goto out;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
+       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;
 
-                       tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_TCP, 0);
+               if (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               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:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
                        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 (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               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 +1251,142 @@ 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;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ip_auth_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ip_auth_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
+                       hp = OPT_HDR(struct ip_auth_hdr, skb, off);
                        nexthdr = hp->nexthdr;
-                       off += (hp->hdrlen+2)<<2;
+                       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 += 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:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
                        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 (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               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:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
                        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 (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               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 +1456,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 +1486,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 +1626,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 +1707,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 de6f8990246fefc8aaef7c0e88e0371143ae9859..c6973f101a3e4ae9e00c604cd9e1708d1bd88485 100644 (file)
@@ -20,7 +20,7 @@ config OF_SELFTEST
        depends on OF_IRQ
        help
          This option builds in test cases for the device tree infrastructure
-         that are executed one at boot time, and the results dumped to the
+         that are executed once at boot time, and the results dumped to the
          console.
 
          If unsure, say N here, but this option is safe to enable.
index 4b9317bdb81ce85209573e6c28f86492e643962b..d3dd41c840f1cd8d6784e4a61382cb3e4987ad1a 100644 (file)
@@ -69,14 +69,6 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                 (unsigned long long)cp, (unsigned long long)s,
                 (unsigned long long)da);
 
-       /*
-        * If the number of address cells is larger than 2 we assume the
-        * mapping doesn't specify a physical address. Rather, the address
-        * specifies an identifier that must match exactly.
-        */
-       if (na > 2 && memcmp(range, addr, na * 4) != 0)
-               return OF_BAD_ADDR;
-
        if (da < cp || da >= (cp + s))
                return OF_BAD_ADDR;
        return da - cp;
index 2fa024b97c4350c680e384c645dc17d0fc5dc177..758b4f8b30b7d237c92b6a541f01db535d37101b 100644 (file)
@@ -922,8 +922,16 @@ void __init unflatten_device_tree(void)
  */
 void __init unflatten_and_copy_device_tree(void)
 {
-       int size = __be32_to_cpu(initial_boot_params->totalsize);
-       void *dt = early_init_dt_alloc_memory_arch(size,
+       int size;
+       void *dt;
+
+       if (!initial_boot_params) {
+               pr_warn("No valid device tree found, continuing without\n");
+               return;
+       }
+
+       size = __be32_to_cpu(initial_boot_params->totalsize);
+       dt = early_init_dt_alloc_memory_arch(size,
                __alignof__(struct boot_param_header));
 
        if (dt) {
index 786b0b47fae46802503ecbecee5719887830c44c..27212402c53247819cf4edf09e576d2cc69f3136 100644 (file)
@@ -165,7 +165,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                if (of_get_property(ipar, "interrupt-controller", NULL) !=
                                NULL) {
                        pr_debug(" -> got it !\n");
-                       of_node_put(old);
                        return 0;
                }
 
@@ -250,8 +249,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                 * Successfully parsed an interrrupt-map translation; copy new
                 * interrupt specifier into the out_irq structure
                 */
-               of_node_put(out_irq->np);
-               out_irq->np = of_node_get(newpar);
+               out_irq->np = newpar;
 
                match_array = imap - newaddrsize - newintsize;
                for (i = 0; i < newintsize; i++)
@@ -268,7 +266,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
        }
  fail:
        of_node_put(ipar);
-       of_node_put(out_irq->np);
        of_node_put(newpar);
 
        return -EINVAL;
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 1cf605f6767357947e9a097981caa7d7869ca2f0..e86439283a5d1911933eed185e22a50146093968 100644 (file)
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
-               acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
+               if (status != AE_NOT_FOUND)
+                       acpi_handle_warn(handle,
+                               "can't evaluate _ADR (%#x)\n", status);
                return AE_OK;
        }
 
@@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot)
        slot->flags &= (~SLOT_ENABLED);
 }
 
+static bool acpiphp_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       return adev && adev->flags.no_hotplug;
+}
+
+static bool slot_no_hotplug(struct acpiphp_slot *slot)
+{
+       struct acpiphp_func *func;
+
+       list_for_each_entry(func, &slot->funcs, sibling)
+               if (acpiphp_no_hotplug(func_to_handle(func)))
+                       return true;
+
+       return false;
+}
 
 /**
  * get_slot_status - get ACPI slot status
@@ -701,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev)
                unsigned long long sta;
 
                status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-               alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
+               alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
+                       || acpiphp_no_hotplug(handle);
        }
        if (!alive) {
                u32 v;
@@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                struct pci_dev *dev, *tmp;
 
                mutex_lock(&slot->crit_sect);
-               /* wake up all functions */
-               if (get_slot_status(slot) == ACPI_STA_ALL) {
+               if (slot_no_hotplug(slot)) {
+                       ; /* do nothing */
+               } else if (get_slot_status(slot) == ACPI_STA_ALL) {
                        /* remove stale devices if any */
                        list_for_each_entry_safe(dev, tmp, &bus->devices,
                                                 bus_list)
index 577074efbe62f93f39ac00c6f5c4963d53bd2b0d..f7ebdba14bde9bc1c7e3dd702bc6e47506067ff5 100644 (file)
@@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
 
-       if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+       if (!adev)
+               return;
+
+       pci_acpi_add_pm_notifier(adev, pci_dev);
+       if (!adev->wakeup.flags.valid)
                return;
 
        device_set_wakeup_capable(dev, true);
        acpi_pci_sleep_wake(pci_dev, false);
-
-       pci_acpi_add_pm_notifier(adev, pci_dev);
        if (adev->wakeup.flags.run_wake)
                device_set_run_wake(dev, true);
 }
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+
+       if (!adev)
+               return;
 
-       if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) {
+       pci_acpi_remove_pm_notifier(adev);
+       if (adev->wakeup.flags.valid) {
                device_set_wakeup_capable(dev, false);
                device_set_run_wake(dev, false);
-               pci_acpi_remove_pm_notifier(adev);
        }
 }
 
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
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
new file mode 100644 (file)
index 0000000..3e5b449
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ *  chromeos_laptop.c - Driver to instantiate Chromebook i2c/smbus devices.
+ *
+ *  Author : Benson Leung <bleung@chromium.org>
+ *
+ *  Copyright (C) 2012 Google, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/dmi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#define ATMEL_TP_I2C_ADDR      0x4b
+#define ATMEL_TP_I2C_BL_ADDR   0x25
+#define ATMEL_TS_I2C_ADDR      0x4a
+#define ATMEL_TS_I2C_BL_ADDR   0x26
+#define CYAPA_TP_I2C_ADDR      0x67
+#define ISL_ALS_I2C_ADDR       0x44
+#define TAOS_ALS_I2C_ADDR      0x29
+
+static struct i2c_client *als;
+static struct i2c_client *tp;
+static struct i2c_client *ts;
+
+const char *i2c_adapter_names[] = {
+       "SMBus I801 adapter",
+       "i915 gmbus vga",
+       "i915 gmbus panel",
+};
+
+/* Keep this enum consistent with i2c_adapter_names */
+enum i2c_adapter_type {
+       I2C_ADAPTER_SMBUS = 0,
+       I2C_ADAPTER_VGADDC,
+       I2C_ADAPTER_PANEL,
+};
+
+static struct i2c_board_info __initdata cyapa_device = {
+       I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
+       .flags          = I2C_CLIENT_WAKE,
+};
+
+static struct i2c_board_info __initdata isl_als_device = {
+       I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
+};
+
+static struct i2c_board_info __initdata tsl2583_als_device = {
+       I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
+};
+
+static struct i2c_board_info __initdata tsl2563_als_device = {
+       I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
+};
+
+static struct mxt_platform_data atmel_224s_tp_platform_data = {
+       .x_line                 = 18,
+       .y_line                 = 12,
+       .x_size                 = 102*20,
+       .y_size                 = 68*20,
+       .blen                   = 0x80, /* Gain setting is in upper 4 bits */
+       .threshold              = 0x32,
+       .voltage                = 0,    /* 3.3V */
+       .orient                 = MXT_VERTICAL_FLIP,
+       .irqflags               = IRQF_TRIGGER_FALLING,
+       .is_tp                  = true,
+       .key_map                = { KEY_RESERVED,
+                                   KEY_RESERVED,
+                                   KEY_RESERVED,
+                                   BTN_LEFT },
+       .config                 = NULL,
+       .config_length          = 0,
+};
+
+static struct i2c_board_info __initdata atmel_224s_tp_device = {
+       I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR),
+       .platform_data = &atmel_224s_tp_platform_data,
+       .flags          = I2C_CLIENT_WAKE,
+};
+
+static struct mxt_platform_data atmel_1664s_platform_data = {
+       .x_line                 = 32,
+       .y_line                 = 50,
+       .x_size                 = 1700,
+       .y_size                 = 2560,
+       .blen                   = 0x89, /* Gain setting is in upper 4 bits */
+       .threshold              = 0x28,
+       .voltage                = 0,    /* 3.3V */
+       .orient                 = MXT_ROTATED_90_COUNTER,
+       .irqflags               = IRQF_TRIGGER_FALLING,
+       .is_tp                  = false,
+       .config                 = NULL,
+       .config_length          = 0,
+};
+
+static struct i2c_board_info __initdata atmel_1664s_device = {
+       I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR),
+       .platform_data = &atmel_1664s_platform_data,
+       .flags          = I2C_CLIENT_WAKE,
+};
+
+static struct i2c_client __init *__add_probed_i2c_device(
+               const char *name,
+               int bus,
+               struct i2c_board_info *info,
+               const unsigned short *addrs)
+{
+       const struct dmi_device *dmi_dev;
+       const struct dmi_dev_onboard *dev_data;
+       struct i2c_adapter *adapter;
+       struct i2c_client *client;
+
+       if (bus < 0)
+               return NULL;
+       /*
+        * If a name is specified, look for irq platform information stashed
+        * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware.
+        */
+       if (name) {
+               dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL);
+               if (!dmi_dev) {
+                       pr_err("%s failed to dmi find device %s.\n",
+                              __func__,
+                              name);
+                       return NULL;
+               }
+               dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data;
+               if (!dev_data) {
+                       pr_err("%s failed to get data from dmi for %s.\n",
+                              __func__, name);
+                       return NULL;
+               }
+               info->irq = dev_data->instance;
+       }
+
+       adapter = i2c_get_adapter(bus);
+       if (!adapter) {
+               pr_err("%s failed to get i2c adapter %d.\n", __func__, bus);
+               return NULL;
+       }
+
+       /* add the i2c device */
+       client = i2c_new_probed_device(adapter, info, addrs, NULL);
+       if (!client)
+               pr_err("%s failed to register device %d-%02x\n",
+                      __func__, bus, info->addr);
+       else
+               pr_debug("%s added i2c device %d-%02x\n",
+                        __func__, bus, info->addr);
+
+       i2c_put_adapter(adapter);
+       return client;
+}
+
+static int __init __find_i2c_adap(struct device *dev, void *data)
+{
+       const char *name = data;
+       static const char *prefix = "i2c-";
+       struct i2c_adapter *adapter;
+       if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
+               return 0;
+       adapter = to_i2c_adapter(dev);
+       return (strncmp(adapter->name, name, strlen(name)) == 0);
+}
+
+static int __init find_i2c_adapter_num(enum i2c_adapter_type type)
+{
+       struct device *dev = NULL;
+       struct i2c_adapter *adapter;
+       const char *name = i2c_adapter_names[type];
+       /* find the adapter by name */
+       dev = bus_find_device(&i2c_bus_type, NULL, (void *)name,
+                             __find_i2c_adap);
+       if (!dev) {
+               pr_err("%s: i2c adapter %s not found on system.\n", __func__,
+                      name);
+               return -ENODEV;
+       }
+       adapter = to_i2c_adapter(dev);
+       return adapter->nr;
+}
+
+/*
+ * Takes a list of addresses in addrs as such :
+ * { addr1, ... , addrn, I2C_CLIENT_END };
+ * add_probed_i2c_device will use i2c_new_probed_device
+ * and probe for devices at all of the addresses listed.
+ * Returns NULL if no devices found.
+ * See Documentation/i2c/instantiating-devices for more information.
+ */
+static __init struct i2c_client *add_probed_i2c_device(
+               const char *name,
+               enum i2c_adapter_type type,
+               struct i2c_board_info *info,
+               const unsigned short *addrs)
+{
+       return __add_probed_i2c_device(name,
+                                      find_i2c_adapter_num(type),
+                                      info,
+                                      addrs);
+}
+
+/*
+ * Probes for a device at a single address, the one provided by
+ * info->addr.
+ * Returns NULL if no device found.
+ */
+static __init struct i2c_client *add_i2c_device(const char *name,
+                                               enum i2c_adapter_type type,
+                                               struct i2c_board_info *info)
+{
+       const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
+       return __add_probed_i2c_device(name,
+                                      find_i2c_adapter_num(type),
+                                      info,
+                                      addr_list);
+}
+
+
+static struct i2c_client __init *add_smbus_device(const char *name,
+                                                 struct i2c_board_info *info)
+{
+       return add_i2c_device(name, I2C_ADAPTER_SMBUS, info);
+}
+
+static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id)
+{
+       /* add cyapa touchpad on smbus */
+       tp = add_smbus_device("trackpad", &cyapa_device);
+       return 0;
+}
+
+static int __init setup_atmel_224s_tp(const struct dmi_system_id *id)
+{
+       const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR,
+                                            ATMEL_TP_I2C_ADDR,
+                                            I2C_CLIENT_END };
+
+       /* add atmel mxt touchpad on VGA DDC GMBus */
+       tp = add_probed_i2c_device("trackpad", I2C_ADAPTER_VGADDC,
+                                  &atmel_224s_tp_device, addr_list);
+       return 0;
+}
+
+static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id)
+{
+       const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR,
+                                            ATMEL_TS_I2C_ADDR,
+                                            I2C_CLIENT_END };
+
+       /* add atmel mxt touch device on PANEL GMBus */
+       ts = add_probed_i2c_device("touchscreen", I2C_ADAPTER_PANEL,
+                                  &atmel_1664s_device, addr_list);
+       return 0;
+}
+
+
+static int __init setup_isl29018_als(const struct dmi_system_id *id)
+{
+       /* add isl29018 light sensor */
+       als = add_smbus_device("lightsensor", &isl_als_device);
+       return 0;
+}
+
+static int __init setup_isl29023_als(const struct dmi_system_id *id)
+{
+       /* add isl29023 light sensor on Panel GMBus */
+       als = add_i2c_device("lightsensor", I2C_ADAPTER_PANEL,
+                            &isl_als_device);
+       return 0;
+}
+
+static int __init setup_tsl2583_als(const struct dmi_system_id *id)
+{
+       /* add tsl2583 light sensor on smbus */
+       als = add_smbus_device(NULL, &tsl2583_als_device);
+       return 0;
+}
+
+static int __init setup_tsl2563_als(const struct dmi_system_id *id)
+{
+       /* add tsl2563 light sensor on smbus */
+       als = add_smbus_device(NULL, &tsl2563_als_device);
+       return 0;
+}
+
+static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = {
+       {
+               .ident = "Samsung Series 5 550 - Touchpad",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
+               },
+               .callback = setup_cyapa_smbus_tp,
+       },
+       {
+               .ident = "Chromebook Pixel - Touchscreen",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
+               },
+               .callback = setup_atmel_1664s_ts,
+       },
+       {
+               .ident = "Chromebook Pixel - Touchpad",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
+               },
+               .callback = setup_atmel_224s_tp,
+       },
+       {
+               .ident = "Samsung Series 5 550 - Light Sensor",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
+               },
+               .callback = setup_isl29018_als,
+       },
+       {
+               .ident = "Chromebook Pixel - Light Sensor",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
+               },
+               .callback = setup_isl29023_als,
+       },
+       {
+               .ident = "Acer C7 Chromebook - Touchpad",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
+               },
+               .callback = setup_cyapa_smbus_tp,
+       },
+       {
+               .ident = "HP Pavilion 14 Chromebook - Touchpad",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
+               },
+               .callback = setup_cyapa_smbus_tp,
+       },
+       {
+               .ident = "Samsung Series 5 - Light Sensor",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
+               },
+               .callback = setup_tsl2583_als,
+       },
+       {
+               .ident = "Cr-48 - Light Sensor",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
+               },
+               .callback = setup_tsl2563_als,
+       },
+       {
+               .ident = "Acer AC700 - Light Sensor",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+               },
+               .callback = setup_tsl2563_als,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
+
+static int __init chromeos_laptop_init(void)
+{
+       if (!dmi_check_system(chromeos_laptop_dmi_table)) {
+               pr_debug("%s unsupported system.\n", __func__);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit chromeos_laptop_exit(void)
+{
+       if (als)
+               i2c_unregister_device(als);
+       if (tp)
+               i2c_unregister_device(tp);
+       if (ts)
+               i2c_unregister_device(ts);
+}
+
+module_init(chromeos_laptop_init);
+module_exit(chromeos_laptop_exit);
+
+MODULE_DESCRIPTION("Chrome OS Laptop driver");
+MODULE_AUTHOR("Benson Leung <bleung@chromium.org>");
+MODULE_LICENSE("GPL");
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;
diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c
deleted file mode 100644 (file)
index 3e5b449..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- *  chromeos_laptop.c - Driver to instantiate Chromebook i2c/smbus devices.
- *
- *  Author : Benson Leung <bleung@chromium.org>
- *
- *  Copyright (C) 2012 Google, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/dmi.h>
-#include <linux/i2c.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-
-#define ATMEL_TP_I2C_ADDR      0x4b
-#define ATMEL_TP_I2C_BL_ADDR   0x25
-#define ATMEL_TS_I2C_ADDR      0x4a
-#define ATMEL_TS_I2C_BL_ADDR   0x26
-#define CYAPA_TP_I2C_ADDR      0x67
-#define ISL_ALS_I2C_ADDR       0x44
-#define TAOS_ALS_I2C_ADDR      0x29
-
-static struct i2c_client *als;
-static struct i2c_client *tp;
-static struct i2c_client *ts;
-
-const char *i2c_adapter_names[] = {
-       "SMBus I801 adapter",
-       "i915 gmbus vga",
-       "i915 gmbus panel",
-};
-
-/* Keep this enum consistent with i2c_adapter_names */
-enum i2c_adapter_type {
-       I2C_ADAPTER_SMBUS = 0,
-       I2C_ADAPTER_VGADDC,
-       I2C_ADAPTER_PANEL,
-};
-
-static struct i2c_board_info __initdata cyapa_device = {
-       I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
-       .flags          = I2C_CLIENT_WAKE,
-};
-
-static struct i2c_board_info __initdata isl_als_device = {
-       I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
-};
-
-static struct i2c_board_info __initdata tsl2583_als_device = {
-       I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
-};
-
-static struct i2c_board_info __initdata tsl2563_als_device = {
-       I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
-};
-
-static struct mxt_platform_data atmel_224s_tp_platform_data = {
-       .x_line                 = 18,
-       .y_line                 = 12,
-       .x_size                 = 102*20,
-       .y_size                 = 68*20,
-       .blen                   = 0x80, /* Gain setting is in upper 4 bits */
-       .threshold              = 0x32,
-       .voltage                = 0,    /* 3.3V */
-       .orient                 = MXT_VERTICAL_FLIP,
-       .irqflags               = IRQF_TRIGGER_FALLING,
-       .is_tp                  = true,
-       .key_map                = { KEY_RESERVED,
-                                   KEY_RESERVED,
-                                   KEY_RESERVED,
-                                   BTN_LEFT },
-       .config                 = NULL,
-       .config_length          = 0,
-};
-
-static struct i2c_board_info __initdata atmel_224s_tp_device = {
-       I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR),
-       .platform_data = &atmel_224s_tp_platform_data,
-       .flags          = I2C_CLIENT_WAKE,
-};
-
-static struct mxt_platform_data atmel_1664s_platform_data = {
-       .x_line                 = 32,
-       .y_line                 = 50,
-       .x_size                 = 1700,
-       .y_size                 = 2560,
-       .blen                   = 0x89, /* Gain setting is in upper 4 bits */
-       .threshold              = 0x28,
-       .voltage                = 0,    /* 3.3V */
-       .orient                 = MXT_ROTATED_90_COUNTER,
-       .irqflags               = IRQF_TRIGGER_FALLING,
-       .is_tp                  = false,
-       .config                 = NULL,
-       .config_length          = 0,
-};
-
-static struct i2c_board_info __initdata atmel_1664s_device = {
-       I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR),
-       .platform_data = &atmel_1664s_platform_data,
-       .flags          = I2C_CLIENT_WAKE,
-};
-
-static struct i2c_client __init *__add_probed_i2c_device(
-               const char *name,
-               int bus,
-               struct i2c_board_info *info,
-               const unsigned short *addrs)
-{
-       const struct dmi_device *dmi_dev;
-       const struct dmi_dev_onboard *dev_data;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-
-       if (bus < 0)
-               return NULL;
-       /*
-        * If a name is specified, look for irq platform information stashed
-        * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware.
-        */
-       if (name) {
-               dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL);
-               if (!dmi_dev) {
-                       pr_err("%s failed to dmi find device %s.\n",
-                              __func__,
-                              name);
-                       return NULL;
-               }
-               dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data;
-               if (!dev_data) {
-                       pr_err("%s failed to get data from dmi for %s.\n",
-                              __func__, name);
-                       return NULL;
-               }
-               info->irq = dev_data->instance;
-       }
-
-       adapter = i2c_get_adapter(bus);
-       if (!adapter) {
-               pr_err("%s failed to get i2c adapter %d.\n", __func__, bus);
-               return NULL;
-       }
-
-       /* add the i2c device */
-       client = i2c_new_probed_device(adapter, info, addrs, NULL);
-       if (!client)
-               pr_err("%s failed to register device %d-%02x\n",
-                      __func__, bus, info->addr);
-       else
-               pr_debug("%s added i2c device %d-%02x\n",
-                        __func__, bus, info->addr);
-
-       i2c_put_adapter(adapter);
-       return client;
-}
-
-static int __init __find_i2c_adap(struct device *dev, void *data)
-{
-       const char *name = data;
-       static const char *prefix = "i2c-";
-       struct i2c_adapter *adapter;
-       if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
-               return 0;
-       adapter = to_i2c_adapter(dev);
-       return (strncmp(adapter->name, name, strlen(name)) == 0);
-}
-
-static int __init find_i2c_adapter_num(enum i2c_adapter_type type)
-{
-       struct device *dev = NULL;
-       struct i2c_adapter *adapter;
-       const char *name = i2c_adapter_names[type];
-       /* find the adapter by name */
-       dev = bus_find_device(&i2c_bus_type, NULL, (void *)name,
-                             __find_i2c_adap);
-       if (!dev) {
-               pr_err("%s: i2c adapter %s not found on system.\n", __func__,
-                      name);
-               return -ENODEV;
-       }
-       adapter = to_i2c_adapter(dev);
-       return adapter->nr;
-}
-
-/*
- * Takes a list of addresses in addrs as such :
- * { addr1, ... , addrn, I2C_CLIENT_END };
- * add_probed_i2c_device will use i2c_new_probed_device
- * and probe for devices at all of the addresses listed.
- * Returns NULL if no devices found.
- * See Documentation/i2c/instantiating-devices for more information.
- */
-static __init struct i2c_client *add_probed_i2c_device(
-               const char *name,
-               enum i2c_adapter_type type,
-               struct i2c_board_info *info,
-               const unsigned short *addrs)
-{
-       return __add_probed_i2c_device(name,
-                                      find_i2c_adapter_num(type),
-                                      info,
-                                      addrs);
-}
-
-/*
- * Probes for a device at a single address, the one provided by
- * info->addr.
- * Returns NULL if no device found.
- */
-static __init struct i2c_client *add_i2c_device(const char *name,
-                                               enum i2c_adapter_type type,
-                                               struct i2c_board_info *info)
-{
-       const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
-       return __add_probed_i2c_device(name,
-                                      find_i2c_adapter_num(type),
-                                      info,
-                                      addr_list);
-}
-
-
-static struct i2c_client __init *add_smbus_device(const char *name,
-                                                 struct i2c_board_info *info)
-{
-       return add_i2c_device(name, I2C_ADAPTER_SMBUS, info);
-}
-
-static int __init setup_cyapa_smbus_tp(const struct dmi_system_id *id)
-{
-       /* add cyapa touchpad on smbus */
-       tp = add_smbus_device("trackpad", &cyapa_device);
-       return 0;
-}
-
-static int __init setup_atmel_224s_tp(const struct dmi_system_id *id)
-{
-       const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR,
-                                            ATMEL_TP_I2C_ADDR,
-                                            I2C_CLIENT_END };
-
-       /* add atmel mxt touchpad on VGA DDC GMBus */
-       tp = add_probed_i2c_device("trackpad", I2C_ADAPTER_VGADDC,
-                                  &atmel_224s_tp_device, addr_list);
-       return 0;
-}
-
-static int __init setup_atmel_1664s_ts(const struct dmi_system_id *id)
-{
-       const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR,
-                                            ATMEL_TS_I2C_ADDR,
-                                            I2C_CLIENT_END };
-
-       /* add atmel mxt touch device on PANEL GMBus */
-       ts = add_probed_i2c_device("touchscreen", I2C_ADAPTER_PANEL,
-                                  &atmel_1664s_device, addr_list);
-       return 0;
-}
-
-
-static int __init setup_isl29018_als(const struct dmi_system_id *id)
-{
-       /* add isl29018 light sensor */
-       als = add_smbus_device("lightsensor", &isl_als_device);
-       return 0;
-}
-
-static int __init setup_isl29023_als(const struct dmi_system_id *id)
-{
-       /* add isl29023 light sensor on Panel GMBus */
-       als = add_i2c_device("lightsensor", I2C_ADAPTER_PANEL,
-                            &isl_als_device);
-       return 0;
-}
-
-static int __init setup_tsl2583_als(const struct dmi_system_id *id)
-{
-       /* add tsl2583 light sensor on smbus */
-       als = add_smbus_device(NULL, &tsl2583_als_device);
-       return 0;
-}
-
-static int __init setup_tsl2563_als(const struct dmi_system_id *id)
-{
-       /* add tsl2563 light sensor on smbus */
-       als = add_smbus_device(NULL, &tsl2563_als_device);
-       return 0;
-}
-
-static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = {
-       {
-               .ident = "Samsung Series 5 550 - Touchpad",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
-               },
-               .callback = setup_cyapa_smbus_tp,
-       },
-       {
-               .ident = "Chromebook Pixel - Touchscreen",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
-               },
-               .callback = setup_atmel_1664s_ts,
-       },
-       {
-               .ident = "Chromebook Pixel - Touchpad",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
-               },
-               .callback = setup_atmel_224s_tp,
-       },
-       {
-               .ident = "Samsung Series 5 550 - Light Sensor",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
-               },
-               .callback = setup_isl29018_als,
-       },
-       {
-               .ident = "Chromebook Pixel - Light Sensor",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
-               },
-               .callback = setup_isl29023_als,
-       },
-       {
-               .ident = "Acer C7 Chromebook - Touchpad",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
-               },
-               .callback = setup_cyapa_smbus_tp,
-       },
-       {
-               .ident = "HP Pavilion 14 Chromebook - Touchpad",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
-               },
-               .callback = setup_cyapa_smbus_tp,
-       },
-       {
-               .ident = "Samsung Series 5 - Light Sensor",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
-               },
-               .callback = setup_tsl2583_als,
-       },
-       {
-               .ident = "Cr-48 - Light Sensor",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
-               },
-               .callback = setup_tsl2563_als,
-       },
-       {
-               .ident = "Acer AC700 - Light Sensor",
-               .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
-               },
-               .callback = setup_tsl2563_als,
-       },
-       { }
-};
-MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
-
-static int __init chromeos_laptop_init(void)
-{
-       if (!dmi_check_system(chromeos_laptop_dmi_table)) {
-               pr_debug("%s unsupported system.\n", __func__);
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static void __exit chromeos_laptop_exit(void)
-{
-       if (als)
-               i2c_unregister_device(als);
-       if (tp)
-               i2c_unregister_device(tp);
-       if (ts)
-               i2c_unregister_device(ts);
-}
-
-module_init(chromeos_laptop_init);
-module_exit(chromeos_laptop_exit);
-
-MODULE_DESCRIPTION("Chrome OS Laptop driver");
-MODULE_AUTHOR("Benson Leung <bleung@chromium.org>");
-MODULE_LICENSE("GPL");
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 5e2054afe840e9d6412a28c5250f34d1017aa7b2..85ad58c6da17233a9503650500b69579887c84bb 100644 (file)
@@ -196,6 +196,7 @@ config BATTERY_MAX17040
 config BATTERY_MAX17042
        tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge"
        depends on I2C
+       select REGMAP_I2C
        help
          MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
          in handheld and portable equipment. The MAX17042 is configured
index 00e6672963601754262ced9e842f31c27e07c69e..557af943b2f53d0a3ee2a280122e42e69db94c67 100644 (file)
@@ -511,6 +511,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        dev_set_drvdata(dev, psy);
        psy->dev = dev;
 
+       rc = dev_set_name(dev, "%s", psy->name);
+       if (rc)
+               goto dev_set_name_failed;
+
        INIT_WORK(&psy->changed_work, power_supply_changed_work);
 
        rc = power_supply_check_supplies(psy);
@@ -524,10 +528,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto wakeup_init_failed;
 
-       rc = kobject_set_name(&dev->kobj, "%s", psy->name);
-       if (rc)
-               goto kobject_set_name_failed;
-
        rc = device_add(dev);
        if (rc)
                goto device_add_failed;
@@ -553,11 +553,11 @@ create_triggers_failed:
 register_cooler_failed:
        psy_unregister_thermal(psy);
 register_thermal_failed:
-wakeup_init_failed:
        device_del(dev);
-kobject_set_name_failed:
 device_add_failed:
+wakeup_init_failed:
 check_supplies_failed:
+dev_set_name_failed:
        put_device(dev);
 success:
        return rc;
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 3f4ca4e09a4ccc4d49fba39d64094fafe1f1fdc7..34629ea913d4eb3bd77fefee02bd301e946cf5a3 100644 (file)
@@ -942,7 +942,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
                return rc;
        }
 
-       tp->screen = tty3270_alloc_screen(tp->view.cols, tp->view.rows);
+       tp->screen = tty3270_alloc_screen(tp->view.rows, tp->view.cols);
        if (IS_ERR(tp->screen)) {
                rc = PTR_ERR(tp->screen);
                raw3270_put_view(&tp->view);
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 51ae940adce2bc01a401e56b53f82ea62bb7ebe0..710599f54cc5f8bf7b8782ab5b47ab0b21e46a7b 100644 (file)
@@ -118,6 +118,13 @@ config SPI_BCM63XX
        help
           Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
 
+config SPI_BCM63XX_HSSPI
+       tristate "Broadcom BCM63XX HS SPI controller driver"
+       depends on BCM63XX || COMPILE_TEST
+       help
+         This enables support for the High Speed SPI controller present on
+         newer Broadcom BCM63XX SoCs.
+
 config SPI_BITBANG
        tristate "Utilities for Bitbanging SPI masters"
        help
@@ -159,7 +166,6 @@ config SPI_DAVINCI
        tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
        depends on ARCH_DAVINCI || ARCH_KEYSTONE
        select SPI_BITBANG
-       select TI_EDMA
        help
          SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
@@ -301,6 +307,7 @@ config SPI_OMAP_UWIRE
 
 config SPI_OMAP24XX
        tristate "McSPI driver for OMAP"
+       depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
        depends on ARCH_OMAP2PLUS || COMPILE_TEST
        help
          SPI master controller for OMAP24XX and later Multichannel SPI
@@ -370,7 +377,7 @@ config SPI_PXA2XX_PCI
 
 config SPI_RSPI
        tristate "Renesas RSPI controller"
-       depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE
+       depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
        help
          SPI driver for Renesas RSPI blocks.
 
index ab8d8644af0e9e97e66d082c472f2a83793dfbd7..95af48d2d360d694e25012c80fa0cf127222db16 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79)                       += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
+obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
 obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
 obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
index 595b62cb545d9f804a6fe64bc07c20a6a892892d..5d7deaf628670b1cfad9c92b21d66c03a7c8d805 100644 (file)
@@ -220,8 +220,6 @@ static int altera_spi_probe(struct platform_device *pdev)
 
        /* setup the state for the bitbang driver */
        hw->bitbang.master = master;
-       if (!hw->bitbang.master)
-               return err;
        hw->bitbang.chipselect = altera_spi_chipsel;
        hw->bitbang.txrx_bufs = altera_spi_txrx;
 
index 821bf7ac218d965411027e3ce7efe16ed8e3e567..31534b51715aa95e29664cc80d44d71b5131d0ab 100644 (file)
@@ -243,21 +243,21 @@ static int ath79_spi_probe(struct platform_device *pdev)
                goto err_put_master;
        }
 
-       sp->base = ioremap(r->start, resource_size(r));
+       sp->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
        if (!sp->base) {
                ret = -ENXIO;
                goto err_put_master;
        }
 
-       sp->clk = clk_get(&pdev->dev, "ahb");
+       sp->clk = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(sp->clk)) {
                ret = PTR_ERR(sp->clk);
-               goto err_unmap;
+               goto err_put_master;
        }
 
        ret = clk_enable(sp->clk);
        if (ret)
-               goto err_clk_put;
+               goto err_put_master;
 
        rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
        if (!rate) {
@@ -280,10 +280,6 @@ err_disable:
        ath79_spi_disable(sp);
 err_clk_disable:
        clk_disable(sp->clk);
-err_clk_put:
-       clk_put(sp->clk);
-err_unmap:
-       iounmap(sp->base);
 err_put_master:
        spi_master_put(sp->bitbang.master);
 
@@ -297,8 +293,6 @@ static int ath79_spi_remove(struct platform_device *pdev)
        spi_bitbang_stop(&sp->bitbang);
        ath79_spi_disable(sp);
        clk_disable(sp->clk);
-       clk_put(sp->clk);
-       iounmap(sp->base);
        spi_master_put(sp->bitbang.master);
 
        return 0;
index 273db0beb2b88ffeb588307ce08b2cb40120c790..b0842f75101647616ada3a3db4f545a57b519be0 100644 (file)
  */
 #define DMA_MIN_BYTES  16
 
+#define SPI_DMA_TIMEOUT                (msecs_to_jiffies(1000))
+
 struct atmel_spi_dma {
        struct dma_chan                 *chan_rx;
        struct dma_chan                 *chan_tx;
@@ -220,17 +222,13 @@ struct atmel_spi {
        int                     irq;
        struct clk              *clk;
        struct platform_device  *pdev;
-       struct spi_device       *stay;
 
-       u8                      stopping;
-       struct list_head        queue;
-       struct tasklet_struct   tasklet;
        struct spi_transfer     *current_transfer;
        unsigned long           current_remaining_bytes;
-       struct spi_transfer     *next_transfer;
-       unsigned long           next_remaining_bytes;
        int                     done_status;
 
+       struct completion       xfer_completion;
+
        /* scratch buffer */
        void                    *buffer;
        dma_addr_t              buffer_dma;
@@ -241,6 +239,9 @@ struct atmel_spi {
        bool                    use_pdc;
        /* dmaengine data */
        struct atmel_spi_dma    dma;
+
+       bool                    keep_cs;
+       bool                    cs_active;
 };
 
 /* Controller-specific per-slave state */
@@ -376,17 +377,6 @@ static inline bool atmel_spi_use_dma(struct atmel_spi *as,
        return as->use_dma && xfer->len >= DMA_MIN_BYTES;
 }
 
-static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
-                                       struct spi_transfer *xfer)
-{
-       return msg->transfers.prev == &xfer->transfer_list;
-}
-
-static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
-{
-       return xfer->delay_usecs == 0 && !xfer->cs_change;
-}
-
 static int atmel_spi_dma_slave_config(struct atmel_spi *as,
                                struct dma_slave_config *slave_config,
                                u8 bits_per_word)
@@ -513,23 +503,20 @@ static void dma_callback(void *data)
        struct spi_master       *master = data;
        struct atmel_spi        *as = spi_master_get_devdata(master);
 
-       /* trigger SPI tasklet */
-       tasklet_schedule(&as->tasklet);
+       complete(&as->xfer_completion);
 }
 
 /*
  * Next transfer using PIO.
- * lock is held, spi tasklet is blocked
  */
 static void atmel_spi_next_xfer_pio(struct spi_master *master,
                                struct spi_transfer *xfer)
 {
        struct atmel_spi        *as = spi_master_get_devdata(master);
+       unsigned long xfer_pos = xfer->len - as->current_remaining_bytes;
 
        dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_pio\n");
 
-       as->current_remaining_bytes = xfer->len;
-
        /* Make sure data is not remaining in RDR */
        spi_readl(as, RDR);
        while (spi_readl(as, SR) & SPI_BIT(RDRF)) {
@@ -537,13 +524,14 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
                cpu_relax();
        }
 
-       if (xfer->tx_buf)
+       if (xfer->tx_buf) {
                if (xfer->bits_per_word > 8)
-                       spi_writel(as, TDR, *(u16 *)(xfer->tx_buf));
+                       spi_writel(as, TDR, *(u16 *)(xfer->tx_buf + xfer_pos));
                else
-                       spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
-       else
+                       spi_writel(as, TDR, *(u8 *)(xfer->tx_buf + xfer_pos));
+       } else {
                spi_writel(as, TDR, 0);
+       }
 
        dev_dbg(master->dev.parent,
                "  start pio xfer %p: len %u tx %p rx %p bitpw %d\n",
@@ -556,7 +544,6 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
 
 /*
  * Submit next transfer for DMA.
- * lock is held, spi tasklet is blocked
  */
 static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
                                struct spi_transfer *xfer,
@@ -694,74 +681,90 @@ static void atmel_spi_next_xfer_data(struct spi_master *master,
        *plen = len;
 }
 
+static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
+                                   struct spi_device *spi,
+                                   struct spi_transfer *xfer)
+{
+       u32                     scbr, csr;
+       unsigned long           bus_hz;
+
+       /* v1 chips start out at half the peripheral bus speed. */
+       bus_hz = clk_get_rate(as->clk);
+       if (!atmel_spi_is_v2(as))
+               bus_hz /= 2;
+
+       /*
+        * Calculate the lowest divider that satisfies the
+        * constraint, assuming div32/fdiv/mbz == 0.
+        */
+       if (xfer->speed_hz)
+               scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
+       else
+               /*
+                * This can happend if max_speed is null.
+                * In this case, we set the lowest possible speed
+                */
+               scbr = 0xff;
+
+       /*
+        * If the resulting divider doesn't fit into the
+        * register bitfield, we can't satisfy the constraint.
+        */
+       if (scbr >= (1 << SPI_SCBR_SIZE)) {
+               dev_err(&spi->dev,
+                       "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
+                       xfer->speed_hz, scbr, bus_hz/255);
+               return -EINVAL;
+       }
+       if (scbr == 0) {
+               dev_err(&spi->dev,
+                       "setup: %d Hz too high, scbr %u; max %ld Hz\n",
+                       xfer->speed_hz, scbr, bus_hz);
+               return -EINVAL;
+       }
+       csr = spi_readl(as, CSR0 + 4 * spi->chip_select);
+       csr = SPI_BFINS(SCBR, scbr, csr);
+       spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
+
+       return 0;
+}
+
 /*
  * Submit next transfer for PDC.
  * lock is held, spi irq is blocked
  */
 static void atmel_spi_pdc_next_xfer(struct spi_master *master,
-                               struct spi_message *msg)
+                                       struct spi_message *msg,
+                                       struct spi_transfer *xfer)
 {
        struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_transfer     *xfer;
-       u32                     len, remaining;
-       u32                     ieval;
+       u32                     len;
        dma_addr_t              tx_dma, rx_dma;
 
-       if (!as->current_transfer)
-               xfer = list_entry(msg->transfers.next,
-                               struct spi_transfer, transfer_list);
-       else if (!as->next_transfer)
-               xfer = list_entry(as->current_transfer->transfer_list.next,
-                               struct spi_transfer, transfer_list);
-       else
-               xfer = NULL;
-
-       if (xfer) {
-               spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-
-               len = xfer->len;
-               atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
-               remaining = xfer->len - len;
-
-               spi_writel(as, RPR, rx_dma);
-               spi_writel(as, TPR, tx_dma);
-
-               if (msg->spi->bits_per_word > 8)
-                       len >>= 1;
-               spi_writel(as, RCR, len);
-               spi_writel(as, TCR, len);
-
-               dev_dbg(&msg->spi->dev,
-                       "  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
-                       xfer, xfer->len, xfer->tx_buf,
-                       (unsigned long long)xfer->tx_dma, xfer->rx_buf,
-                       (unsigned long long)xfer->rx_dma);
-       } else {
-               xfer = as->next_transfer;
-               remaining = as->next_remaining_bytes;
-       }
+       spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
 
-       as->current_transfer = xfer;
-       as->current_remaining_bytes = remaining;
+       len = as->current_remaining_bytes;
+       atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+       as->current_remaining_bytes -= len;
 
-       if (remaining > 0)
-               len = remaining;
-       else if (!atmel_spi_xfer_is_last(msg, xfer)
-                       && atmel_spi_xfer_can_be_chained(xfer)) {
-               xfer = list_entry(xfer->transfer_list.next,
-                               struct spi_transfer, transfer_list);
-               len = xfer->len;
-       } else
-               xfer = NULL;
+       spi_writel(as, RPR, rx_dma);
+       spi_writel(as, TPR, tx_dma);
 
-       as->next_transfer = xfer;
+       if (msg->spi->bits_per_word > 8)
+               len >>= 1;
+       spi_writel(as, RCR, len);
+       spi_writel(as, TCR, len);
 
-       if (xfer) {
-               u32     total;
+       dev_dbg(&msg->spi->dev,
+               "  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
+               xfer, xfer->len, xfer->tx_buf,
+               (unsigned long long)xfer->tx_dma, xfer->rx_buf,
+               (unsigned long long)xfer->rx_dma);
 
-               total = len;
+       if (as->current_remaining_bytes) {
+               len = as->current_remaining_bytes;
                atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
-               as->next_remaining_bytes = total - len;
+               as->current_remaining_bytes -= len;
 
                spi_writel(as, RNPR, rx_dma);
                spi_writel(as, TNPR, tx_dma);
@@ -776,11 +779,6 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
                        xfer, xfer->len, xfer->tx_buf,
                        (unsigned long long)xfer->tx_dma, xfer->rx_buf,
                        (unsigned long long)xfer->rx_dma);
-               ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES);
-       } else {
-               spi_writel(as, RNCR, 0);
-               spi_writel(as, TNCR, 0);
-               ieval = SPI_BIT(RXBUFF) | SPI_BIT(ENDRX) | SPI_BIT(OVRES);
        }
 
        /* REVISIT: We're waiting for ENDRX before we start the next
@@ -793,82 +791,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
         *
         * It should be doable, though. Just not now...
         */
-       spi_writel(as, IER, ieval);
+       spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
        spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
 }
 
-/*
- * Choose way to submit next transfer and start it.
- * lock is held, spi tasklet is blocked
- */
-static void atmel_spi_dma_next_xfer(struct spi_master *master,
-                               struct spi_message *msg)
-{
-       struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_transfer     *xfer;
-       u32     remaining, len;
-
-       remaining = as->current_remaining_bytes;
-       if (remaining) {
-               xfer = as->current_transfer;
-               len = remaining;
-       } else {
-               if (!as->current_transfer)
-                       xfer = list_entry(msg->transfers.next,
-                               struct spi_transfer, transfer_list);
-               else
-                       xfer = list_entry(
-                               as->current_transfer->transfer_list.next,
-                                       struct spi_transfer, transfer_list);
-
-               as->current_transfer = xfer;
-               len = xfer->len;
-       }
-
-       if (atmel_spi_use_dma(as, xfer)) {
-               u32 total = len;
-               if (!atmel_spi_next_xfer_dma_submit(master, xfer, &len)) {
-                       as->current_remaining_bytes = total - len;
-                       return;
-               } else {
-                       dev_err(&msg->spi->dev, "unable to use DMA, fallback to PIO\n");
-               }
-       }
-
-       /* use PIO if error appened using DMA */
-       atmel_spi_next_xfer_pio(master, xfer);
-}
-
-static void atmel_spi_next_message(struct spi_master *master)
-{
-       struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_device       *spi;
-
-       BUG_ON(as->current_transfer);
-
-       msg = list_entry(as->queue.next, struct spi_message, queue);
-       spi = msg->spi;
-
-       dev_dbg(master->dev.parent, "start message %p for %s\n",
-                       msg, dev_name(&spi->dev));
-
-       /* select chip if it's not still active */
-       if (as->stay) {
-               if (as->stay != spi) {
-                       cs_deactivate(as, as->stay);
-                       cs_activate(as, spi);
-               }
-               as->stay = NULL;
-       } else
-               cs_activate(as, spi);
-
-       if (as->use_pdc)
-               atmel_spi_pdc_next_xfer(master, msg);
-       else
-               atmel_spi_dma_next_xfer(master, msg);
-}
-
 /*
  * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
  *  - The buffer is either valid for CPU access, else NULL
@@ -924,41 +850,7 @@ static void atmel_spi_disable_pdc_transfer(struct atmel_spi *as)
        spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
 }
 
-static void
-atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-               struct spi_message *msg, int stay)
-{
-       if (!stay || as->done_status < 0)
-               cs_deactivate(as, msg->spi);
-       else
-               as->stay = msg->spi;
-
-       list_del(&msg->queue);
-       msg->status = as->done_status;
-
-       dev_dbg(master->dev.parent,
-               "xfer complete: %u bytes transferred\n",
-               msg->actual_length);
-
-       atmel_spi_unlock(as);
-       msg->complete(msg->context);
-       atmel_spi_lock(as);
-
-       as->current_transfer = NULL;
-       as->next_transfer = NULL;
-       as->done_status = 0;
-
-       /* continue if needed */
-       if (list_empty(&as->queue) || as->stopping) {
-               if (as->use_pdc)
-                       atmel_spi_disable_pdc_transfer(as);
-       } else {
-               atmel_spi_next_message(master);
-       }
-}
-
 /* Called from IRQ
- * lock is held
  *
  * Must update "current_remaining_bytes" to keep track of data
  * to transfer.
@@ -966,9 +858,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 static void
 atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
 {
-       u8              *txp;
        u8              *rxp;
-       u16             *txp16;
        u16             *rxp16;
        unsigned long   xfer_pos = xfer->len - as->current_remaining_bytes;
 
@@ -990,96 +880,12 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
        } else {
                as->current_remaining_bytes--;
        }
-
-       if (as->current_remaining_bytes) {
-               if (xfer->tx_buf) {
-                       if (xfer->bits_per_word > 8) {
-                               txp16 = (u16 *)(((u8 *)xfer->tx_buf)
-                                                       + xfer_pos + 2);
-                               spi_writel(as, TDR, *txp16);
-                       } else {
-                               txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
-                               spi_writel(as, TDR, *txp);
-                       }
-               } else {
-                       spi_writel(as, TDR, 0);
-               }
-       }
-}
-
-/* Tasklet
- * Called from DMA callback + pio transfer and overrun IRQ.
- */
-static void atmel_spi_tasklet_func(unsigned long data)
-{
-       struct spi_master       *master = (struct spi_master *)data;
-       struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_transfer     *xfer;
-
-       dev_vdbg(master->dev.parent, "atmel_spi_tasklet_func\n");
-
-       atmel_spi_lock(as);
-
-       xfer = as->current_transfer;
-
-       if (xfer == NULL)
-               /* already been there */
-               goto tasklet_out;
-
-       msg = list_entry(as->queue.next, struct spi_message, queue);
-
-       if (as->current_remaining_bytes == 0) {
-               if (as->done_status < 0) {
-                       /* error happened (overrun) */
-                       if (atmel_spi_use_dma(as, xfer))
-                               atmel_spi_stop_dma(as);
-               } else {
-                       /* only update length if no error */
-                       msg->actual_length += xfer->len;
-               }
-
-               if (atmel_spi_use_dma(as, xfer))
-                       if (!msg->is_dma_mapped)
-                               atmel_spi_dma_unmap_xfer(master, xfer);
-
-               if (xfer->delay_usecs)
-                       udelay(xfer->delay_usecs);
-
-               if (atmel_spi_xfer_is_last(msg, xfer) || as->done_status < 0) {
-                       /* report completed (or erroneous) message */
-                       atmel_spi_msg_done(master, as, msg, xfer->cs_change);
-               } else {
-                       if (xfer->cs_change) {
-                               cs_deactivate(as, msg->spi);
-                               udelay(1);
-                               cs_activate(as, msg->spi);
-                       }
-
-                       /*
-                        * Not done yet. Submit the next transfer.
-                        *
-                        * FIXME handle protocol options for xfer
-                        */
-                       atmel_spi_dma_next_xfer(master, msg);
-               }
-       } else {
-               /*
-                * Keep going, we still have data to send in
-                * the current transfer.
-                */
-               atmel_spi_dma_next_xfer(master, msg);
-       }
-
-tasklet_out:
-       atmel_spi_unlock(as);
 }
 
 /* Interrupt
  *
  * No need for locking in this Interrupt handler: done_status is the
- * only information modified. What we need is the update of this field
- * before tasklet runs. This is ensured by using barrier.
+ * only information modified.
  */
 static irqreturn_t
 atmel_spi_pio_interrupt(int irq, void *dev_id)
@@ -1107,8 +913,6 @@ atmel_spi_pio_interrupt(int irq, void *dev_id)
                 *
                 * We will also not process any remaning transfers in
                 * the message.
-                *
-                * All actions are done in tasklet with done_status indication
                 */
                as->done_status = -EIO;
                smp_wmb();
@@ -1116,7 +920,7 @@ atmel_spi_pio_interrupt(int irq, void *dev_id)
                /* Clear any overrun happening while cleaning up */
                spi_readl(as, SR);
 
-               tasklet_schedule(&as->tasklet);
+               complete(&as->xfer_completion);
 
        } else if (pending & SPI_BIT(RDRF)) {
                atmel_spi_lock(as);
@@ -1125,11 +929,10 @@ atmel_spi_pio_interrupt(int irq, void *dev_id)
                        ret = IRQ_HANDLED;
                        xfer = as->current_transfer;
                        atmel_spi_pump_pio_data(as, xfer);
-                       if (!as->current_remaining_bytes) {
-                               /* no more data to xfer, kick tasklet */
+                       if (!as->current_remaining_bytes)
                                spi_writel(as, IDR, pending);
-                               tasklet_schedule(&as->tasklet);
-                       }
+
+                       complete(&as->xfer_completion);
                }
 
                atmel_spi_unlock(as);
@@ -1147,116 +950,35 @@ atmel_spi_pdc_interrupt(int irq, void *dev_id)
 {
        struct spi_master       *master = dev_id;
        struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_transfer     *xfer;
        u32                     status, pending, imr;
        int                     ret = IRQ_NONE;
 
-       atmel_spi_lock(as);
-
-       xfer = as->current_transfer;
-       msg = list_entry(as->queue.next, struct spi_message, queue);
-
        imr = spi_readl(as, IMR);
        status = spi_readl(as, SR);
        pending = status & imr;
 
        if (pending & SPI_BIT(OVRES)) {
-               int timeout;
 
                ret = IRQ_HANDLED;
 
                spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX)
                                     | SPI_BIT(OVRES)));
 
-               /*
-                * When we get an overrun, we disregard the current
-                * transfer. Data will not be copied back from any
-                * bounce buffer and msg->actual_len will not be
-                * updated with the last xfer.
-                *
-                * We will also not process any remaning transfers in
-                * the message.
-                *
-                * First, stop the transfer and unmap the DMA buffers.
-                */
-               spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-               if (!msg->is_dma_mapped)
-                       atmel_spi_dma_unmap_xfer(master, xfer);
-
-               /* REVISIT: udelay in irq is unfriendly */
-               if (xfer->delay_usecs)
-                       udelay(xfer->delay_usecs);
-
-               dev_warn(master->dev.parent, "overrun (%u/%u remaining)\n",
-                        spi_readl(as, TCR), spi_readl(as, RCR));
-
-               /*
-                * Clean up DMA registers and make sure the data
-                * registers are empty.
-                */
-               spi_writel(as, RNCR, 0);
-               spi_writel(as, TNCR, 0);
-               spi_writel(as, RCR, 0);
-               spi_writel(as, TCR, 0);
-               for (timeout = 1000; timeout; timeout--)
-                       if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
-                               break;
-               if (!timeout)
-                       dev_warn(master->dev.parent,
-                                "timeout waiting for TXEMPTY");
-               while (spi_readl(as, SR) & SPI_BIT(RDRF))
-                       spi_readl(as, RDR);
-
                /* Clear any overrun happening while cleaning up */
                spi_readl(as, SR);
 
                as->done_status = -EIO;
-               atmel_spi_msg_done(master, as, msg, 0);
+
+               complete(&as->xfer_completion);
+
        } else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
                ret = IRQ_HANDLED;
 
                spi_writel(as, IDR, pending);
 
-               if (as->current_remaining_bytes == 0) {
-                       msg->actual_length += xfer->len;
-
-                       if (!msg->is_dma_mapped)
-                               atmel_spi_dma_unmap_xfer(master, xfer);
-
-                       /* REVISIT: udelay in irq is unfriendly */
-                       if (xfer->delay_usecs)
-                               udelay(xfer->delay_usecs);
-
-                       if (atmel_spi_xfer_is_last(msg, xfer)) {
-                               /* report completed message */
-                               atmel_spi_msg_done(master, as, msg,
-                                               xfer->cs_change);
-                       } else {
-                               if (xfer->cs_change) {
-                                       cs_deactivate(as, msg->spi);
-                                       udelay(1);
-                                       cs_activate(as, msg->spi);
-                               }
-
-                               /*
-                                * Not done yet. Submit the next transfer.
-                                *
-                                * FIXME handle protocol options for xfer
-                                */
-                               atmel_spi_pdc_next_xfer(master, msg);
-                       }
-               } else {
-                       /*
-                        * Keep going, we still have data to send in
-                        * the current transfer.
-                        */
-                       atmel_spi_pdc_next_xfer(master, msg);
-               }
+               complete(&as->xfer_completion);
        }
 
-       atmel_spi_unlock(as);
-
        return ret;
 }
 
@@ -1264,17 +986,13 @@ static int atmel_spi_setup(struct spi_device *spi)
 {
        struct atmel_spi        *as;
        struct atmel_spi_device *asd;
-       u32                     scbr, csr;
+       u32                     csr;
        unsigned int            bits = spi->bits_per_word;
-       unsigned long           bus_hz;
        unsigned int            npcs_pin;
        int                     ret;
 
        as = spi_master_get_devdata(spi->master);
 
-       if (as->stopping)
-               return -ESHUTDOWN;
-
        if (spi->chip_select > spi->master->num_chipselect) {
                dev_dbg(&spi->dev,
                                "setup: invalid chipselect %u (%u defined)\n",
@@ -1290,33 +1008,7 @@ static int atmel_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       /* v1 chips start out at half the peripheral bus speed. */
-       bus_hz = clk_get_rate(as->clk);
-       if (!atmel_spi_is_v2(as))
-               bus_hz /= 2;
-
-       if (spi->max_speed_hz) {
-               /*
-                * Calculate the lowest divider that satisfies the
-                * constraint, assuming div32/fdiv/mbz == 0.
-                */
-               scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
-
-               /*
-                * If the resulting divider doesn't fit into the
-                * register bitfield, we can't satisfy the constraint.
-                */
-               if (scbr >= (1 << SPI_SCBR_SIZE)) {
-                       dev_dbg(&spi->dev,
-                               "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
-                               spi->max_speed_hz, scbr, bus_hz/255);
-                       return -EINVAL;
-               }
-       } else
-               /* speed zero means "as slow as possible" */
-               scbr = 0xff;
-
-       csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
+       csr = SPI_BF(BITS, bits - 8);
        if (spi->mode & SPI_CPOL)
                csr |= SPI_BIT(CPOL);
        if (!(spi->mode & SPI_CPHA))
@@ -1352,19 +1044,13 @@ static int atmel_spi_setup(struct spi_device *spi)
                asd->npcs_pin = npcs_pin;
                spi->controller_state = asd;
                gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
-       } else {
-               atmel_spi_lock(as);
-               if (as->stay == spi)
-                       as->stay = NULL;
-               cs_deactivate(as, spi);
-               atmel_spi_unlock(as);
        }
 
        asd->csr = csr;
 
        dev_dbg(&spi->dev,
-               "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
-               bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
+               "setup: bpw %u mode 0x%x -> csr%d %08x\n",
+               bits, spi->mode, spi->chip_select, csr);
 
        if (!atmel_spi_is_v2(as))
                spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
@@ -1372,103 +1058,218 @@ static int atmel_spi_setup(struct spi_device *spi)
        return 0;
 }
 
-static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+static int atmel_spi_one_transfer(struct spi_master *master,
+                                       struct spi_message *msg,
+                                       struct spi_transfer *xfer)
 {
        struct atmel_spi        *as;
-       struct spi_transfer     *xfer;
-       struct device           *controller = spi->master->dev.parent;
+       struct spi_device       *spi = msg->spi;
        u8                      bits;
+       u32                     len;
        struct atmel_spi_device *asd;
+       int                     timeout;
+       int                     ret;
 
-       as = spi_master_get_devdata(spi->master);
-
-       dev_dbg(controller, "new message %p submitted for %s\n",
-                       msg, dev_name(&spi->dev));
+       as = spi_master_get_devdata(master);
 
-       if (unlikely(list_empty(&msg->transfers)))
+       if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
+               dev_dbg(&spi->dev, "missing rx or tx buf\n");
                return -EINVAL;
+       }
 
-       if (as->stopping)
-               return -ESHUTDOWN;
+       if (xfer->bits_per_word) {
+               asd = spi->controller_state;
+               bits = (asd->csr >> 4) & 0xf;
+               if (bits != xfer->bits_per_word - 8) {
+                       dev_dbg(&spi->dev,
+                       "you can't yet change bits_per_word in transfers\n");
+                       return -ENOPROTOOPT;
+               }
+       }
 
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
-                       dev_dbg(&spi->dev, "missing rx or tx buf\n");
+       if (xfer->bits_per_word > 8) {
+               if (xfer->len % 2) {
+                       dev_dbg(&spi->dev,
+                       "buffer len should be 16 bits aligned\n");
                        return -EINVAL;
                }
+       }
 
-               if (xfer->bits_per_word) {
-                       asd = spi->controller_state;
-                       bits = (asd->csr >> 4) & 0xf;
-                       if (bits != xfer->bits_per_word - 8) {
-                               dev_dbg(&spi->dev,
-                                       "you can't yet change bits_per_word in transfers\n");
-                               return -ENOPROTOOPT;
+       /*
+        * DMA map early, for performance (empties dcache ASAP) and
+        * better fault reporting.
+        */
+       if ((!msg->is_dma_mapped)
+               && (atmel_spi_use_dma(as, xfer) || as->use_pdc)) {
+               if (atmel_spi_dma_map_xfer(as, xfer) < 0)
+                       return -ENOMEM;
+       }
+
+       atmel_spi_set_xfer_speed(as, msg->spi, xfer);
+
+       as->done_status = 0;
+       as->current_transfer = xfer;
+       as->current_remaining_bytes = xfer->len;
+       while (as->current_remaining_bytes) {
+               reinit_completion(&as->xfer_completion);
+
+               if (as->use_pdc) {
+                       atmel_spi_pdc_next_xfer(master, msg, xfer);
+               } else if (atmel_spi_use_dma(as, xfer)) {
+                       len = as->current_remaining_bytes;
+                       ret = atmel_spi_next_xfer_dma_submit(master,
+                                                               xfer, &len);
+                       if (ret) {
+                               dev_err(&spi->dev,
+                                       "unable to use DMA, fallback to PIO\n");
+                               atmel_spi_next_xfer_pio(master, xfer);
+                       } else {
+                               as->current_remaining_bytes -= len;
                        }
+               } else {
+                       atmel_spi_next_xfer_pio(master, xfer);
                }
 
-               if (xfer->bits_per_word > 8) {
-                       if (xfer->len % 2) {
-                               dev_dbg(&spi->dev, "buffer len should be 16 bits aligned\n");
-                               return -EINVAL;
-                       }
+               ret = wait_for_completion_timeout(&as->xfer_completion,
+                                                       SPI_DMA_TIMEOUT);
+               if (WARN_ON(ret == 0)) {
+                       dev_err(&spi->dev,
+                               "spi trasfer timeout, err %d\n", ret);
+                       as->done_status = -EIO;
+               } else {
+                       ret = 0;
                }
 
-               /* FIXME implement these protocol options!! */
-               if (xfer->speed_hz < spi->max_speed_hz) {
-                       dev_dbg(&spi->dev, "can't change speed in transfer\n");
-                       return -ENOPROTOOPT;
+               if (as->done_status)
+                       break;
+       }
+
+       if (as->done_status) {
+               if (as->use_pdc) {
+                       dev_warn(master->dev.parent,
+                               "overrun (%u/%u remaining)\n",
+                               spi_readl(as, TCR), spi_readl(as, RCR));
+
+                       /*
+                        * Clean up DMA registers and make sure the data
+                        * registers are empty.
+                        */
+                       spi_writel(as, RNCR, 0);
+                       spi_writel(as, TNCR, 0);
+                       spi_writel(as, RCR, 0);
+                       spi_writel(as, TCR, 0);
+                       for (timeout = 1000; timeout; timeout--)
+                               if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
+                                       break;
+                       if (!timeout)
+                               dev_warn(master->dev.parent,
+                                        "timeout waiting for TXEMPTY");
+                       while (spi_readl(as, SR) & SPI_BIT(RDRF))
+                               spi_readl(as, RDR);
+
+                       /* Clear any overrun happening while cleaning up */
+                       spi_readl(as, SR);
+
+               } else if (atmel_spi_use_dma(as, xfer)) {
+                       atmel_spi_stop_dma(as);
                }
 
-               /*
-                * DMA map early, for performance (empties dcache ASAP) and
-                * better fault reporting.
-                */
-               if ((!msg->is_dma_mapped) && (atmel_spi_use_dma(as, xfer)
-                       || as->use_pdc)) {
-                       if (atmel_spi_dma_map_xfer(as, xfer) < 0)
-                               return -ENOMEM;
+               if (!msg->is_dma_mapped
+                       && (atmel_spi_use_dma(as, xfer) || as->use_pdc))
+                       atmel_spi_dma_unmap_xfer(master, xfer);
+
+               return 0;
+
+       } else {
+               /* only update length if no error */
+               msg->actual_length += xfer->len;
+       }
+
+       if (!msg->is_dma_mapped
+               && (atmel_spi_use_dma(as, xfer) || as->use_pdc))
+               atmel_spi_dma_unmap_xfer(master, xfer);
+
+       if (xfer->delay_usecs)
+               udelay(xfer->delay_usecs);
+
+       if (xfer->cs_change) {
+               if (list_is_last(&xfer->transfer_list,
+                                &msg->transfers)) {
+                       as->keep_cs = true;
+               } else {
+                       as->cs_active = !as->cs_active;
+                       if (as->cs_active)
+                               cs_activate(as, msg->spi);
+                       else
+                               cs_deactivate(as, msg->spi);
                }
        }
 
-#ifdef VERBOSE
+       return 0;
+}
+
+static int atmel_spi_transfer_one_message(struct spi_master *master,
+                                               struct spi_message *msg)
+{
+       struct atmel_spi *as;
+       struct spi_transfer *xfer;
+       struct spi_device *spi = msg->spi;
+       int ret = 0;
+
+       as = spi_master_get_devdata(master);
+
+       dev_dbg(&spi->dev, "new message %p submitted for %s\n",
+                                       msg, dev_name(&spi->dev));
+
+       if (unlikely(list_empty(&msg->transfers)))
+               return -EINVAL;
+
+       atmel_spi_lock(as);
+       cs_activate(as, spi);
+
+       as->cs_active = true;
+       as->keep_cs = false;
+
+       msg->status = 0;
+       msg->actual_length = 0;
+
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               dev_dbg(controller,
+               ret = atmel_spi_one_transfer(master, msg, xfer);
+               if (ret)
+                       goto msg_done;
+       }
+
+       if (as->use_pdc)
+               atmel_spi_disable_pdc_transfer(as);
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               dev_dbg(&spi->dev,
                        "  xfer %p: len %u tx %p/%08x rx %p/%08x\n",
                        xfer, xfer->len,
                        xfer->tx_buf, xfer->tx_dma,
                        xfer->rx_buf, xfer->rx_dma);
        }
-#endif
 
-       msg->status = -EINPROGRESS;
-       msg->actual_length = 0;
+msg_done:
+       if (!as->keep_cs)
+               cs_deactivate(as, msg->spi);
 
-       atmel_spi_lock(as);
-       list_add_tail(&msg->queue, &as->queue);
-       if (!as->current_transfer)
-               atmel_spi_next_message(spi->master);
        atmel_spi_unlock(as);
 
-       return 0;
+       msg->status = as->done_status;
+       spi_finalize_current_message(spi->master);
+
+       return ret;
 }
 
 static void atmel_spi_cleanup(struct spi_device *spi)
 {
-       struct atmel_spi        *as = spi_master_get_devdata(spi->master);
        struct atmel_spi_device *asd = spi->controller_state;
        unsigned                gpio = (unsigned) spi->controller_data;
 
        if (!asd)
                return;
 
-       atmel_spi_lock(as);
-       if (as->stay == spi) {
-               as->stay = NULL;
-               cs_deactivate(as, spi);
-       }
-       atmel_spi_unlock(as);
-
        spi->controller_state = NULL;
        gpio_free(gpio);
        kfree(asd);
@@ -1510,7 +1311,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        if (irq < 0)
                return irq;
 
-       clk = clk_get(&pdev->dev, "spi_clk");
+       clk = devm_clk_get(&pdev->dev, "spi_clk");
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
@@ -1527,7 +1328,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        master->bus_num = pdev->id;
        master->num_chipselect = master->dev.of_node ? 0 : 4;
        master->setup = atmel_spi_setup;
-       master->transfer = atmel_spi_transfer;
+       master->transfer_one_message = atmel_spi_transfer_one_message;
        master->cleanup = atmel_spi_cleanup;
        platform_set_drvdata(pdev, master);
 
@@ -1543,7 +1344,6 @@ static int atmel_spi_probe(struct platform_device *pdev)
                goto out_free;
 
        spin_lock_init(&as->lock);
-       INIT_LIST_HEAD(&as->queue);
 
        as->pdev = pdev;
        as->regs = devm_ioremap_resource(&pdev->dev, regs);
@@ -1555,6 +1355,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
        as->irq = irq;
        as->clk = clk;
 
+       init_completion(&as->xfer_completion);
+
        atmel_get_caps(as);
 
        as->use_dma = false;
@@ -1570,14 +1372,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
                dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
 
        if (as->use_pdc) {
-               ret = request_irq(irq, atmel_spi_pdc_interrupt, 0,
-                                       dev_name(&pdev->dev), master);
+               ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pdc_interrupt,
+                                       0, dev_name(&pdev->dev), master);
        } else {
-               tasklet_init(&as->tasklet, atmel_spi_tasklet_func,
-                                       (unsigned long)master);
-
-               ret = request_irq(irq, atmel_spi_pio_interrupt, 0,
-                                       dev_name(&pdev->dev), master);
+               ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pio_interrupt,
+                                       0, dev_name(&pdev->dev), master);
        }
        if (ret)
                goto out_unmap_regs;
@@ -1603,7 +1402,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
                        (unsigned long)regs->start, irq);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret)
                goto out_free_dma;
 
@@ -1617,15 +1416,11 @@ out_free_dma:
        spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
        clk_disable_unprepare(clk);
 out_free_irq:
-       free_irq(irq, master);
 out_unmap_regs:
 out_free_buffer:
-       if (!as->use_pdc)
-               tasklet_kill(&as->tasklet);
        dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
                        as->buffer_dma);
 out_free:
-       clk_put(clk);
        spi_master_put(master);
        return ret;
 }
@@ -1634,12 +1429,9 @@ static int atmel_spi_remove(struct platform_device *pdev)
 {
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
-       struct spi_message      *msg;
-       struct spi_transfer     *xfer;
 
        /* reset the hardware and block queue progress */
        spin_lock_irq(&as->lock);
-       as->stopping = 1;
        if (as->use_dma) {
                atmel_spi_stop_dma(as);
                atmel_spi_release_dma(as);
@@ -1650,28 +1442,10 @@ static int atmel_spi_remove(struct platform_device *pdev)
        spi_readl(as, SR);
        spin_unlock_irq(&as->lock);
 
-       /* Terminate remaining queued transfers */
-       list_for_each_entry(msg, &as->queue, queue) {
-               list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-                       if (!msg->is_dma_mapped
-                               && (atmel_spi_use_dma(as, xfer)
-                                       || as->use_pdc))
-                               atmel_spi_dma_unmap_xfer(master, xfer);
-               }
-               msg->status = -ESHUTDOWN;
-               msg->complete(msg->context);
-       }
-
-       if (!as->use_pdc)
-               tasklet_kill(&as->tasklet);
        dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
                        as->buffer_dma);
 
        clk_disable_unprepare(as->clk);
-       clk_put(as->clk);
-       free_irq(as->irq, master);
-
-       spi_unregister_master(master);
 
        return 0;
 }
index 3ed666fe840a0cdbaf1a2a2c6cd75670dd25fb48..8a89dd1f265427da19089824d284432451c7537c 100644 (file)
@@ -347,8 +347,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 
        clk_prepare_enable(bs->clk);
 
-       err = request_irq(bs->irq, bcm2835_spi_interrupt, 0,
-                       dev_name(&pdev->dev), master);
+       err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
+                               dev_name(&pdev->dev), master);
        if (err) {
                dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
                goto out_clk_disable;
@@ -361,13 +361,11 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        err = devm_spi_register_master(&pdev->dev, master);
        if (err) {
                dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
-               goto out_free_irq;
+               goto out_clk_disable;
        }
 
        return 0;
 
-out_free_irq:
-       free_irq(bs->irq, master);
 out_clk_disable:
        clk_disable_unprepare(bs->clk);
 out_master_put:
@@ -377,11 +375,9 @@ 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);
-
        /* Clear FIFOs, and disable the HW block */
        bcm2835_wr(bs, BCM2835_SPI_CS,
                   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
new file mode 100644 (file)
index 0000000..b528f9f
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * Broadcom BCM63XX High Speed SPI Controller driver
+ *
+ * Copyright 2000-2010 Broadcom Corporation
+ * Copyright 2012-2013 Jonas Gorski <jogo@openwrt.org>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#define HSSPI_GLOBAL_CTRL_REG                  0x0
+#define GLOBAL_CTRL_CS_POLARITY_SHIFT          0
+#define GLOBAL_CTRL_CS_POLARITY_MASK           0x000000ff
+#define GLOBAL_CTRL_PLL_CLK_CTRL_SHIFT         8
+#define GLOBAL_CTRL_PLL_CLK_CTRL_MASK          0x0000ff00
+#define GLOBAL_CTRL_CLK_GATE_SSOFF             BIT(16)
+#define GLOBAL_CTRL_CLK_POLARITY               BIT(17)
+#define GLOBAL_CTRL_MOSI_IDLE                  BIT(18)
+
+#define HSSPI_GLOBAL_EXT_TRIGGER_REG           0x4
+
+#define HSSPI_INT_STATUS_REG                   0x8
+#define HSSPI_INT_STATUS_MASKED_REG            0xc
+#define HSSPI_INT_MASK_REG                     0x10
+
+#define HSSPI_PINGx_CMD_DONE(i)                        BIT((i * 8) + 0)
+#define HSSPI_PINGx_RX_OVER(i)                 BIT((i * 8) + 1)
+#define HSSPI_PINGx_TX_UNDER(i)                        BIT((i * 8) + 2)
+#define HSSPI_PINGx_POLL_TIMEOUT(i)            BIT((i * 8) + 3)
+#define HSSPI_PINGx_CTRL_INVAL(i)              BIT((i * 8) + 4)
+
+#define HSSPI_INT_CLEAR_ALL                    0xff001f1f
+
+#define HSSPI_PINGPONG_COMMAND_REG(x)          (0x80 + (x) * 0x40)
+#define PINGPONG_CMD_COMMAND_MASK              0xf
+#define PINGPONG_COMMAND_NOOP                  0
+#define PINGPONG_COMMAND_START_NOW             1
+#define PINGPONG_COMMAND_START_TRIGGER         2
+#define PINGPONG_COMMAND_HALT                  3
+#define PINGPONG_COMMAND_FLUSH                 4
+#define PINGPONG_CMD_PROFILE_SHIFT             8
+#define PINGPONG_CMD_SS_SHIFT                  12
+
+#define HSSPI_PINGPONG_STATUS_REG(x)           (0x84 + (x) * 0x40)
+
+#define HSSPI_PROFILE_CLK_CTRL_REG(x)          (0x100 + (x) * 0x20)
+#define CLK_CTRL_FREQ_CTRL_MASK                        0x0000ffff
+#define CLK_CTRL_SPI_CLK_2X_SEL                        BIT(14)
+#define CLK_CTRL_ACCUM_RST_ON_LOOP             BIT(15)
+
+#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x)       (0x104 + (x) * 0x20)
+#define SIGNAL_CTRL_LATCH_RISING               BIT(12)
+#define SIGNAL_CTRL_LAUNCH_RISING              BIT(13)
+#define SIGNAL_CTRL_ASYNC_INPUT_PATH           BIT(16)
+
+#define HSSPI_PROFILE_MODE_CTRL_REG(x)         (0x108 + (x) * 0x20)
+#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT      8
+#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT      12
+#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT      16
+#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT      18
+#define MODE_CTRL_MODE_3WIRE                   BIT(20)
+#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT                24
+
+#define HSSPI_FIFO_REG(x)                      (0x200 + (x) * 0x200)
+
+
+#define HSSPI_OP_CODE_SHIFT                    13
+#define HSSPI_OP_SLEEP                         (0 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ_WRITE                    (1 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_WRITE                         (2 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ                          (3 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_SETIRQ                                (4 << HSSPI_OP_CODE_SHIFT)
+
+#define HSSPI_BUFFER_LEN                       512
+#define HSSPI_OPCODE_LEN                       2
+
+#define HSSPI_MAX_PREPEND_LEN                  15
+
+#define HSSPI_MAX_SYNC_CLOCK                   30000000
+
+#define HSSPI_BUS_NUM                          1 /* 0 is legacy SPI */
+
+struct bcm63xx_hsspi {
+       struct completion done;
+       struct mutex bus_mutex;
+
+       struct platform_device *pdev;
+       struct clk *clk;
+       void __iomem *regs;
+       u8 __iomem *fifo;
+
+       u32 speed_hz;
+       u8 cs_polarity;
+};
+
+static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
+                                bool active)
+{
+       u32 reg;
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       reg &= ~BIT(cs);
+       if (active == !(bs->cs_polarity & BIT(cs)))
+               reg |= BIT(cs);
+
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+}
+
+static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
+                                 struct spi_device *spi, int hz)
+{
+       unsigned profile = spi->chip_select;
+       u32 reg;
+
+       reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
+       __raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
+                    bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
+
+       reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+       if (hz > HSSPI_MAX_SYNC_CLOCK)
+               reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
+       else
+               reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
+       __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+
+       mutex_lock(&bs->bus_mutex);
+       /* setup clock polarity */
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       reg &= ~GLOBAL_CTRL_CLK_POLARITY;
+       if (spi->mode & SPI_CPOL)
+               reg |= GLOBAL_CTRL_CLK_POLARITY;
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+}
+
+static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+       unsigned chip_select = spi->chip_select;
+       u16 opcode = 0;
+       int pending = t->len;
+       int step_size = HSSPI_BUFFER_LEN;
+       const u8 *tx = t->tx_buf;
+       u8 *rx = t->rx_buf;
+
+       bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
+       bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);
+
+       if (tx && rx)
+               opcode = HSSPI_OP_READ_WRITE;
+       else if (tx)
+               opcode = HSSPI_OP_WRITE;
+       else if (rx)
+               opcode = HSSPI_OP_READ;
+
+       if (opcode != HSSPI_OP_READ)
+               step_size -= HSSPI_OPCODE_LEN;
+
+       __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
+                    2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
+                    2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
+                    bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
+
+       while (pending > 0) {
+               int curr_step = min_t(int, step_size, pending);
+
+               init_completion(&bs->done);
+               if (tx) {
+                       memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step);
+                       tx += curr_step;
+               }
+
+               __raw_writew(opcode | curr_step, bs->fifo);
+
+               /* enable interrupt */
+               __raw_writel(HSSPI_PINGx_CMD_DONE(0),
+                            bs->regs + HSSPI_INT_MASK_REG);
+
+               /* start the transfer */
+               __raw_writel(!chip_select << PINGPONG_CMD_SS_SHIFT |
+                            chip_select << PINGPONG_CMD_PROFILE_SHIFT |
+                            PINGPONG_COMMAND_START_NOW,
+                            bs->regs + HSSPI_PINGPONG_COMMAND_REG(0));
+
+               if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
+                       dev_err(&bs->pdev->dev, "transfer timed out!\n");
+                       return -ETIMEDOUT;
+               }
+
+               if (rx) {
+                       memcpy_fromio(rx, bs->fifo, curr_step);
+                       rx += curr_step;
+               }
+
+               pending -= curr_step;
+       }
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_setup(struct spi_device *spi)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+       u32 reg;
+
+       reg = __raw_readl(bs->regs +
+                         HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+       reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
+       if (spi->mode & SPI_CPHA)
+               reg |= SIGNAL_CTRL_LAUNCH_RISING;
+       else
+               reg |= SIGNAL_CTRL_LATCH_RISING;
+       __raw_writel(reg, bs->regs +
+                    HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       /* only change actual polarities if there is no transfer */
+       if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) {
+               if (spi->mode & SPI_CS_HIGH)
+                       reg |= BIT(spi->chip_select);
+               else
+                       reg &= ~BIT(spi->chip_select);
+               __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       }
+
+       if (spi->mode & SPI_CS_HIGH)
+               bs->cs_polarity |= BIT(spi->chip_select);
+       else
+               bs->cs_polarity &= ~BIT(spi->chip_select);
+
+       mutex_unlock(&bs->bus_mutex);
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
+                                     struct spi_message *msg)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+       struct spi_transfer *t;
+       struct spi_device *spi = msg->spi;
+       int status = -EINVAL;
+       int dummy_cs;
+       u32 reg;
+
+       /* This controller does not support keeping CS active during idle.
+        * To work around this, we use the following ugly hack:
+        *
+        * a. Invert the target chip select's polarity so it will be active.
+        * b. Select a "dummy" chip select to use as the hardware target.
+        * c. Invert the dummy chip select's polarity so it will be inactive
+        *    during the actual transfers.
+        * d. Tell the hardware to send to the dummy chip select. Thanks to
+        *    the multiplexed nature of SPI the actual target will receive
+        *    the transfer and we see its response.
+        *
+        * e. At the end restore the polarities again to their default values.
+        */
+
+       dummy_cs = !spi->chip_select;
+       bcm63xx_hsspi_set_cs(bs, dummy_cs, true);
+
+       list_for_each_entry(t, &msg->transfers, transfer_list) {
+               status = bcm63xx_hsspi_do_txrx(spi, t);
+               if (status)
+                       break;
+
+               msg->actual_length += t->len;
+
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+
+               if (t->cs_change)
+                       bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);
+       }
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       reg &= ~GLOBAL_CTRL_CS_POLARITY_MASK;
+       reg |= bs->cs_polarity;
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+
+       msg->status = status;
+       spi_finalize_current_message(master);
+
+       return 0;
+}
+
+static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
+{
+       struct bcm63xx_hsspi *bs = (struct bcm63xx_hsspi *)dev_id;
+
+       if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0)
+               return IRQ_NONE;
+
+       __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+
+       complete(&bs->done);
+
+       return IRQ_HANDLED;
+}
+
+static int bcm63xx_hsspi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct bcm63xx_hsspi *bs;
+       struct resource *res_mem;
+       void __iomem *regs;
+       struct device *dev = &pdev->dev;
+       struct clk *clk;
+       int irq, ret;
+       u32 reg, rate;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "no irq\n");
+               return -ENXIO;
+       }
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(dev, res_mem);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       clk = devm_clk_get(dev, "hsspi");
+
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       rate = clk_get_rate(clk);
+       if (!rate)
+               return -EINVAL;
+
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               return ret;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+       if (!master) {
+               ret = -ENOMEM;
+               goto out_disable_clk;
+       }
+
+       bs = spi_master_get_devdata(master);
+       bs->pdev = pdev;
+       bs->clk = clk;
+       bs->regs = regs;
+       bs->speed_hz = rate;
+       bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
+
+       mutex_init(&bs->bus_mutex);
+
+       master->bus_num = HSSPI_BUS_NUM;
+       master->num_chipselect = 8;
+       master->setup = bcm63xx_hsspi_setup;
+       master->transfer_one_message = bcm63xx_hsspi_transfer_one;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->auto_runtime_pm = true;
+
+       platform_set_drvdata(pdev, master);
+
+       /* Initialize the hardware */
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+
+       /* clean up any pending interrupts */
+       __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
+
+       /* read out default CS polarities */
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK;
+       __raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF,
+                    bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
+                              pdev->name, bs);
+
+       if (ret)
+               goto out_put_master;
+
+       /* register and we are done */
+       ret = devm_spi_register_master(dev, master);
+       if (ret)
+               goto out_put_master;
+
+       return 0;
+
+out_put_master:
+       spi_master_put(master);
+out_disable_clk:
+       clk_disable_unprepare(clk);
+       return ret;
+}
+
+
+static int bcm63xx_hsspi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       /* reset the hardware and block queue progress */
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+       clk_disable_unprepare(bs->clk);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bcm63xx_hsspi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       spi_master_suspend(master);
+       clk_disable_unprepare(bs->clk);
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+       int ret;
+
+       ret = clk_prepare_enable(bs->clk);
+       if (ret)
+               return ret;
+
+       spi_master_resume(master);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_hsspi_suspend, bcm63xx_hsspi_resume)
+};
+
+static struct platform_driver bcm63xx_hsspi_driver = {
+       .driver = {
+               .name   = "bcm63xx-hsspi",
+               .owner  = THIS_MODULE,
+               .pm     = &bcm63xx_hsspi_pm_ops,
+       },
+       .probe          = bcm63xx_hsspi_probe,
+       .remove         = bcm63xx_hsspi_remove,
+};
+
+module_platform_driver(bcm63xx_hsspi_driver);
+
+MODULE_ALIAS("platform:bcm63xx_hsspi");
+MODULE_DESCRIPTION("Broadcom BCM63xx High Speed SPI Controller driver");
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
+MODULE_LICENSE("GPL");
index 80d56b214eb51af96ceb9e9d55ffea6bbb2d7302..77286aef2adfc9e5495704405f4c76f45855b1a0 100644 (file)
@@ -169,8 +169,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
                               transfer_list);
        }
 
-       len -= prepend_len;
-
        init_completion(&bs->done);
 
        /* Fill in the Message control register */
@@ -205,13 +203,7 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
        if (!timeout)
                return -ETIMEDOUT;
 
-       /* read out all data */
-       rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
-
-       if (do_rx && rx_tail != len)
-               return -EIO;
-
-       if (!rx_tail)
+       if (!do_rx)
                return 0;
 
        len = 0;
@@ -345,22 +337,19 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "no irq\n");
-               ret = -ENXIO;
-               goto out;
+               return -ENXIO;
        }
 
-       clk = clk_get(dev, "spi");
+       clk = devm_clk_get(dev, "spi");
        if (IS_ERR(clk)) {
                dev_err(dev, "no clock for device\n");
-               ret = PTR_ERR(clk);
-               goto out;
+               return PTR_ERR(clk);
        }
 
        master = spi_alloc_master(dev, sizeof(*bs));
        if (!master) {
                dev_err(dev, "out of memory\n");
-               ret = -ENOMEM;
-               goto out_clk;
+               return -ENOMEM;
        }
 
        bs = spi_master_get_devdata(master);
@@ -408,7 +397,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        }
 
        /* Initialize hardware */
-       clk_prepare_enable(bs->clk);
+       ret = clk_prepare_enable(bs->clk);
+       if (ret)
+               goto out_err;
+
        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
 
        /* register and we are done */
@@ -427,15 +419,12 @@ out_clk_disable:
        clk_disable_unprepare(clk);
 out_err:
        spi_master_put(master);
-out_clk:
-       clk_put(clk);
-out:
        return ret;
 }
 
 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 */
@@ -443,12 +432,11 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
 
        /* HW shutdown */
        clk_disable_unprepare(bs->clk);
-       clk_put(bs->clk);
 
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int bcm63xx_spi_suspend(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
@@ -465,29 +453,27 @@ static int bcm63xx_spi_resume(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+       int ret;
 
-       clk_prepare_enable(bs->clk);
+       ret = clk_prepare_enable(bs->clk);
+       if (ret)
+               return ret;
 
        spi_master_resume(master);
 
        return 0;
 }
+#endif
 
 static const struct dev_pm_ops bcm63xx_spi_pm_ops = {
-       .suspend        = bcm63xx_spi_suspend,
-       .resume         = bcm63xx_spi_resume,
+       SET_SYSTEM_SLEEP_PM_OPS(bcm63xx_spi_suspend, bcm63xx_spi_resume)
 };
 
-#define BCM63XX_SPI_PM_OPS     (&bcm63xx_spi_pm_ops)
-#else
-#define BCM63XX_SPI_PM_OPS     NULL
-#endif
-
 static struct platform_driver bcm63xx_spi_driver = {
        .driver = {
                .name   = "bcm63xx-spi",
                .owner  = THIS_MODULE,
-               .pm     = BCM63XX_SPI_PM_OPS,
+               .pm     = &bcm63xx_spi_pm_ops,
        },
        .probe          = bcm63xx_spi_probe,
        .remove         = bcm63xx_spi_remove,
index c16bf853c3eb3f3a0c7ab3c3c8731cc179d30a15..c616e41521be18589ec89ab68dcfeec9cd477da7 100644 (file)
@@ -38,7 +38,7 @@
  *
  * Since this is software, the timings may not be exactly what your board's
  * chips need ... there may be several reasons you'd need to tweak timings
- * in these routines, not just make to make it faster or slower to match a
+ * in these routines, not just to make it faster or slower to match a
  * particular CPU clock rate.
  */
 
index 6f03d7e6435d82d367d568bd478af2aed9394a98..374ba4a48a9e1450dba5c46c062c71a3de6f00df 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CLPS711X SPI bus driver
  *
- *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -198,7 +198,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
                        ret = -EINVAL;
                        goto err_out;
                }
-               if (gpio_request(hw->chipselect[i], DRIVER_NAME)) {
+               if (devm_gpio_request(&pdev->dev, hw->chipselect[i], NULL)) {
                        dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
                        ret = -EINVAL;
                        goto err_out;
@@ -240,38 +240,21 @@ static int spi_clps711x_probe(struct platform_device *pdev)
        dev_err(&pdev->dev, "Failed to register master\n");
 
 err_out:
-       while (--i >= 0)
-               if (gpio_is_valid(hw->chipselect[i]))
-                       gpio_free(hw->chipselect[i]);
-
        spi_master_put(master);
 
        return ret;
 }
 
-static int spi_clps711x_remove(struct platform_device *pdev)
-{
-       int i;
-       struct spi_master *master = platform_get_drvdata(pdev);
-       struct spi_clps711x_data *hw = spi_master_get_devdata(master);
-
-       for (i = 0; i < master->num_chipselect; i++)
-               if (gpio_is_valid(hw->chipselect[i]))
-                       gpio_free(hw->chipselect[i]);
-
-       return 0;
-}
-
 static struct platform_driver clps711x_spi_driver = {
        .driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
        },
        .probe  = spi_clps711x_probe,
-       .remove = spi_clps711x_remove,
 };
 module_platform_driver(clps711x_spi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
 MODULE_DESCRIPTION("CLPS711X SPI bus driver");
+MODULE_ALIAS("platform:" DRIVER_NAME);
index cc5b75d10c386145dad24ac595c5495e4b7564f0..cabed8f9119e1af30d80766420d548b94567c91c 100644 (file)
@@ -397,44 +397,31 @@ static int mcfqspi_probe(struct platform_device *pdev)
        mcfqspi = spi_master_get_devdata(master);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_dbg(&pdev->dev, "platform_get_resource failed\n");
-               status = -ENXIO;
+       mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mcfqspi->iobase)) {
+               status = PTR_ERR(mcfqspi->iobase);
                goto fail0;
        }
 
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               dev_dbg(&pdev->dev, "request_mem_region failed\n");
-               status = -EBUSY;
-               goto fail0;
-       }
-
-       mcfqspi->iobase = ioremap(res->start, resource_size(res));
-       if (!mcfqspi->iobase) {
-               dev_dbg(&pdev->dev, "ioremap failed\n");
-               status = -ENOMEM;
-               goto fail1;
-       }
-
        mcfqspi->irq = platform_get_irq(pdev, 0);
        if (mcfqspi->irq < 0) {
                dev_dbg(&pdev->dev, "platform_get_irq failed\n");
                status = -ENXIO;
-               goto fail2;
+               goto fail0;
        }
 
-       status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
-                            pdev->name, mcfqspi);
+       status = devm_request_irq(&pdev->dev, mcfqspi->irq, mcfqspi_irq_handler,
+                               0, pdev->name, mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "request_irq failed\n");
-               goto fail2;
+               goto fail0;
        }
 
-       mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
+       mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk");
        if (IS_ERR(mcfqspi->clk)) {
                dev_dbg(&pdev->dev, "clk_get failed\n");
                status = PTR_ERR(mcfqspi->clk);
-               goto fail3;
+               goto fail0;
        }
        clk_enable(mcfqspi->clk);
 
@@ -445,7 +432,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
        status = mcfqspi_cs_setup(mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "error initializing cs_control\n");
-               goto fail4;
+               goto fail1;
        }
 
        init_waitqueue_head(&mcfqspi->waitq);
@@ -459,10 +446,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, master);
 
-       status = spi_register_master(master);
+       status = devm_spi_register_master(&pdev->dev, master);
        if (status) {
                dev_dbg(&pdev->dev, "spi_register_master failed\n");
-               goto fail5;
+               goto fail2;
        }
        pm_runtime_enable(mcfqspi->dev);
 
@@ -470,17 +457,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
 
        return 0;
 
-fail5:
-       mcfqspi_cs_teardown(mcfqspi);
-fail4:
-       clk_disable(mcfqspi->clk);
-       clk_put(mcfqspi->clk);
-fail3:
-       free_irq(mcfqspi->irq, mcfqspi);
 fail2:
-       iounmap(mcfqspi->iobase);
+       mcfqspi_cs_teardown(mcfqspi);
 fail1:
-       release_mem_region(res->start, resource_size(res));
+       clk_disable(mcfqspi->clk);
 fail0:
        spi_master_put(master);
 
@@ -501,11 +481,6 @@ static int mcfqspi_remove(struct platform_device *pdev)
 
        mcfqspi_cs_teardown(mcfqspi);
        clk_disable(mcfqspi->clk);
-       clk_put(mcfqspi->clk);
-       free_irq(mcfqspi->irq, mcfqspi);
-       iounmap(mcfqspi->iobase);
-       release_mem_region(res->start, resource_size(res));
-       spi_unregister_master(master);
 
        return 0;
 }
index 50b2d88c81901c2b0b0ec1720f7e802ccf4924fb..5e7389faa2a0189472d71fedcba95ae8ecd1cf35 100644 (file)
@@ -396,10 +396,6 @@ static int davinci_spi_setup(struct spi_device *spi)
        dspi = spi_master_get_devdata(spi->master);
        pdata = &dspi->pdata;
 
-       /* if bits per word length is zero then set it default 8 */
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        if (!(spi->mode & SPI_NO_CS)) {
                if ((pdata->chip_sel == NULL) ||
                    (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
@@ -853,7 +849,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct davinci_spi *dspi;
        struct davinci_spi_platform_data *pdata;
-       struct resource *r, *mem;
+       struct resource *r;
        resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
        resource_size_t dma_tx_chan = SPI_NO_RESOURCE;
        int i = 0, ret = 0;
@@ -894,39 +890,33 @@ static int davinci_spi_probe(struct platform_device *pdev)
 
        dspi->pbase = r->start;
 
-       mem = request_mem_region(r->start, resource_size(r), pdev->name);
-       if (mem == NULL) {
-               ret = -EBUSY;
+       dspi->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(dspi->base)) {
+               ret = PTR_ERR(dspi->base);
                goto free_master;
        }
 
-       dspi->base = ioremap(r->start, resource_size(r));
-       if (dspi->base == NULL) {
-               ret = -ENOMEM;
-               goto release_region;
-       }
-
        dspi->irq = platform_get_irq(pdev, 0);
        if (dspi->irq <= 0) {
                ret = -EINVAL;
-               goto unmap_io;
+               goto free_master;
        }
 
-       ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn,
-                                0, dev_name(&pdev->dev), dspi);
+       ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq,
+                               dummy_thread_fn, 0, dev_name(&pdev->dev), dspi);
        if (ret)
-               goto unmap_io;
+               goto free_master;
 
        dspi->bitbang.master = master;
        if (dspi->bitbang.master == NULL) {
                ret = -ENODEV;
-               goto irq_free;
+               goto free_master;
        }
 
-       dspi->clk = clk_get(&pdev->dev, NULL);
+       dspi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dspi->clk)) {
                ret = -ENODEV;
-               goto irq_free;
+               goto free_master;
        }
        clk_prepare_enable(dspi->clk);
 
@@ -963,8 +953,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
                        goto free_clk;
 
                dev_info(&pdev->dev, "DMA: supported\n");
-               dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
-                               "event queue: %d\n", dma_rx_chan, dma_tx_chan,
+               dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, "
+                               "event queue: %d\n", &dma_rx_chan, &dma_tx_chan,
                                pdata->dma_event_q);
        }
 
@@ -1015,13 +1005,6 @@ free_dma:
        dma_release_channel(dspi->dma_tx);
 free_clk:
        clk_disable_unprepare(dspi->clk);
-       clk_put(dspi->clk);
-irq_free:
-       free_irq(dspi->irq, dspi);
-unmap_io:
-       iounmap(dspi->base);
-release_region:
-       release_mem_region(dspi->pbase, resource_size(r));
 free_master:
        spi_master_put(master);
 err:
@@ -1041,7 +1024,6 @@ static int davinci_spi_remove(struct platform_device *pdev)
 {
        struct davinci_spi *dspi;
        struct spi_master *master;
-       struct resource *r;
 
        master = platform_get_drvdata(pdev);
        dspi = spi_master_get_devdata(master);
@@ -1049,11 +1031,6 @@ static int davinci_spi_remove(struct platform_device *pdev)
        spi_bitbang_stop(&dspi->bitbang);
 
        clk_disable_unprepare(dspi->clk);
-       clk_put(dspi->clk);
-       free_irq(dspi->irq, dspi);
-       iounmap(dspi->base);
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(dspi->pbase, resource_size(r));
        spi_master_put(master);
 
        return 0;
index 168c620947f4b515bd3307fc84a9dcd3f06073f7..9af56cdf1540551d595409efc47533cf45c5e5c5 100644 (file)
@@ -30,14 +30,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
        struct dw_spi_mmio *dwsmmio;
        struct dw_spi *dws;
-       struct resource *mem, *ioarea;
+       struct resource *mem;
        int ret;
 
-       dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
-       if (!dwsmmio) {
-               ret = -ENOMEM;
-               goto err_end;
-       }
+       dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio),
+                       GFP_KERNEL);
+       if (!dwsmmio)
+               return -ENOMEM;
 
        dws = &dwsmmio->dws;
 
@@ -45,80 +44,51 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
                dev_err(&pdev->dev, "no mem resource?\n");
-               ret = -EINVAL;
-               goto err_kfree;
+               return -EINVAL;
        }
 
-       ioarea = request_mem_region(mem->start, resource_size(mem),
-                       pdev->name);
-       if (!ioarea) {
-               dev_err(&pdev->dev, "SPI region already claimed\n");
-               ret = -EBUSY;
-               goto err_kfree;
-       }
-
-       dws->regs = ioremap_nocache(mem->start, resource_size(mem));
-       if (!dws->regs) {
-               dev_err(&pdev->dev, "SPI region already mapped\n");
-               ret = -ENOMEM;
-               goto err_release_reg;
+       dws->regs = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(dws->regs)) {
+               dev_err(&pdev->dev, "SPI region map failed\n");
+               return PTR_ERR(dws->regs);
        }
 
        dws->irq = platform_get_irq(pdev, 0);
        if (dws->irq < 0) {
                dev_err(&pdev->dev, "no irq resource?\n");
-               ret = dws->irq; /* -ENXIO */
-               goto err_unmap;
+               return dws->irq; /* -ENXIO */
        }
 
-       dwsmmio->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(dwsmmio->clk)) {
-               ret = PTR_ERR(dwsmmio->clk);
-               goto err_unmap;
-       }
-       clk_enable(dwsmmio->clk);
+       dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dwsmmio->clk))
+               return PTR_ERR(dwsmmio->clk);
+       ret = clk_prepare_enable(dwsmmio->clk);
+       if (ret)
+               return ret;
 
-       dws->parent_dev = &pdev->dev;
        dws->bus_num = 0;
        dws->num_cs = 4;
        dws->max_freq = clk_get_rate(dwsmmio->clk);
 
-       ret = dw_spi_add_host(dws);
+       ret = dw_spi_add_host(&pdev->dev, dws);
        if (ret)
-               goto err_clk;
+               goto out;
 
        platform_set_drvdata(pdev, dwsmmio);
        return 0;
 
-err_clk:
-       clk_disable(dwsmmio->clk);
-       clk_put(dwsmmio->clk);
-       dwsmmio->clk = NULL;
-err_unmap:
-       iounmap(dws->regs);
-err_release_reg:
-       release_mem_region(mem->start, resource_size(mem));
-err_kfree:
-       kfree(dwsmmio);
-err_end:
+out:
+       clk_disable_unprepare(dwsmmio->clk);
        return ret;
 }
 
 static int dw_spi_mmio_remove(struct platform_device *pdev)
 {
        struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
-       struct resource *mem;
-
-       clk_disable(dwsmmio->clk);
-       clk_put(dwsmmio->clk);
-       dwsmmio->clk = NULL;
 
+       clk_disable_unprepare(dwsmmio->clk);
        dw_spi_remove_host(&dwsmmio->dws);
-       iounmap(dwsmmio->dws.regs);
-       kfree(dwsmmio);
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
index 66fa9955ea148e5c10c3cfda9b3b90da65902ef0..3f3dc1226edf19aefad97630e2112287f419cabc 100644 (file)
@@ -43,35 +43,25 @@ static int spi_pci_probe(struct pci_dev *pdev,
        dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
                pdev->vendor, pdev->device);
 
-       ret = pci_enable_device(pdev);
+       ret = pcim_enable_device(pdev);
        if (ret)
                return ret;
 
-       dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
-       if (!dwpci) {
-               ret = -ENOMEM;
-               goto err_disable;
-       }
+       dwpci = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_pci),
+                       GFP_KERNEL);
+       if (!dwpci)
+               return -ENOMEM;
 
        dwpci->pdev = pdev;
        dws = &dwpci->dws;
 
        /* Get basic io resource and map it */
        dws->paddr = pci_resource_start(pdev, pci_bar);
-       dws->iolen = pci_resource_len(pdev, pci_bar);
 
-       ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
+       ret = pcim_iomap_regions(pdev, 1, dev_name(&pdev->dev));
        if (ret)
-               goto err_kfree;
-
-       dws->regs = ioremap_nocache((unsigned long)dws->paddr,
-                               pci_resource_len(pdev, pci_bar));
-       if (!dws->regs) {
-               ret = -ENOMEM;
-               goto err_release_reg;
-       }
+               return ret;
 
-       dws->parent_dev = &pdev->dev;
        dws->bus_num = 0;
        dws->num_cs = 4;
        dws->irq = pdev->irq;
@@ -83,26 +73,17 @@ static int spi_pci_probe(struct pci_dev *pdev,
        if (pdev->device == 0x0800) {
                ret = dw_spi_mid_init(dws);
                if (ret)
-                       goto err_unmap;
+                       return ret;
        }
 
-       ret = dw_spi_add_host(dws);
+       ret = dw_spi_add_host(&pdev->dev, dws);
        if (ret)
-               goto err_unmap;
+               return ret;
 
        /* PCI hook and SPI hook use the same drv data */
        pci_set_drvdata(pdev, dwpci);
-       return 0;
 
-err_unmap:
-       iounmap(dws->regs);
-err_release_reg:
-       pci_release_region(pdev, pci_bar);
-err_kfree:
-       kfree(dwpci);
-err_disable:
-       pci_disable_device(pdev);
-       return ret;
+       return 0;
 }
 
 static void spi_pci_remove(struct pci_dev *pdev)
@@ -110,10 +91,6 @@ static void spi_pci_remove(struct pci_dev *pdev)
        struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
 
        dw_spi_remove_host(&dwpci->dws);
-       iounmap(dwpci->dws.regs);
-       pci_release_region(pdev, 0);
-       kfree(dwpci);
-       pci_disable_device(pdev);
 }
 
 #ifdef CONFIG_PM
@@ -148,7 +125,7 @@ static int spi_resume(struct pci_dev *pdev)
 #define spi_resume     NULL
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
+static const struct pci_device_id pci_ids[] = {
        /* Intel MID platform SPI controller 0 */
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
        {},
index b897c4adb39deda5f7e293d86216e74458ce912d..bf98d63d92b3eabbd80ea49d125421069139c535 100644 (file)
@@ -427,7 +427,6 @@ static void pump_transfers(unsigned long data)
        dws->tx_end = dws->tx + transfer->len;
        dws->rx = transfer->rx_buf;
        dws->rx_end = dws->rx + transfer->len;
-       dws->cs_change = transfer->cs_change;
        dws->len = dws->cur_transfer->len;
        if (chip != dws->prev_chip)
                cs_change = 1;
@@ -620,9 +619,11 @@ static int dw_spi_setup(struct spi_device *spi)
        /* Only alloc on first setup */
        chip = spi_get_ctldata(spi);
        if (!chip) {
-               chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+               chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data),
+                               GFP_KERNEL);
                if (!chip)
                        return -ENOMEM;
+               spi_set_ctldata(spi, chip);
        }
 
        /*
@@ -667,7 +668,6 @@ static int dw_spi_setup(struct spi_device *spi)
                        | (spi->mode  << SPI_MODE_OFFSET)
                        | (chip->tmode << SPI_TMOD_OFFSET);
 
-       spi_set_ctldata(spi, chip);
        return 0;
 }
 
@@ -776,18 +776,16 @@ static void spi_hw_init(struct dw_spi *dws)
        }
 }
 
-int dw_spi_add_host(struct dw_spi *dws)
+int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 {
        struct spi_master *master;
        int ret;
 
        BUG_ON(dws == NULL);
 
-       master = spi_alloc_master(dws->parent_dev, 0);
-       if (!master) {
-               ret = -ENOMEM;
-               goto exit;
-       }
+       master = spi_alloc_master(dev, 0);
+       if (!master)
+               return -ENOMEM;
 
        dws->master = master;
        dws->type = SSI_MOTO_SPI;
@@ -797,7 +795,7 @@ int dw_spi_add_host(struct dw_spi *dws)
        snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
                        dws->bus_num);
 
-       ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
+       ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
                        dws->name, dws);
        if (ret < 0) {
                dev_err(&master->dev, "can not get IRQ\n");
@@ -836,7 +834,7 @@ int dw_spi_add_host(struct dw_spi *dws)
        }
 
        spi_master_set_devdata(master, dws);
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(dev, master);
        if (ret) {
                dev_err(&master->dev, "problem registering spi master\n");
                goto err_queue_alloc;
@@ -851,10 +849,8 @@ err_queue_alloc:
                dws->dma_ops->dma_exit(dws);
 err_diable_hw:
        spi_enable_chip(dws, 0);
-       free_irq(dws->irq, dws);
 err_free_master:
        spi_master_put(master);
-exit:
        return ret;
 }
 EXPORT_SYMBOL_GPL(dw_spi_add_host);
@@ -878,10 +874,6 @@ void dw_spi_remove_host(struct dw_spi *dws)
        spi_enable_chip(dws, 0);
        /* Disable clk */
        spi_set_clk(dws, 0);
-       free_irq(dws->irq, dws);
-
-       /* Disconnect from the SPI framework */
-       spi_unregister_master(dws->master);
 }
 EXPORT_SYMBOL_GPL(dw_spi_remove_host);
 
index 9c57c078031ead4ad4e2af02fb4b35c7b7d8b249..587643dae11e8b1a66c319d977c0047768bbad45 100644 (file)
@@ -92,13 +92,11 @@ struct dw_spi_dma_ops {
 struct dw_spi {
        struct spi_master       *master;
        struct spi_device       *cur_dev;
-       struct device           *parent_dev;
        enum dw_ssi_type        type;
        char                    name[16];
 
        void __iomem            *regs;
        unsigned long           paddr;
-       u32                     iolen;
        int                     irq;
        u32                     fifo_len;       /* depth of the FIFO buffer */
        u32                     max_freq;       /* max bus freq supported */
@@ -135,7 +133,6 @@ struct dw_spi {
        u8                      n_bytes;        /* current is a 1/2 bytes op */
        u8                      max_bits_per_word;      /* maxim is 16b */
        u32                     dma_width;
-       int                     cs_change;
        irqreturn_t             (*transfer_handler)(struct dw_spi *dws);
        void                    (*cs_control)(u32 command);
 
@@ -231,7 +228,7 @@ struct dw_spi_chip {
        void (*cs_control)(u32 command);
 };
 
-extern int dw_spi_add_host(struct dw_spi *dws);
+extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
 extern void dw_spi_remove_host(struct dw_spi *dws);
 extern int dw_spi_suspend_host(struct dw_spi *dws);
 extern int dw_spi_resume_host(struct dw_spi *dws);
index c7a74f0ef89285eb2f14926dd979145987509dc6..dd5bd468e9621698c7a130418d5a74994c474cbe 100644 (file)
@@ -433,21 +433,12 @@ static int falcon_sflash_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret)
                spi_master_put(master);
        return ret;
 }
 
-static int falcon_sflash_remove(struct platform_device *pdev)
-{
-       struct falcon_sflash *priv = platform_get_drvdata(pdev);
-
-       spi_unregister_master(priv->master);
-
-       return 0;
-}
-
 static const struct of_device_id falcon_sflash_match[] = {
        { .compatible = "lantiq,sflash-falcon" },
        {},
@@ -456,7 +447,6 @@ MODULE_DEVICE_TABLE(of, falcon_sflash_match);
 
 static struct platform_driver falcon_sflash_driver = {
        .probe  = falcon_sflash_probe,
-       .remove = falcon_sflash_remove,
        .driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 8641b03bdd7a26f6057914a05e2095c4a9d22d0c..ec79f726672a14f7644810101afe59e82322976c 100644 (file)
@@ -320,8 +320,10 @@ static void dspi_chipselect(struct spi_device *spi, int value)
        switch (value) {
        case BITBANG_CS_ACTIVE:
                pushr |= SPI_PUSHR_CONT;
+               break;
        case BITBANG_CS_INACTIVE:
                pushr &= ~SPI_PUSHR_CONT;
+               break;
        }
 
        writel(pushr, dspi->base + SPI_PUSHR);
@@ -373,9 +375,6 @@ static int dspi_setup(struct spi_device *spi)
        if (!spi->max_speed_hz)
                return -EINVAL;
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        return dspi_setup_transfer(spi, NULL);
 }
 
index 80d8f40f7e0553d600f1e36b018daa7fae275a64..428dc7a6b62e7c173fb9a1dd8b9028ab9ded01b3 100644 (file)
@@ -705,7 +705,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
                goto err;
 
        irq = irq_of_parse_and_map(np, 0);
-       if (!ret) {
+       if (!irq) {
                ret = -EINVAL;
                goto err;
        }
@@ -727,6 +727,66 @@ static int of_fsl_espi_remove(struct platform_device *dev)
        return mpc8xxx_spi_remove(&dev->dev);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int of_fsl_espi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_espi_reg *reg_base;
+       u32 regval;
+       int ret;
+
+       mpc8xxx_spi = spi_master_get_devdata(master);
+       reg_base = mpc8xxx_spi->reg_base;
+
+       ret = spi_master_suspend(master);
+       if (ret) {
+               dev_warn(dev, "cannot suspend master\n");
+               return ret;
+       }
+
+       regval = mpc8xxx_spi_read_reg(&reg_base->mode);
+       regval &= ~SPMODE_ENABLE;
+       mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+       return 0;
+}
+
+static int of_fsl_espi_resume(struct device *dev)
+{
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mpc8xxx_spi *mpc8xxx_spi;
+       struct fsl_espi_reg *reg_base;
+       u32 regval;
+       int i;
+
+       mpc8xxx_spi = spi_master_get_devdata(master);
+       reg_base = mpc8xxx_spi->reg_base;
+
+       /* SPI controller initializations */
+       mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+       mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+       mpc8xxx_spi_write_reg(&reg_base->command, 0);
+       mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+       /* Init eSPI CS mode register */
+       for (i = 0; i < pdata->max_chipselect; i++)
+               mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+       /* Enable SPI interface */
+       regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+       mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+       return spi_master_resume(master);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops espi_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
+};
+
 static const struct of_device_id of_fsl_espi_match[] = {
        { .compatible = "fsl,mpc8536-espi" },
        {}
@@ -738,6 +798,7 @@ static struct platform_driver fsl_espi_driver = {
                .name = "fsl_espi",
                .owner = THIS_MODULE,
                .of_match_table = of_fsl_espi_match,
+               .pm = &espi_pm,
        },
        .probe          = of_fsl_espi_probe,
        .remove         = of_fsl_espi_remove,
index 3fb09f981980aedb23a760dd0b14d604c843661b..7beeb29472ac73f59fcf0e92e04c9c31ef88a75a 100644 (file)
@@ -115,17 +115,17 @@ spi_to_pdata(const struct spi_device *spi)
 
 static inline void setsck(const struct spi_device *spi, int is_on)
 {
-       gpio_set_value(SPI_SCK_GPIO, is_on);
+       gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
 }
 
 static inline void setmosi(const struct spi_device *spi, int is_on)
 {
-       gpio_set_value(SPI_MOSI_GPIO, is_on);
+       gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
 }
 
 static inline int getmiso(const struct spi_device *spi)
 {
-       return !!gpio_get_value(SPI_MISO_GPIO);
+       return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
 }
 
 #undef pdata
@@ -229,7 +229,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
 
        if (cs != SPI_GPIO_NO_CHIPSELECT) {
                /* SPI is normally active-low */
-               gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+               gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
        }
 }
 
index b80f2f70fef7c22174df30a97c311f2aa9693e5c..a5474ef9d2a0cf4ad7367ee1e0399fae2e982145 100644 (file)
@@ -206,7 +206,8 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 #define MX51_ECSPI_STAT_RR             (1 <<  3)
 
 /* MX51 eCSPI */
-static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
+static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
+                                     unsigned int *fres)
 {
        /*
         * there are two 4-bit dividers, the pre-divider divides by
@@ -234,6 +235,10 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
 
        pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
                        __func__, fin, fspi, post, pre);
+
+       /* Resulting frequency for the SCLK line. */
+       *fres = (fin / (pre + 1)) >> post;
+
        return (pre << MX51_ECSPI_CTRL_PREDIV_OFFSET) |
                (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET);
 }
@@ -264,6 +269,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
                struct spi_imx_config *config)
 {
        u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
+       u32 clk = config->speed_hz, delay;
 
        /*
         * The hardware seems to have a race condition when changing modes. The
@@ -275,7 +281,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
        /* set clock speed */
-       ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz);
+       ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk);
 
        /* set chip select to use */
        ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -297,6 +303,23 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
        writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
+       /*
+        * Wait until the changes in the configuration register CONFIGREG
+        * propagate into the hardware. It takes exactly one tick of the
+        * SCLK clock, but we will wait two SCLK clock just to be sure. The
+        * effect of the delay it takes for the hardware to apply changes
+        * is noticable if the SCLK clock run very slow. In such a case, if
+        * the polarity of SCLK should be inverted, the GPIO ChipSelect might
+        * be asserted before the SCLK polarity changes, which would disrupt
+        * the SPI communication as the device on the other end would consider
+        * the change of SCLK polarity as a clock tick already.
+        */
+       delay = (2 * 1000000) / clk;
+       if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
+               udelay(delay);
+       else                    /* SCLK is _very_ slow */
+               usleep_range(delay, delay + 10);
+
        return 0;
 }
 
index 9602bbd8d7eac061fffb5543704fc9d68a48f135..46d2313f7c6fc1e155ff15c7f60962291c923524 100644 (file)
@@ -504,7 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        master->cleanup = mpc512x_psc_spi_cleanup;
        master->dev.of_node = dev->of_node;
 
-       tempp = ioremap(regaddr, size);
+       tempp = devm_ioremap(dev, regaddr, size);
        if (!tempp) {
                dev_err(dev, "could not ioremap I/O port range\n");
                ret = -EFAULT;
@@ -513,9 +513,8 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        mps->psc = tempp;
        mps->fifo =
                (struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
-
-       ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
-                         "mpc512x-psc-spi", mps);
+       ret = devm_request_irq(dev, mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
+                               "mpc512x-psc-spi", mps);
        if (ret)
                goto free_master;
        init_completion(&mps->txisrdone);
@@ -525,11 +524,11 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        clk = devm_clk_get(dev, clk_name);
        if (IS_ERR(clk)) {
                ret = PTR_ERR(clk);
-               goto free_irq;
+               goto free_master;
        }
        ret = clk_prepare_enable(clk);
        if (ret)
-               goto free_irq;
+               goto free_master;
        mps->clk_mclk = clk;
        mps->mclk_rate = clk_get_rate(clk);
 
@@ -545,11 +544,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 
 free_clock:
        clk_disable_unprepare(mps->clk_mclk);
-free_irq:
-       free_irq(mps->irq, mps);
 free_master:
-       if (mps->psc)
-               iounmap(mps->psc);
        spi_master_put(master);
 
        return ret;
@@ -557,13 +552,10 @@ 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);
-       free_irq(mps->irq, mps);
-       if (mps->psc)
-               iounmap(mps->psc);
 
        return 0;
 }
index 73afb56c08cc26826d468ad4aaacdce3a7e7043f..79e5aa2250c89d48541d8d9eb263410c2aa66ac6 100644 (file)
@@ -111,14 +111,6 @@ static int mxs_spi_setup_transfer(struct spi_device *dev,
        return 0;
 }
 
-static int mxs_spi_setup(struct spi_device *dev)
-{
-       if (!dev->bits_per_word)
-               dev->bits_per_word = 8;
-
-       return 0;
-}
-
 static u32 mxs_spi_cs_to_reg(unsigned cs)
 {
        u32 select = 0;
@@ -502,7 +494,6 @@ static int mxs_spi_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        master->transfer_one_message = mxs_spi_transfer_one;
-       master->setup = mxs_spi_setup;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->mode_bits = SPI_CPOL | SPI_CPHA;
        master->num_chipselect = 3;
@@ -565,7 +556,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 e0c32bc69ee2553d137e28d0ea2c70cdd58a2050..50406306bc209493152eca0a5b636811e30593d6 100644 (file)
@@ -57,7 +57,6 @@ struct nuc900_spi {
        const unsigned char     *tx;
        unsigned char           *rx;
        struct clk              *clk;
-       struct resource         *ioarea;
        struct spi_master       *master;
        struct spi_device       *curdev;
        struct device           *dev;
@@ -344,8 +343,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi));
        if (master == NULL) {
                dev_err(&pdev->dev, "No memory for spi_master\n");
-               err = -ENOMEM;
-               goto err_nomem;
+               return -ENOMEM;
        }
 
        hw = spi_master_get_devdata(master);
@@ -370,46 +368,31 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        hw->bitbang.txrx_bufs      = nuc900_spi_txrx;
 
        hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (hw->res == NULL) {
-               dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
-               err = -ENOENT;
-               goto err_pdata;
-       }
-
-       hw->ioarea = request_mem_region(hw->res->start,
-                                       resource_size(hw->res), pdev->name);
-
-       if (hw->ioarea == NULL) {
-               dev_err(&pdev->dev, "Cannot reserve region\n");
-               err = -ENXIO;
+       hw->regs = devm_ioremap_resource(&pdev->dev, hw->res);
+       if (IS_ERR(hw->regs)) {
+               err = PTR_ERR(hw->regs);
                goto err_pdata;
        }
 
-       hw->regs = ioremap(hw->res->start, resource_size(hw->res));
-       if (hw->regs == NULL) {
-               dev_err(&pdev->dev, "Cannot map IO\n");
-               err = -ENXIO;
-               goto err_iomap;
-       }
-
        hw->irq = platform_get_irq(pdev, 0);
        if (hw->irq < 0) {
                dev_err(&pdev->dev, "No IRQ specified\n");
                err = -ENOENT;
-               goto err_irq;
+               goto err_pdata;
        }
 
-       err = request_irq(hw->irq, nuc900_spi_irq, 0, pdev->name, hw);
+       err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0,
+                               pdev->name, hw);
        if (err) {
                dev_err(&pdev->dev, "Cannot claim IRQ\n");
-               goto err_irq;
+               goto err_pdata;
        }
 
-       hw->clk = clk_get(&pdev->dev, "spi");
+       hw->clk = devm_clk_get(&pdev->dev, "spi");
        if (IS_ERR(hw->clk)) {
                dev_err(&pdev->dev, "No clock for device\n");
                err = PTR_ERR(hw->clk);
-               goto err_clk;
+               goto err_pdata;
        }
 
        mfp_set_groupg(&pdev->dev, NULL);
@@ -425,17 +408,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 
 err_register:
        clk_disable(hw->clk);
-       clk_put(hw->clk);
-err_clk:
-       free_irq(hw->irq, hw);
-err_irq:
-       iounmap(hw->regs);
-err_iomap:
-       release_mem_region(hw->res->start, resource_size(hw->res));
-       kfree(hw->ioarea);
 err_pdata:
        spi_master_put(hw->master);
-err_nomem:
        return err;
 }
 
@@ -443,18 +417,8 @@ static int nuc900_spi_remove(struct platform_device *dev)
 {
        struct nuc900_spi *hw = platform_get_drvdata(dev);
 
-       free_irq(hw->irq, hw);
-
        spi_bitbang_stop(&hw->bitbang);
-
        clk_disable(hw->clk);
-       clk_put(hw->clk);
-
-       iounmap(hw->regs);
-
-       release_mem_region(hw->res->start, resource_size(hw->res));
-       kfree(hw->ioarea);
-
        spi_master_put(hw->master);
        return 0;
 }
index 91c66859620232a024827df02f846c0a6f08798d..f7c896e2981ef684d339f8e97f2b021ff468c35d 100644 (file)
@@ -153,62 +153,22 @@ static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
                }
 
                wait_for_completion(&hw->done);
-       } else if (txp && rxp) {
-               /* we need to tighten the transfer loop */
-               writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
-                               u8 rx, tx = *txp++;
-                               tiny_spi_wait_txr(hw);
-                               rx = readb(hw->base + TINY_SPI_TXDATA);
-                               writeb(tx, hw->base + TINY_SPI_TXDATA);
-                               *rxp++ = rx;
-                       }
-                       tiny_spi_wait_txr(hw);
-                       *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-               }
-               tiny_spi_wait_txe(hw);
-               *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-       } else if (rxp) {
-               writeb(0, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(0,
-                              hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
-                               u8 rx;
-                               tiny_spi_wait_txr(hw);
-                               rx = readb(hw->base + TINY_SPI_TXDATA);
-                               writeb(0, hw->base + TINY_SPI_TXDATA);
-                               *rxp++ = rx;
-                       }
-                       tiny_spi_wait_txr(hw);
-                       *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
-               }
-               tiny_spi_wait_txe(hw);
-               *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
-       } else if (txp) {
-               writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(*txp++, hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
-                               u8 tx = *txp++;
-                               tiny_spi_wait_txr(hw);
-                               writeb(tx, hw->base + TINY_SPI_TXDATA);
-                       }
-               }
-               tiny_spi_wait_txe(hw);
        } else {
-               writeb(0, hw->base + TINY_SPI_TXDATA);
-               if (t->len > 1) {
-                       writeb(0, hw->base + TINY_SPI_TXDATA);
-                       for (i = 2; i < t->len; i++) {
+               /* we need to tighten the transfer loop */
+               writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
+               for (i = 1; i < t->len; i++) {
+                       writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA);
+
+                       if (rxp || (i != t->len - 1))
                                tiny_spi_wait_txr(hw);
-                               writeb(0, hw->base + TINY_SPI_TXDATA);
-                       }
+                       if (rxp)
+                               *rxp++ = readb(hw->base + TINY_SPI_TXDATA);
                }
                tiny_spi_wait_txe(hw);
+               if (rxp)
+                       *rxp++ = readb(hw->base + TINY_SPI_RXDATA);
        }
+
        return t->len;
 }
 
index b6ed82beb01dc651d687f374ce5536ce289d440c..0d32054bfc0dd624c1d99ec37f47f6c8244b3ab2 100644 (file)
@@ -470,31 +470,12 @@ err:
        return status;
 }
 
-static int omap1_spi100k_remove(struct platform_device *pdev)
-{
-       struct spi_master       *master;
-       struct omap1_spi100k    *spi100k;
-       struct resource         *r;
-       int                     status = 0;
-
-       master = platform_get_drvdata(pdev);
-       spi100k = spi_master_get_devdata(master);
-
-       if (status != 0)
-               return status;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       return 0;
-}
-
 static struct platform_driver omap1_spi100k_driver = {
        .driver = {
                .name           = "omap1_spi100k",
                .owner          = THIS_MODULE,
        },
        .probe          = omap1_spi100k_probe,
-       .remove         = omap1_spi100k_remove,
 };
 
 module_platform_driver(omap1_spi100k_driver);
@@ -502,4 +483,3 @@ module_platform_driver(omap1_spi100k_driver);
 MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
 MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
 MODULE_LICENSE("GPL");
-
index 443df39840bc899fb3525dcb141ed82da87d72f4..a72127f08e39faa04d1433094590094ea1ac357d 100644 (file)
@@ -157,14 +157,14 @@ static inline void mcspi_write_reg(struct spi_master *master,
 {
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
-       __raw_writel(val, mcspi->base + idx);
+       writel_relaxed(val, mcspi->base + idx);
 }
 
 static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
 {
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
-       return __raw_readl(mcspi->base + idx);
+       return readl_relaxed(mcspi->base + idx);
 }
 
 static inline void mcspi_write_cs_reg(const struct spi_device *spi,
@@ -172,14 +172,14 @@ static inline void mcspi_write_cs_reg(const struct spi_device *spi,
 {
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       __raw_writel(val, cs->base +  idx);
+       writel_relaxed(val, cs->base +  idx);
 }
 
 static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
 {
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       return __raw_readl(cs->base + idx);
+       return readl_relaxed(cs->base + idx);
 }
 
 static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
@@ -338,7 +338,7 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
        mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable);
 
        list_for_each_entry(cs, &ctx->cs, node)
-               __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+               writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 }
 
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
@@ -346,9 +346,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
        unsigned long timeout;
 
        timeout = jiffies + msecs_to_jiffies(1000);
-       while (!(__raw_readl(reg) & bit)) {
+       while (!(readl_relaxed(reg) & bit)) {
                if (time_after(jiffies, timeout)) {
-                       if (!(__raw_readl(reg) & bit))
+                       if (!(readl_relaxed(reg) & bit))
                                return -ETIMEDOUT;
                        else
                                return 0;
@@ -675,7 +675,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %02x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -687,7 +687,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 1 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -701,7 +701,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                word_len, *(rx - 1));
                        }
@@ -722,7 +722,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %04x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -734,7 +734,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 2 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -748,7 +748,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                word_len, *(rx - 1));
                        }
@@ -769,7 +769,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %08x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -781,7 +781,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 4 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -795,7 +795,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                word_len, *(rx - 1));
                        }
@@ -1107,7 +1107,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
 
                        /* RX_ONLY mode needs dummy data in TX reg */
                        if (t->tx_buf == NULL)
-                               __raw_writel(0, cs->base
+                               writel_relaxed(0, cs->base
                                                + OMAP2_MCSPI_TX0);
 
                        if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
@@ -1470,9 +1470,9 @@ static int omap2_mcspi_resume(struct device *dev)
                         * change in account.
                         */
                        cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE;
-                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
                        cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
-                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
                }
        }
        pm_runtime_mark_last_busy(mcspi->dev);
index 744841e095e4be7d4a8b7e6f057b2bed2915cf9a..7f2121fe262223391185bfc458be0ced703463a6 100644 (file)
@@ -434,7 +434,7 @@ static int orion_spi_probe(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
        spi->master = master;
 
-       spi->clk = clk_get(&pdev->dev, NULL);
+       spi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(spi->clk)) {
                status = PTR_ERR(spi->clk);
                goto out;
@@ -465,7 +465,6 @@ static int orion_spi_probe(struct platform_device *pdev)
 
 out_rel_clk:
        clk_disable_unprepare(spi->clk);
-       clk_put(spi->clk);
 out:
        spi_master_put(master);
        return status;
@@ -481,7 +480,6 @@ static int orion_spi_remove(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
 
        clk_disable_unprepare(spi->clk);
-       clk_put(spi->clk);
 
        return 0;
 }
index 74bc18775658667617464aa865a7fb939161c438..3f006d3ed2a8bad5f749e5433aa1572ea23df15b 100644 (file)
@@ -62,7 +62,7 @@ static void ce4100_spi_remove(struct pci_dev *dev)
        platform_device_unregister(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
+static const struct pci_device_id ce4100_spi_devices[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
        { },
 };
index cb0e1f1137adb65384188ce31651171cb3f5f311..cbc68848789d09aa808ab44c8e84f4d2a765ab8f 100644 (file)
@@ -1066,6 +1066,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 
        pdata->num_chipselect = 1;
        pdata->enable_dma = true;
+       pdata->tx_chan_id = -1;
+       pdata->rx_chan_id = -1;
 
        return pdata;
 }
@@ -1073,6 +1075,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 +1295,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..d1e89bb352d8cd614a9fb31d2ce3d44dd171475e 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/spi/rspi.h>
 
-#define RSPI_SPCR              0x00
-#define RSPI_SSLP              0x01
-#define RSPI_SPPCR             0x02
-#define RSPI_SPSR              0x03
-#define RSPI_SPDR              0x04
-#define RSPI_SPSCR             0x08
-#define RSPI_SPSSR             0x09
-#define RSPI_SPBR              0x0a
-#define RSPI_SPDCR             0x0b
-#define RSPI_SPCKD             0x0c
-#define RSPI_SSLND             0x0d
-#define RSPI_SPND              0x0e
-#define RSPI_SPCR2             0x0f
-#define RSPI_SPCMD0            0x10
-#define RSPI_SPCMD1            0x12
-#define RSPI_SPCMD2            0x14
-#define RSPI_SPCMD3            0x16
-#define RSPI_SPCMD4            0x18
-#define RSPI_SPCMD5            0x1a
-#define RSPI_SPCMD6            0x1c
-#define RSPI_SPCMD7            0x1e
+#define RSPI_SPCR              0x00    /* Control Register */
+#define RSPI_SSLP              0x01    /* Slave Select Polarity Register */
+#define RSPI_SPPCR             0x02    /* Pin Control Register */
+#define RSPI_SPSR              0x03    /* Status Register */
+#define RSPI_SPDR              0x04    /* Data Register */
+#define RSPI_SPSCR             0x08    /* Sequence Control Register */
+#define RSPI_SPSSR             0x09    /* Sequence Status Register */
+#define RSPI_SPBR              0x0a    /* Bit Rate Register */
+#define RSPI_SPDCR             0x0b    /* Data Control Register */
+#define RSPI_SPCKD             0x0c    /* Clock Delay Register */
+#define RSPI_SSLND             0x0d    /* Slave Select Negation Delay Register */
+#define RSPI_SPND              0x0e    /* Next-Access Delay Register */
+#define RSPI_SPCR2             0x0f    /* Control Register 2 */
+#define RSPI_SPCMD0            0x10    /* Command Register 0 */
+#define RSPI_SPCMD1            0x12    /* Command Register 1 */
+#define RSPI_SPCMD2            0x14    /* Command Register 2 */
+#define RSPI_SPCMD3            0x16    /* Command Register 3 */
+#define RSPI_SPCMD4            0x18    /* Command Register 4 */
+#define RSPI_SPCMD5            0x1a    /* Command Register 5 */
+#define RSPI_SPCMD6            0x1c    /* Command Register 6 */
+#define RSPI_SPCMD7            0x1e    /* Command Register 7 */
+#define RSPI_SPBFCR            0x20    /* Buffer Control Register */
+#define RSPI_SPBFDR            0x22    /* Buffer Data Count Setting Register */
 
 /*qspi only */
-#define QSPI_SPBFCR            0x18
-#define QSPI_SPBDCR            0x1a
-#define QSPI_SPBMUL0           0x1c
-#define QSPI_SPBMUL1           0x20
-#define QSPI_SPBMUL2           0x24
-#define QSPI_SPBMUL3           0x28
-
-/* SPCR */
-#define SPCR_SPRIE             0x80
-#define SPCR_SPE               0x40
-#define SPCR_SPTIE             0x20
-#define SPCR_SPEIE             0x10
-#define SPCR_MSTR              0x08
-#define SPCR_MODFEN            0x04
-#define SPCR_TXMD              0x02
-#define SPCR_SPMS              0x01
-
-/* SSLP */
-#define SSLP_SSL1P             0x02
-#define SSLP_SSL0P             0x01
-
-/* SPPCR */
-#define SPPCR_MOIFE            0x20
-#define SPPCR_MOIFV            0x10
+#define QSPI_SPBFCR            0x18    /* Buffer Control Register */
+#define QSPI_SPBDCR            0x1a    /* Buffer Data Count Register */
+#define QSPI_SPBMUL0           0x1c    /* Transfer Data Length Multiplier Setting Register 0 */
+#define QSPI_SPBMUL1           0x20    /* Transfer Data Length Multiplier Setting Register 1 */
+#define QSPI_SPBMUL2           0x24    /* Transfer Data Length Multiplier Setting Register 2 */
+#define QSPI_SPBMUL3           0x28    /* Transfer Data Length Multiplier Setting Register 3 */
+
+/* SPCR - Control Register */
+#define SPCR_SPRIE             0x80    /* Receive Interrupt Enable */
+#define SPCR_SPE               0x40    /* Function Enable */
+#define SPCR_SPTIE             0x20    /* Transmit Interrupt Enable */
+#define SPCR_SPEIE             0x10    /* Error Interrupt Enable */
+#define SPCR_MSTR              0x08    /* Master/Slave Mode Select */
+#define SPCR_MODFEN            0x04    /* Mode Fault Error Detection Enable */
+/* RSPI on SH only */
+#define SPCR_TXMD              0x02    /* TX Only Mode (vs. Full Duplex) */
+#define SPCR_SPMS              0x01    /* 3-wire Mode (vs. 4-wire) */
+/* QSPI on R-Car M2 only */
+#define SPCR_WSWAP             0x02    /* Word Swap of read-data for DMAC */
+#define SPCR_BSWAP             0x01    /* Byte Swap of read-data for DMAC */
+
+/* SSLP - Slave Select Polarity Register */
+#define SSLP_SSL1P             0x02    /* SSL1 Signal Polarity Setting */
+#define SSLP_SSL0P             0x01    /* SSL0 Signal Polarity Setting */
+
+/* SPPCR - Pin Control Register */
+#define SPPCR_MOIFE            0x20    /* MOSI Idle Value Fixing Enable */
+#define SPPCR_MOIFV            0x10    /* MOSI Idle Fixed Value */
 #define SPPCR_SPOM             0x04
-#define SPPCR_SPLP2            0x02
-#define SPPCR_SPLP             0x01
-
-/* SPSR */
-#define SPSR_SPRF              0x80
-#define SPSR_SPTEF             0x20
-#define SPSR_PERF              0x08
-#define SPSR_MODF              0x04
-#define SPSR_IDLNF             0x02
-#define SPSR_OVRF              0x01
-
-/* SPSCR */
-#define SPSCR_SPSLN_MASK       0x07
-
-/* SPSSR */
-#define SPSSR_SPECM_MASK       0x70
-#define SPSSR_SPCP_MASK                0x07
-
-/* SPDCR */
-#define SPDCR_SPLW             0x20
-#define SPDCR_SPRDTD           0x10
+#define SPPCR_SPLP2            0x02    /* Loopback Mode 2 (non-inverting) */
+#define SPPCR_SPLP             0x01    /* Loopback Mode (inverting) */
+
+#define SPPCR_IO3FV            0x04    /* Single-/Dual-SPI Mode IO3 Output Fixed Value */
+#define SPPCR_IO2FV            0x04    /* Single-/Dual-SPI Mode IO2 Output Fixed Value */
+
+/* SPSR - Status Register */
+#define SPSR_SPRF              0x80    /* Receive Buffer Full Flag */
+#define SPSR_TEND              0x40    /* Transmit End */
+#define SPSR_SPTEF             0x20    /* Transmit Buffer Empty Flag */
+#define SPSR_PERF              0x08    /* Parity Error Flag */
+#define SPSR_MODF              0x04    /* Mode Fault Error Flag */
+#define SPSR_IDLNF             0x02    /* RSPI Idle Flag */
+#define SPSR_OVRF              0x01    /* Overrun Error Flag */
+
+/* SPSCR - Sequence Control Register */
+#define SPSCR_SPSLN_MASK       0x07    /* Sequence Length Specification */
+
+/* SPSSR - Sequence Status Register */
+#define SPSSR_SPECM_MASK       0x70    /* Command Error Mask */
+#define SPSSR_SPCP_MASK                0x07    /* Command Pointer Mask */
+
+/* SPDCR - Data Control Register */
+#define SPDCR_TXDMY            0x80    /* Dummy Data Transmission Enable */
+#define SPDCR_SPLW1            0x40    /* Access Width Specification (RZ) */
+#define SPDCR_SPLW0            0x20    /* Access Width Specification (RZ) */
+#define SPDCR_SPLLWORD         (SPDCR_SPLW1 | SPDCR_SPLW0)
+#define SPDCR_SPLWORD          SPDCR_SPLW1
+#define SPDCR_SPLBYTE          SPDCR_SPLW0
+#define SPDCR_SPLW             0x20    /* Access Width Specification (SH) */
+#define SPDCR_SPRDTD           0x10    /* Receive Transmit Data Select */
 #define SPDCR_SLSEL1           0x08
 #define SPDCR_SLSEL0           0x04
-#define SPDCR_SLSEL_MASK       0x0c
+#define SPDCR_SLSEL_MASK       0x0c    /* SSL1 Output Select */
 #define SPDCR_SPFC1            0x02
 #define SPDCR_SPFC0            0x01
+#define SPDCR_SPFC_MASK                0x03    /* Frame Count Setting (1-4) */
 
-/* SPCKD */
-#define SPCKD_SCKDL_MASK       0x07
+/* SPCKD - Clock Delay Register */
+#define SPCKD_SCKDL_MASK       0x07    /* Clock Delay Setting (1-8) */
 
-/* SSLND */
-#define SSLND_SLNDL_MASK       0x07
+/* SSLND - Slave Select Negation Delay Register */
+#define SSLND_SLNDL_MASK       0x07    /* SSL Negation Delay Setting (1-8) */
 
-/* SPND */
-#define SPND_SPNDL_MASK                0x07
+/* SPND - Next-Access Delay Register */
+#define SPND_SPNDL_MASK                0x07    /* Next-Access Delay Setting (1-8) */
 
-/* SPCR2 */
-#define SPCR2_PTE              0x08
-#define SPCR2_SPIE             0x04
-#define SPCR2_SPOE             0x02
-#define SPCR2_SPPE             0x01
+/* SPCR2 - Control Register 2 */
+#define SPCR2_PTE              0x08    /* Parity Self-Test Enable */
+#define SPCR2_SPIE             0x04    /* Idle Interrupt Enable */
+#define SPCR2_SPOE             0x02    /* Odd Parity Enable (vs. Even) */
+#define SPCR2_SPPE             0x01    /* Parity Enable */
 
-/* SPCMDn */
-#define SPCMD_SCKDEN           0x8000
-#define SPCMD_SLNDEN           0x4000
-#define SPCMD_SPNDEN           0x2000
-#define SPCMD_LSBF             0x1000
-#define SPCMD_SPB_MASK         0x0f00
+/* SPCMDn - Command Registers */
+#define SPCMD_SCKDEN           0x8000  /* Clock Delay Setting Enable */
+#define SPCMD_SLNDEN           0x4000  /* SSL Negation Delay Setting Enable */
+#define SPCMD_SPNDEN           0x2000  /* Next-Access Delay Enable */
+#define SPCMD_LSBF             0x1000  /* LSB First */
+#define SPCMD_SPB_MASK         0x0f00  /* Data Length Setting */
 #define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
 #define SPCMD_SPB_8BIT         0x0000  /* qspi only */
 #define SPCMD_SPB_16BIT                0x0100
 #define SPCMD_SPB_20BIT                0x0000
 #define SPCMD_SPB_24BIT                0x0100
 #define SPCMD_SPB_32BIT                0x0200
-#define SPCMD_SSLKP            0x0080
-#define SPCMD_SSLA_MASK                0x0030
-#define SPCMD_BRDV_MASK                0x000c
-#define SPCMD_CPOL             0x0002
-#define SPCMD_CPHA             0x0001
-
-/* SPBFCR */
-#define SPBFCR_TXRST           0x80    /* qspi only */
-#define SPBFCR_RXRST           0x40    /* qspi only */
+#define SPCMD_SSLKP            0x0080  /* SSL Signal Level Keeping */
+#define SPCMD_SPIMOD_MASK      0x0060  /* SPI Operating Mode (QSPI only) */
+#define SPCMD_SPIMOD1          0x0040
+#define SPCMD_SPIMOD0          0x0020
+#define SPCMD_SPIMOD_SINGLE    0
+#define SPCMD_SPIMOD_DUAL      SPCMD_SPIMOD0
+#define SPCMD_SPIMOD_QUAD      SPCMD_SPIMOD1
+#define SPCMD_SPRW             0x0010  /* SPI Read/Write Access (Dual/Quad) */
+#define SPCMD_SSLA_MASK                0x0030  /* SSL Assert Signal Setting (RSPI) */
+#define SPCMD_BRDV_MASK                0x000c  /* Bit Rate Division Setting */
+#define SPCMD_CPOL             0x0002  /* Clock Polarity Setting */
+#define SPCMD_CPHA             0x0001  /* Clock Phase Setting */
+
+/* SPBFCR - Buffer Control Register */
+#define SPBFCR_TXRST           0x80    /* Transmit Buffer Data Reset (qspi only) */
+#define SPBFCR_RXRST           0x40    /* Receive Buffer Data Reset (qspi only) */
+#define SPBFCR_TXTRG_MASK      0x30    /* Transmit Buffer Data Triggering Number */
+#define SPBFCR_RXTRG_MASK      0x07    /* Receive Buffer Data Triggering Number */
+
+#define DUMMY_DATA             0x00
 
 struct rspi_data {
        void __iomem *addr;
@@ -158,7 +186,8 @@ struct rspi_data {
        wait_queue_head_t wait;
        spinlock_t lock;
        struct clk *clk;
-       unsigned char spsr;
+       u8 spsr;
+       u16 spcmd;
        const struct spi_ops *ops;
 
        /* for dmaengine */
@@ -170,34 +199,35 @@ struct rspi_data {
        unsigned dma_callbacked:1;
 };
 
-static void rspi_write8(struct rspi_data *rspi, u8 data, u16 offset)
+static void rspi_write8(const struct rspi_data *rspi, u8 data, u16 offset)
 {
        iowrite8(data, rspi->addr + offset);
 }
 
-static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset)
+static void rspi_write16(const struct rspi_data *rspi, u16 data, u16 offset)
 {
        iowrite16(data, rspi->addr + offset);
 }
 
-static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset)
+static void rspi_write32(const struct rspi_data *rspi, u32 data, u16 offset)
 {
        iowrite32(data, rspi->addr + offset);
 }
 
-static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
+static u8 rspi_read8(const struct rspi_data *rspi, u16 offset)
 {
        return ioread8(rspi->addr + offset);
 }
 
-static u16 rspi_read16(struct rspi_data *rspi, u16 offset)
+static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
 {
        return ioread16(rspi->addr + offset);
 }
 
 /* optional functions */
 struct spi_ops {
-       int (*set_config_register)(struct rspi_data *rspi, int access_size);
+       int (*set_config_register)(const struct rspi_data *rspi,
+                                  int access_size);
        int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
                        struct spi_transfer *t);
        int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
@@ -208,7 +238,8 @@ struct spi_ops {
 /*
  * functions for RSPI
  */
-static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
+static int rspi_set_config_register(const struct rspi_data *rspi,
+                                   int access_size)
 {
        int spbr;
 
@@ -231,7 +262,7 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
        rspi_write8(rspi, 0x00, RSPI_SPCR2);
 
        /* Sets SPCMD */
-       rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
+       rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | rspi->spcmd,
                     RSPI_SPCMD0);
 
        /* Sets RSPI mode */
@@ -243,7 +274,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
 /*
  * functions for QSPI
  */
-static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
+static int qspi_set_config_register(const struct rspi_data *rspi,
+                                   int access_size)
 {
        u16 spcmd;
        int spbr;
@@ -268,10 +300,10 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
                spcmd = SPCMD_SPB_8BIT;
        else if (access_size == 16)
                spcmd = SPCMD_SPB_16BIT;
-       else if (access_size == 32)
+       else
                spcmd = SPCMD_SPB_32BIT;
 
-       spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
+       spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | rspi->spcmd | SPCMD_SPNDEN;
 
        /* Resets transfer data length */
        rspi_write32(rspi, 0, QSPI_SPBMUL0);
@@ -292,12 +324,12 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
 
 #define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
 
-static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
+static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
 }
 
-static void rspi_disable_irq(struct rspi_data *rspi, u8 disable)
+static void rspi_disable_irq(const struct rspi_data *rspi, u8 disable)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~disable, RSPI_SPCR);
 }
@@ -316,12 +348,12 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
        return 0;
 }
 
-static void rspi_assert_ssl(struct rspi_data *rspi)
+static void rspi_assert_ssl(const struct rspi_data *rspi)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_SPE, RSPI_SPCR);
 }
 
-static void rspi_negate_ssl(struct rspi_data *rspi)
+static void rspi_negate_ssl(const struct rspi_data *rspi)
 {
        rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
 }
@@ -330,9 +362,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                         struct spi_transfer *t)
 {
        int remain = t->len;
-       u8 *data;
-
-       data = (u8 *)t->tx_buf;
+       const u8 *data = t->tx_buf;
        while (remain > 0) {
                rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD,
                            RSPI_SPCR);
@@ -348,7 +378,7 @@ static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                remain--;
        }
 
-       /* Waiting for the last transmition */
+       /* Waiting for the last transmission */
        rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
 
        return 0;
@@ -358,12 +388,11 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                         struct spi_transfer *t)
 {
        int remain = t->len;
-       u8 *data;
+       const u8 *data = t->tx_buf;
 
        rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
        rspi_write8(rspi, 0x00, QSPI_SPBFCR);
 
-       data = (u8 *)t->tx_buf;
        while (remain > 0) {
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
@@ -383,7 +412,7 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
                remain--;
        }
 
-       /* Waiting for the last transmition */
+       /* Waiting for the last transmission */
        rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
 
        return 0;
@@ -399,8 +428,8 @@ static void rspi_dma_complete(void *arg)
        wake_up_interruptible(&rspi->wait);
 }
 
-static int rspi_dma_map_sg(struct scatterlist *sg, void *buf, unsigned len,
-                          struct dma_chan *chan,
+static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
+                          unsigned len, struct dma_chan *chan,
                           enum dma_transfer_direction dir)
 {
        sg_init_table(sg, 1);
@@ -440,12 +469,13 @@ static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
 static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
 {
        struct scatterlist sg;
-       void *buf = NULL;
+       const void *buf = NULL;
        struct dma_async_tx_descriptor *desc;
        unsigned len;
        int ret = 0;
 
        if (rspi->dma_width_16bit) {
+               void *tmp;
                /*
                 * If DMAC bus width is 16-bit, the driver allocates a dummy
                 * buffer. And, the driver converts original data into the
@@ -454,13 +484,14 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
                 *  DMAC data:     1st byte, dummy, 2nd byte, dummy ...
                 */
                len = t->len * 2;
-               buf = kmalloc(len, GFP_KERNEL);
-               if (!buf)
+               tmp = kmalloc(len, GFP_KERNEL);
+               if (!tmp)
                        return -ENOMEM;
-               rspi_memory_to_8bit(buf, t->tx_buf, t->len);
+               rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
+               buf = tmp;
        } else {
                len = t->len;
-               buf = (void *)t->tx_buf;
+               buf = t->tx_buf;
        }
 
        if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
@@ -508,9 +539,9 @@ end_nomap:
        return ret;
 }
 
-static void rspi_receive_init(struct rspi_data *rspi)
+static void rspi_receive_init(const struct rspi_data *rspi)
 {
-       unsigned char spsr;
+       u8 spsr;
 
        spsr = rspi_read8(rspi, RSPI_SPSR);
        if (spsr & SPSR_SPRF)
@@ -528,7 +559,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 
        rspi_receive_init(rspi);
 
-       data = (u8 *)t->rx_buf;
+       data = t->rx_buf;
        while (remain > 0) {
                rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD,
                            RSPI_SPCR);
@@ -539,7 +570,7 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
                        return -ETIMEDOUT;
                }
                /* dummy write for generate clock */
-               rspi_write16(rspi, 0x00, RSPI_SPDR);
+               rspi_write16(rspi, DUMMY_DATA, RSPI_SPDR);
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
                        dev_err(&rspi->master->dev,
@@ -556,9 +587,9 @@ static int rspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
        return 0;
 }
 
-static void qspi_receive_init(struct rspi_data *rspi)
+static void qspi_receive_init(const struct rspi_data *rspi)
 {
-       unsigned char spsr;
+       u8 spsr;
 
        spsr = rspi_read8(rspi, RSPI_SPSR);
        if (spsr & SPSR_SPRF)
@@ -575,7 +606,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 
        qspi_receive_init(rspi);
 
-       data = (u8 *)t->rx_buf;
+       data = t->rx_buf;
        while (remain > 0) {
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
@@ -584,7 +615,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
                        return -ETIMEDOUT;
                }
                /* dummy write for generate clock */
-               rspi_write8(rspi, 0x00, RSPI_SPDR);
+               rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
 
                if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
                        dev_err(&rspi->master->dev,
@@ -704,7 +735,7 @@ end_nomap:
        return ret;
 }
 
-static int rspi_is_dma(struct rspi_data *rspi, struct spi_transfer *t)
+static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
 {
        if (t->tx_buf && rspi->chan_tx)
                return 1;
@@ -771,10 +802,14 @@ static int rspi_setup(struct spi_device *spi)
 {
        struct rspi_data *rspi = spi_master_get_devdata(spi->master);
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
        rspi->max_speed_hz = spi->max_speed_hz;
 
+       rspi->spcmd = SPCMD_SSLKP;
+       if (spi->mode & SPI_CPOL)
+               rspi->spcmd |= SPCMD_CPOL;
+       if (spi->mode & SPI_CPHA)
+               rspi->spcmd |= SPCMD_CPHA;
+
        set_config_register(rspi, 8);
 
        return 0;
@@ -802,10 +837,10 @@ static void rspi_cleanup(struct spi_device *spi)
 
 static irqreturn_t rspi_irq(int irq, void *_sr)
 {
-       struct rspi_data *rspi = (struct rspi_data *)_sr;
-       unsigned long spsr;
+       struct rspi_data *rspi = _sr;
+       u8 spsr;
        irqreturn_t ret = IRQ_NONE;
-       unsigned char disable_irq = 0;
+       u8 disable_irq = 0;
 
        rspi->spsr = spsr = rspi_read8(rspi, RSPI_SPSR);
        if (spsr & SPSR_SPRF)
@@ -825,7 +860,7 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
 static int rspi_request_dma(struct rspi_data *rspi,
                                      struct platform_device *pdev)
 {
-       struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
+       const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dma_cap_mask_t mask;
        struct dma_slave_config cfg;
@@ -885,14 +920,10 @@ 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);
+       clk_disable(rspi->clk);
 
        return 0;
 }
@@ -904,7 +935,7 @@ static int rspi_probe(struct platform_device *pdev)
        struct rspi_data *rspi;
        int ret, irq;
        char clk_name[16];
-       struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
+       const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
        const struct spi_ops *ops;
        const struct platform_device_id *id_entry = pdev->id_entry;
 
@@ -914,12 +945,6 @@ static int rspi_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "there is no set_config_register\n");
                return -ENODEV;
        }
-       /* get base addr */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(res == NULL)) {
-               dev_err(&pdev->dev, "invalid resource\n");
-               return -EINVAL;
-       }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -937,19 +962,20 @@ static int rspi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rspi);
        rspi->ops = ops;
        rspi->master = master;
-       rspi->addr = ioremap(res->start, resource_size(res));
-       if (rspi->addr == NULL) {
-               dev_err(&pdev->dev, "ioremap error.\n");
-               ret = -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rspi->addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(rspi->addr)) {
+               ret = PTR_ERR(rspi->addr);
                goto error1;
        }
 
        snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
-       rspi->clk = clk_get(&pdev->dev, clk_name);
+       rspi->clk = devm_clk_get(&pdev->dev, clk_name);
        if (IS_ERR(rspi->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
                ret = PTR_ERR(rspi->clk);
-               goto error2;
+               goto error1;
        }
        clk_enable(rspi->clk);
 
@@ -966,37 +992,36 @@ static int rspi_probe(struct platform_device *pdev)
        master->setup = rspi_setup;
        master->transfer = rspi_transfer;
        master->cleanup = rspi_cleanup;
+       master->mode_bits = SPI_CPHA | SPI_CPOL;
 
-       ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi);
+       ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,
+                              dev_name(&pdev->dev), rspi);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq error\n");
-               goto error3;
+               goto error2;
        }
 
        rspi->irq = irq;
        ret = rspi_request_dma(rspi, pdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "rspi_request_dma failed.\n");
-               goto error4;
+               goto error3;
        }
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret < 0) {
                dev_err(&pdev->dev, "spi_register_master error.\n");
-               goto error4;
+               goto error3;
        }
 
        dev_info(&pdev->dev, "probed\n");
 
        return 0;
 
-error4:
-       rspi_release_dma(rspi);
-       free_irq(irq, rspi);
 error3:
-       clk_put(rspi->clk);
+       rspi_release_dma(rspi);
 error2:
-       iounmap(rspi->addr);
+       clk_disable(rspi->clk);
 error1:
        spi_master_put(master);
 
index 9eda21d739c627706a40e101f5ea0b9eed9e4fab..1edffed9e098ee775a5ed7bbcc2b111fc796652d 100644 (file)
@@ -254,9 +254,6 @@ error:
 
 static int sc18is602_setup(struct spi_device *spi)
 {
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
                return -EINVAL;
 
@@ -319,7 +316,7 @@ static int sc18is602_probe(struct i2c_client *client,
        master->transfer_one_message = sc18is602_transfer_one;
        master->dev.of_node = np;
 
-       error = spi_register_master(master);
+       error = devm_spi_register_master(dev, master);
        if (error)
                goto error_reg;
 
@@ -330,16 +327,6 @@ error_reg:
        return error;
 }
 
-static int sc18is602_remove(struct i2c_client *client)
-{
-       struct sc18is602 *hw = i2c_get_clientdata(client);
-       struct spi_master *master = hw->master;
-
-       spi_unregister_master(master);
-
-       return 0;
-}
-
 static const struct i2c_device_id sc18is602_id[] = {
        { "sc18is602", sc18is602 },
        { "sc18is602b", sc18is602b },
@@ -353,7 +340,6 @@ static struct i2c_driver sc18is602_driver = {
                .name = "sc18is602",
        },
        .probe = sc18is602_probe,
-       .remove = sc18is602_remove,
        .id_table = sc18is602_id,
 };
 
index 292567ab4c6c41df0eb981c8692d0454e98bf8ed..82d2f922ffa0a830883fee3aafff2be4b86c1d50 100644 (file)
@@ -197,7 +197,7 @@ static int hspi_transfer_one_message(struct spi_master *master,
 
                        hspi_write(hspi, SPTBR, tx);
 
-                       /* wait recive */
+                       /* wait receive */
                        ret = hspi_status_check_timeout(hspi, 0x4, 0x4);
                        if (ret < 0)
                                break;
@@ -353,4 +353,4 @@ module_platform_driver(hspi_driver);
 MODULE_DESCRIPTION("SuperH HSPI bus driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_ALIAS("platform:sh_spi");
+MODULE_ALIAS("platform:sh-hspi");
index a0c3e54b0003117c6deb8c21c94da2d6b74a9bdd..81cc02f5f9b02494379bbc7cfb5547f17c48fb20 100644 (file)
@@ -152,7 +152,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
        size_t k;
 
        if (!WARN_ON(!spi_hz || !parent_rate))
-               div = parent_rate / spi_hz;
+               div = DIV_ROUND_UP(parent_rate, spi_hz);
 
        /* TODO: make more fine grained */
 
index c120a70094f20f131cf0ef5e7a3861e57f9eba39..86a17d60a68c0f24b495c7257460d2fe558d2dcb 100644 (file)
@@ -358,9 +358,6 @@ static int spi_sh_setup(struct spi_device *spi)
 {
        struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        pr_debug("%s: enter\n", __func__);
 
        spi_sh_write(ss, 0xfe, SPI_SH_CR1);     /* SPI sycle stop */
index ed5e501c465276b6d39318818fa5d668d2685668..e430689c3837360f02e5e6d7e70a40ceae712777 100644 (file)
@@ -536,16 +536,9 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
 static int spi_sirfsoc_setup(struct spi_device *spi)
 {
-       struct sirfsoc_spi *sspi;
-
        if (!spi->max_speed_hz)
                return -EINVAL;
 
-       sspi = spi_master_get_devdata(spi->master);
-
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        return spi_sirfsoc_setup_transfer(spi, NULL);
 }
 
index 0b71270fbf67ba671dd43f116db48de30076514c..286cf8d6764beac9f7e705692ffc3c055c836c3d 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;
        }
@@ -417,10 +417,8 @@ out:
 static int ti_qspi_runtime_resume(struct device *dev)
 {
        struct ti_qspi      *qspi;
-       struct spi_master       *master;
 
-       master = dev_get_drvdata(dev);
-       qspi = spi_master_get_devdata(master);
+       qspi = dev_get_drvdata(dev);
        ti_qspi_restore_ctx(qspi);
 
        return 0;
@@ -459,11 +457,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 +514,20 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
-       struct  ti_qspi *qspi = platform_get_drvdata(pdev);
+       struct ti_qspi *qspi = platform_get_drvdata(pdev);
+       int ret;
+
+       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);
+
        return 0;
 }
 
index 446131308acb26a1fac3ed8bfc1aad9e287404d5..2e7f38c7a9610b11f63fd36c816f311b3372d66d 100644 (file)
@@ -217,7 +217,7 @@ struct pch_pd_dev_save {
        struct pch_spi_board_data *board_dat;
 };
 
-static DEFINE_PCI_DEVICE_TABLE(pch_spi_pcidev_id) = {
+static const struct pci_device_id pch_spi_pcidev_id[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI),    1, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
@@ -466,12 +466,6 @@ static void pch_spi_reset(struct spi_master *master)
 
 static int pch_spi_setup(struct spi_device *pspi)
 {
-       /* check bits per word */
-       if (pspi->bits_per_word == 0) {
-               pspi->bits_per_word = 8;
-               dev_dbg(&pspi->dev, "%s 8 bits per word\n", __func__);
-       }
-
        /* Check baud rate setting */
        /* if baud rate of chip is greater than
           max we can support,return error */
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..63613a96233c3f1eddc77846affea03ffe92a852 100644 (file)
@@ -370,6 +370,17 @@ static void spi_dev_set_name(struct spi_device *spi)
                     spi->chip_select);
 }
 
+static int spi_dev_check(struct device *dev, void *data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct spi_device *new_spi = data;
+
+       if (spi->master == new_spi->master &&
+           spi->chip_select == new_spi->chip_select)
+               return -EBUSY;
+       return 0;
+}
+
 /**
  * spi_add_device - Add spi_device allocated with spi_alloc_device
  * @spi: spi_device to register
@@ -384,7 +395,6 @@ int spi_add_device(struct spi_device *spi)
        static DEFINE_MUTEX(spi_add_lock);
        struct spi_master *master = spi->master;
        struct device *dev = master->dev.parent;
-       struct device *d;
        int status;
 
        /* Chipselects are numbered 0..max; validate. */
@@ -404,12 +414,10 @@ int spi_add_device(struct spi_device *spi)
         */
        mutex_lock(&spi_add_lock);
 
-       d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
-       if (d != NULL) {
+       status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
+       if (status) {
                dev_err(dev, "chipselect %d already in use\n",
                                spi->chip_select);
-               put_device(d);
-               status = -EBUSY;
                goto done;
        }
 
@@ -591,8 +599,10 @@ static int spi_transfer_one_message(struct spi_master *master,
                        goto out;
                }
 
-               if (ret > 0)
+               if (ret > 0) {
+                       ret = 0;
                        wait_for_completion(&master->xfer_completion);
+               }
 
                trace_spi_transfer_stop(msg, xfer);
 
@@ -632,7 +642,7 @@ out:
  *
  * Called by SPI drivers using the core transfer_one_message()
  * implementation to notify it that the current interrupt driven
- * transfer has finised and the next one may be scheduled.
+ * transfer has finished and the next one may be scheduled.
  */
 void spi_finalize_current_transfer(struct spi_master *master)
 {
@@ -685,7 +695,7 @@ static void spi_pump_messages(struct kthread_work *work)
        }
        /* Extract head of queue */
        master->cur_msg =
-           list_entry(master->queue.next, struct spi_message, queue);
+               list_first_entry(&master->queue, struct spi_message, queue);
 
        list_del_init(&master->cur_msg->queue);
        if (master->busy)
@@ -735,7 +745,9 @@ static void spi_pump_messages(struct kthread_work *work)
        ret = master->transfer_one_message(master, master->cur_msg);
        if (ret) {
                dev_err(&master->dev,
-                       "failed to transfer one message from queue\n");
+                       "failed to transfer one message from queue: %d\n", ret);
+               master->cur_msg->status = ret;
+               spi_finalize_current_message(master);
                return;
        }
 }
@@ -791,11 +803,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master)
 
        /* get a pointer to the next message, if any */
        spin_lock_irqsave(&master->queue_lock, flags);
-       if (list_empty(&master->queue))
-               next = NULL;
-       else
-               next = list_entry(master->queue.next,
-                                 struct spi_message, queue);
+       next = list_first_entry_or_null(&master->queue, struct spi_message,
+                                       queue);
        spin_unlock_irqrestore(&master->queue_lock, flags);
 
        return next;
@@ -1415,7 +1424,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 {
@@ -1596,15 +1605,11 @@ int spi_setup(struct spi_device *spi)
 }
 EXPORT_SYMBOL_GPL(spi_setup);
 
-static int __spi_async(struct spi_device *spi, struct spi_message *message)
+static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 {
        struct spi_master *master = spi->master;
        struct spi_transfer *xfer;
 
-       message->spi = spi;
-
-       trace_spi_message_submit(message);
-
        if (list_empty(&message->transfers))
                return -EINVAL;
        if (!message->complete)
@@ -1667,9 +1672,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                if (xfer->rx_buf && !xfer->rx_nbits)
                        xfer->rx_nbits = SPI_NBITS_SINGLE;
                /* check transfer tx/rx_nbits:
-                * 1. keep the value is not out of single, dual and quad
-                * 2. keep tx/rx_nbits is contained by mode in spi_device
-                * 3. if SPI_3WIRE, tx/rx_nbits should be in single
+                * 1. check the value matches one of single, dual and quad
+                * 2. check tx/rx_nbits match the mode in spi_device
                 */
                if (xfer->tx_buf) {
                        if (xfer->tx_nbits != SPI_NBITS_SINGLE &&
@@ -1682,9 +1686,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                        if ((xfer->tx_nbits == SPI_NBITS_QUAD) &&
                                !(spi->mode & SPI_TX_QUAD))
                                return -EINVAL;
-                       if ((spi->mode & SPI_3WIRE) &&
-                               (xfer->tx_nbits != SPI_NBITS_SINGLE))
-                               return -EINVAL;
                }
                /* check transfer rx_nbits */
                if (xfer->rx_buf) {
@@ -1698,13 +1699,22 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
                        if ((xfer->rx_nbits == SPI_NBITS_QUAD) &&
                                !(spi->mode & SPI_RX_QUAD))
                                return -EINVAL;
-                       if ((spi->mode & SPI_3WIRE) &&
-                               (xfer->rx_nbits != SPI_NBITS_SINGLE))
-                               return -EINVAL;
                }
        }
 
        message->status = -EINPROGRESS;
+
+       return 0;
+}
+
+static int __spi_async(struct spi_device *spi, struct spi_message *message)
+{
+       struct spi_master *master = spi->master;
+
+       message->spi = spi;
+
+       trace_spi_message_submit(message);
+
        return master->transfer(spi, message);
 }
 
@@ -1743,6 +1753,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
        int ret;
        unsigned long flags;
 
+       ret = __spi_validate(spi, message);
+       if (ret != 0)
+               return ret;
+
        spin_lock_irqsave(&master->bus_lock_spinlock, flags);
 
        if (master->bus_lock_flag)
@@ -1791,6 +1805,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
        int ret;
        unsigned long flags;
 
+       ret = __spi_validate(spi, message);
+       if (ret != 0)
+               return ret;
+
        spin_lock_irqsave(&master->bus_lock_spinlock, flags);
 
        ret = __spi_async(spi, message);
index 53fee2f9a498866c6a19d3d6c3ca1d078fd7206e..8dfdd2732bdc329b3865c010d0afdb8e1e248337 100644 (file)
@@ -39,7 +39,8 @@ static INT bcm_close(struct net_device *dev)
        return 0;
 }
 
-static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        return ClassifyPacket(netdev_priv(dev), skb);
 }
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 235d2b1ec593c4dfba7a83c4eb5fd0f578e0c5c4..eedffed17e391d3243443c443ff9338bf494c440 100644 (file)
@@ -306,7 +306,8 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
        return NETDEV_TX_OK;
 }
 
-static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb)
+static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        return (u16)smp_processor_id();
 }
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 17659bb04befc24fabded5439be74aba9fdcb5d1..dd69e344e4099c852ffd0bd5ef11ef859a0e274c 100644 (file)
@@ -652,7 +652,8 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb)
        return dscp >> 5;
 }
 
-static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct adapter  *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
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 aa3397620342d20beba92abc732845273d3663ca..2c29db6a247e4788256461100bed11ac79648d26 100644 (file)
@@ -477,9 +477,10 @@ extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
                        const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
 extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
-extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-               const unsigned char *path,
-               struct cifs_sb_info *cifs_sb, unsigned int xid);
+extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                             struct cifs_sb_info *cifs_sb,
+                             struct cifs_fattr *fattr,
+                             const unsigned char *path);
 extern int mdfour(unsigned char *, unsigned char *, int);
 extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
                        const struct nls_table *codepage);
index 124aa0230c1b8738edb8d04ca5d764f0a6cc5b12..d707edb6b852695f0de3993c9ef9cd12a3f909f3 100644 (file)
@@ -4010,7 +4010,7 @@ QFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4179,7 +4179,7 @@ UnixQFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4263,7 +4263,7 @@ UnixQPathInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
index 11ff5f116b20e663bf5e0428a940b437d9b232aa..a514e0a65f69b5936fbd60934b33938666f70dd0 100644 (file)
@@ -193,7 +193,7 @@ check_name(struct dentry *direntry)
 static int
 cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
               struct tcon_link *tlink, unsigned oflags, umode_t mode,
-              __u32 *oplock, struct cifs_fid *fid, int *created)
+              __u32 *oplock, struct cifs_fid *fid)
 {
        int rc = -ENOENT;
        int create_options = CREATE_NOT_DIR;
@@ -349,7 +349,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
                                .device = 0,
                };
 
-               *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        args.uid = current_fsuid();
                        if (inode->i_mode & S_ISGID)
@@ -480,13 +479,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
        cifs_add_pending_open(&fid, tlink, &open);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, opened);
+                           &oplock, &fid);
 
        if (rc) {
                cifs_del_pending_open(&open);
                goto out;
        }
 
+       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               *opened |= FILE_CREATED;
+
        rc = finish_open(file, direntry, generic_file_open, opened);
        if (rc) {
                if (server->ops->close)
@@ -529,7 +531,6 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
        struct TCP_Server_Info *server;
        struct cifs_fid fid;
        __u32 oplock;
-       int created = FILE_CREATED;
 
        cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n",
                 inode, direntry->d_name.name, direntry);
@@ -546,7 +547,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                server->ops->new_lease_key(&fid);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, &created);
+                           &oplock, &fid);
        if (!rc && server->ops->close)
                server->ops->close(xid, tcon, &fid);
 
index 36f9ebb93ceba676c363cdf7b973f3936a9dde8f..49719b8228e58bd44b373fd4b39d844be9e2043b 100644 (file)
@@ -383,7 +383,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                              full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
@@ -799,7 +800,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                          full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
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 cc0234710ddbb780cae5037b717a93d8a7d3d54d..92aee08483a52e100011fb05e1fcfc5255b340ac 100644 (file)
@@ -354,34 +354,30 @@ open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
 
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-                  const unsigned char *path,
-                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                  const unsigned char *path)
 {
-       int rc = 0;
+       int rc;
        u8 *buf = NULL;
        unsigned int link_len = 0;
        unsigned int bytes_read = 0;
-       struct cifs_tcon *ptcon;
 
        if (!CIFSCouldBeMFSymlink(fattr))
                /* it's not a symlink */
                return 0;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-       if (!buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!buf)
+               return -ENOMEM;
 
-       ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
-       if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
-               rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
-                                                &bytes_read, cifs_sb, xid);
+       if (tcon->ses->server->ops->query_mf_symlink)
+               rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
+                                               &bytes_read, cifs_sb, xid);
        else
-               goto out;
+               rc = -ENOSYS;
 
-       if (rc != 0)
+       if (rc)
                goto out;
 
        if (bytes_read == 0) /* not a symlink */
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..af903128891cfa0365f7fac36ba8fc052cc584a4 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
@@ -1908,10 +1907,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                        }
                }
        }
-       if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
-               tep = tf.file->private_data;
-               mutex_lock_nested(&tep->mtx, 1);
-       }
 
        /*
         * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
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..3384dc4bed4034921beffb84783327024e4cf22e 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_COFF(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 b7fc035a6943cc40f649f1cca7be5858fbcf1cbc..73f3e4ee403793e1ae39c75b5d652f64c6a4b52a 100644 (file)
@@ -986,6 +986,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
+       struct address_space *mapping = inode->i_mapping;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int rv;
@@ -1006,6 +1007,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
        if (rv != 1)
                goto out; /* dio not valid, fall back to buffered i/o */
 
+       /*
+        * Now since we are holding a deferred (CW) lock at this point, you
+        * might be wondering why this is ever needed. There is a case however
+        * where we've granted a deferred local lock against a cached exclusive
+        * glock. That is ok provided all granted local locks are deferred, but
+        * it also means that it is possible to encounter pages which are
+        * cached and possibly also mapped. So here we check for that and sort
+        * them out ahead of the dio. The glock state machine will take care of
+        * everything else.
+        *
+        * If in fact the cached glock state (gl->gl_state) is deferred (CW) in
+        * the first place, mapping->nr_pages will always be zero.
+        */
+       if (mapping->nrpages) {
+               loff_t lstart = offset & (PAGE_CACHE_SIZE - 1);
+               loff_t len = iov_length(iov, nr_segs);
+               loff_t end = PAGE_ALIGN(offset + len) - 1;
+
+               rv = 0;
+               if (len == 0)
+                       goto out;
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len);
+               rv = filemap_write_and_wait_range(mapping, lstart, end);
+               if (rv)
+                       return rv;
+               truncate_inode_pages_range(mapping, lstart, end);
+       }
+
        rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs, gfs2_get_block_direct,
                                  NULL, NULL, 0);
index c8420f7e4db604da3663da61c5ae4556b6439783..6f7a47c052592145d7601c0e9ab0341c4dd8c4d7 100644 (file)
@@ -1655,6 +1655,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
        struct task_struct *gh_owner = NULL;
        char flags_buf[32];
 
+       rcu_read_lock();
        if (gh->gh_owner_pid)
                gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
        gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
@@ -1664,6 +1665,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
                       gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
                       gh_owner ? gh_owner->comm : "(ended)",
                       (void *)gh->gh_ip);
+       rcu_read_unlock();
        return 0;
 }
 
index db908f697139cfffbca462d3a7528e13139576b5..f88dcd92501098e4a9bca28724da34e8df5a0154 100644 (file)
@@ -192,8 +192,11 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
        if (ip && !S_ISREG(ip->i_inode.i_mode))
                ip = NULL;
-       if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
-               unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+       if (ip) {
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+               inode_dio_wait(&ip->i_inode);
+       }
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
 
@@ -410,6 +413,9 @@ static int inode_go_lock(struct gfs2_holder *gh)
                        return error;
        }
 
+       if (gh->gh_state != LM_ST_DEFERRED)
+               inode_dio_wait(&ip->i_inode);
+
        if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) &&
            (gl->gl_state == LM_ST_EXCLUSIVE) &&
            (gh->gh_state == LM_ST_EXCLUSIVE)) {
index 610613fb65b552dccfdf9853ac96d2f667bd36d4..9dcb9777a5f80eb32bcfce88aca3a8026776f047 100644 (file)
@@ -551,10 +551,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct buffer_head *bh = bd->bd_bh;
        struct gfs2_glock *gl = bd->bd_gl;
 
-       gfs2_remove_from_ail(bd);
-       bd->bd_bh = NULL;
        bh->b_private = NULL;
        bd->bd_blkno = bh->b_blocknr;
+       gfs2_remove_from_ail(bd); /* drops ref on bh */
+       bd->bd_bh = NULL;
        bd->bd_ops = &gfs2_revoke_lops;
        sdp->sd_log_num_revoke++;
        atomic_inc(&gl->gl_revokes);
index 932415050540e2a1bdefc6d957e68ef7a0d82d01..52f177be3bf861309ed2439d33da7617bba8dba8 100644 (file)
@@ -258,6 +258,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
        struct address_space *mapping = bh->b_page->mapping;
        struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
        struct gfs2_bufdata *bd = bh->b_private;
+       int was_pinned = 0;
 
        if (test_clear_buffer_pinned(bh)) {
                trace_gfs2_pin(bd, 0);
@@ -273,12 +274,16 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
                        tr->tr_num_databuf_rm++;
                }
                tr->tr_touched = 1;
+               was_pinned = 1;
                brelse(bh);
        }
        if (bd) {
                spin_lock(&sdp->sd_ail_lock);
                if (bd->bd_tr) {
                        gfs2_trans_add_revoke(sdp, bd);
+               } else if (was_pinned) {
+                       bh->b_private = NULL;
+                       kmem_cache_free(gfs2_bufdata_cachep, bd);
                }
                spin_unlock(&sdp->sd_ail_lock);
        }
index 82303b4749582cd3c00d402a9f42b9972b1de677..52fa88314f5cdf8ef98ed95e44791a5065cbfccd 100644 (file)
@@ -1366,8 +1366,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        if (IS_ERR(s))
                goto error_bdev;
 
-       if (s->s_root)
+       if (s->s_root) {
+               /*
+                * s_umount nests inside bd_mutex during
+                * __invalidate_device().  blkdev_put() acquires
+                * bd_mutex and can't be called under s_umount.  Drop
+                * s_umount temporarily.  This is safe as we're
+                * holding an active reference.
+                */
+               up_write(&s->s_umount);
                blkdev_put(bdev, mode);
+               down_write(&s->s_umount);
+       }
 
        memset(&args, 0, sizeof(args));
        args.ar_quota = GFS2_QUOTA_DEFAULT;
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 739e0a52dedadea67eb595f4b03619ce3e3383a3..5549d69ddb45a2038ece8e24085e0f9ef6ce9984 100644 (file)
@@ -110,7 +110,7 @@ xfs_attr3_rmt_verify(
        if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
                return false;
        if (be32_to_cpu(rmt->rm_offset) +
-                               be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX)
+                               be32_to_cpu(rmt->rm_bytes) > XATTR_SIZE_MAX)
                return false;
        if (rmt->rm_owner == 0)
                return false;
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..82e0dab46ee52cc991a7130d8f671e011eef10a3 100644 (file)
@@ -287,6 +287,7 @@ xfs_bmapi_allocate(
        INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
        queue_work(xfs_alloc_wq, &args->work);
        wait_for_completion(&done);
+       destroy_work_on_stack(&args->work);
        return args->result;
 }
 
@@ -1187,7 +1188,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 +1206,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..ddabed1f51c22227df9fdc1a7d050ca3b395b470 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;
 };
 
@@ -168,7 +169,8 @@ struct acpi_device_flags {
        u32 ejectable:1;
        u32 power_manageable:1;
        u32 match_driver:1;
-       u32 reserved:27;
+       u32 no_hotplug:1;
+       u32 reserved:26;
 };
 
 /* File System */
@@ -343,6 +345,7 @@ extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
 void acpi_bus_private_data_handler(acpi_handle, void *);
 int acpi_bus_get_private_data(acpi_handle, void **);
+void acpi_bus_no_hotplug(acpi_handle handle);
 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
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 */
diff --git a/include/crypto/ablk_helper.h b/include/crypto/ablk_helper.h
new file mode 100644 (file)
index 0000000..4f93df5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Shared async block cipher helpers
+ */
+
+#ifndef _CRYPTO_ABLK_HELPER_H
+#define _CRYPTO_ABLK_HELPER_H
+
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+#include <crypto/cryptd.h>
+
+struct async_helper_ctx {
+       struct cryptd_ablkcipher *cryptd_tfm;
+};
+
+extern int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
+                       unsigned int key_len);
+
+extern int __ablk_encrypt(struct ablkcipher_request *req);
+
+extern int ablk_encrypt(struct ablkcipher_request *req);
+
+extern int ablk_decrypt(struct ablkcipher_request *req);
+
+extern void ablk_exit(struct crypto_tfm *tfm);
+
+extern int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name);
+
+extern int ablk_init(struct crypto_tfm *tfm);
+
+#endif /* _CRYPTO_ABLK_HELPER_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 87578c109e4869bbecf5cce3a7530a0c2fb80637..49376aec2fbb8a9e054b9605fd9de36e4cd39c5f 100644 (file)
        {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
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 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 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 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..ce2a1f5f9a1e0226d933d28606823239e4467526 100644 (file)
@@ -769,7 +769,8 @@ struct netdev_phys_port_id {
  *        (can also return NETDEV_TX_LOCKED iff NETIF_F_LLTX)
  *     Required can not be NULL.
  *
- * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb);
+ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
+ *                         void *accel_priv);
  *     Called to decide which queue to when device supports multiple
  *     transmit queues.
  *
@@ -990,7 +991,8 @@ struct net_device_ops {
        netdev_tx_t             (*ndo_start_xmit) (struct sk_buff *skb,
                                                   struct net_device *dev);
        u16                     (*ndo_select_queue)(struct net_device *dev,
-                                                   struct sk_buff *skb);
+                                                   struct sk_buff *skb,
+                                                   void *accel_priv);
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
@@ -1255,7 +1257,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
@@ -1529,7 +1531,8 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
 }
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb);
+                                   struct sk_buff *skb,
+                                   void *accel_priv);
 u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
@@ -1819,6 +1822,7 @@ int dev_close(struct net_device *dev);
 void dev_disable_lro(struct net_device *dev);
 int dev_loopback_xmit(struct sk_buff *newskb);
 int dev_queue_xmit(struct sk_buff *skb);
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
 int register_netdevice(struct net_device *dev);
 void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
 void unregister_netdevice_many(struct list_head *head);
@@ -1912,6 +1916,15 @@ static inline int dev_parse_header(const struct sk_buff *skb,
        return dev->header_ops->parse(skb, haddr);
 }
 
+static inline int dev_rebuild_header(struct sk_buff *skb)
+{
+       const struct net_device *dev = skb->dev;
+
+       if (!dev->header_ops || !dev->header_ops->rebuild)
+               return 0;
+       return dev->header_ops->rebuild(skb);
+}
+
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
 static inline int unregister_gifconf(unsigned int family)
@@ -2417,7 +2430,7 @@ int dev_change_carrier(struct net_device *, bool new_carrier);
 int dev_get_phys_port_id(struct net_device *dev,
                         struct netdev_phys_port_id *ppid);
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv);
+                       struct netdev_queue *txq);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 
 extern int             netdev_budget;
@@ -3008,6 +3021,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
        dev->gso_max_size = size;
 }
 
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+                                       int pulled_hlen, u16 mac_offset,
+                                       int mac_len)
+{
+       skb->protocol = protocol;
+       skb->encapsulation = 1;
+       skb_push(skb, pulled_hlen);
+       skb_reset_transport_header(skb);
+       skb->mac_header = mac_offset;
+       skb->network_header = skb->mac_header + mac_len;
+       skb->mac_len = mac_len;
+}
+
 static inline bool netif_is_macvlan(struct net_device *dev)
 {
        return dev->priv_flags & IFF_MACVLAN;
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 2c4e0c1285010fdfee53bebeaff4cd638c50a56f..4b3f46832e197b6fab7214dec07a7a149063be60 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-w90x900/include/mach/nuc900_spi.h
- *
  * Copyright (c) 2009 Nuvoton technology corporation.
  *
  * Wan ZongShun <mcuos.com@gmail.com>
@@ -11,8 +9,8 @@
  *
  */
 
-#ifndef __ASM_ARCH_SPI_H
-#define __ASM_ARCH_SPI_H
+#ifndef __SPI_NUC900_H
+#define __SPI_NUC900_H
 
 extern void mfp_set_groupg(struct device *dev, const char *subname);
 
@@ -32,4 +30,4 @@ struct nuc900_spi_chip {
        unsigned char bits_per_word;
 };
 
-#endif /* __ASM_ARCH_SPI_H */
+#endif /* __SPI_NUC900_H */
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 939428ad25acb506297c1726faaee83d60d047c4..8e3e66ac0a5215d221042e15e631fb2fe2fb51d1 100644 (file)
@@ -24,6 +24,11 @@ extern int rtnl_trylock(void);
 extern int rtnl_is_locked(void);
 #ifdef CONFIG_PROVE_LOCKING
 extern int lockdep_rtnl_is_held(void);
+#else
+static inline int lockdep_rtnl_is_held(void)
+{
+       return 1;
+}
 #endif /* #ifdef CONFIG_PROVE_LOCKING */
 
 /**
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..6f69b3f914fbf94c2d6d42beea62748a29a42d08 100644 (file)
@@ -1638,6 +1638,11 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
        skb->mac_header += offset;
 }
 
+static inline void skb_pop_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->network_header;
+}
+
 static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
 {
@@ -2263,6 +2268,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 +2383,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)
 {
@@ -2529,6 +2531,10 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  * Ethernet MAC Drivers should call this function in their hard_xmit()
  * function immediately before giving the sk_buff to the MAC hardware.
  *
+ * Specifically, one should make absolutely sure that this function is
+ * called before TX completion of this packet can trigger.  Otherwise
+ * the packet could potentially already be freed.
+ *
  * @skb: A socket buffer.
  */
 static inline void skb_tx_timestamp(struct sk_buff *skb)
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 8c62ba74dd91d9800439038d86298f2e2477f1fe..a1d4ca290862d766d5460f198503ae4530df3f45 100644 (file)
@@ -75,6 +75,7 @@ struct spi_device {
        struct spi_master       *master;
        u32                     max_speed_hz;
        u8                      chip_select;
+       u8                      bits_per_word;
        u16                     mode;
 #define        SPI_CPHA        0x01                    /* clock phase */
 #define        SPI_CPOL        0x02                    /* clock polarity */
@@ -92,7 +93,6 @@ struct spi_device {
 #define        SPI_TX_QUAD     0x200                   /* transmit with 4 wires */
 #define        SPI_RX_DUAL     0x400                   /* receive with 2 wires */
 #define        SPI_RX_QUAD     0x800                   /* receive with 4 wires */
-       u8                      bits_per_word;
        int                     irq;
        void                    *controller_state;
        void                    *controller_data;
@@ -277,15 +277,17 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @unprepare_transfer_hardware: there are currently no more messages on the
  *     queue so the subsystem notifies the driver that it may relax the
  *     hardware by issuing this call
- * @set_cs: assert or deassert chip select, true to assert.  May be called
+ * @set_cs: set the logic level of the chip select line.  May be called
  *          from interrupt context.
  * @prepare_message: set up the controller to transfer a single message,
  *                   for example doing DMA mapping.  Called from threaded
  *                   context.
- * @transfer_one: transfer a single spi_transfer. When the
- *               driver is finished with this transfer it must call
- *               spi_finalize_current_transfer() so the subsystem can issue
- *                the next transfer
+ * @transfer_one: transfer a single spi_transfer.
+ *                  - return 0 if the transfer is finished,
+ *                  - return 1 if the transfer is still in progress. When
+ *                    the driver is finished with this transfer it must
+ *                    call spi_finalize_current_transfer() so the subsystem
+ *                    can issue the next transfer
  * @unprepare_message: undo any work done by prepare_message().
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *     number. Any individual value may be -ENOENT for CS lines that
@@ -576,8 +578,8 @@ struct spi_transfer {
        dma_addr_t      rx_dma;
 
        unsigned        cs_change:1;
-       u8              tx_nbits;
-       u8              rx_nbits;
+       unsigned        tx_nbits:3;
+       unsigned        rx_nbits:3;
 #define        SPI_NBITS_SINGLE        0x01 /* 1bit transfer */
 #define        SPI_NBITS_DUAL          0x02 /* 2bits transfer */
 #define        SPI_NBITS_QUAD          0x04 /* 4bits transfer */
@@ -847,7 +849,7 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
        ssize_t                 status;
        u16                     result;
 
-       status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
+       status = spi_write_then_read(spi, &cmd, 1, &result, 2);
 
        /* return negative errno or unsigned value */
        return (status < 0) ? status : result;
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 31e2de7d57c5d6c210e1b445b19551407fd31b6c..c0f0a13ed8183e58029aec1d12097aa1efb085f0 100644 (file)
 #define LLC_S_PF_IS_1(pdu)     ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 1 : 0)
 
 #define PDU_SUPV_GET_Nr(pdu)   ((pdu->ctrl_2 & 0xFE) >> 1)
-#define PDU_GET_NEXT_Vr(sn)    (++sn & ~LLC_2_SEQ_NBR_MODULO)
+#define PDU_GET_NEXT_Vr(sn)    (((sn) + 1) & ~LLC_2_SEQ_NBR_MODULO)
 
 /* FRMR information field macros */
 
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..0a248b323d875c08ca456d62ed46c028781e9432 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? */
@@ -1045,9 +1046,6 @@ struct sctp_outq {
 
        /* Corked? */
        char cork;
-
-       /* Is this structure empty?  */
-       char empty;
 };
 
 void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
@@ -1725,12 +1723,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 af998397041768a82ee347665e7040a9a4e44b9c..5f73785f5977e5f3c1b1a443c8f4a8f194b5f2b2 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;
 }
 
index 2037c45adfe648e907fa86290f7dfea847989c20..56ebdfca627375b1a7ec7d5ce5606bc124ecdf42 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, \
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 2f3f7ea8c77b8a653b0972302ead53319f13e5fc..fe421e8a431bcf91dd1d5e845b5d06ce81bbe23d 100644 (file)
@@ -983,6 +983,8 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_CP_DMA_COMPUTE  0x17
 /* CIK macrotile mode array */
 #define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY   0x18
+/* query the number of render backends */
+#define RADEON_INFO_SI_BACKEND_ENABLED_MASK    0x19
 
 
 struct drm_radeon_info {
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..bd24470d24a2c7a3145af21094e03f67b7ce0761 100644 (file)
@@ -464,7 +464,8 @@ struct input_keymap_entry {
 #define KEY_BRIGHTNESS_ZERO    244     /* brightness off, use ambient */
 #define KEY_DISPLAY_OFF                245     /* display device to off state */
 
-#define KEY_WIMAX              246
+#define KEY_WWAN               246     /* Wireless WAN (LTE, UMTS, GSM, etc.) */
+#define KEY_WIMAX              KEY_WWAN
 #define KEY_RFKILL             247     /* Key that controls all radios */
 
 #define KEY_MICMUTE            248     /* Mute / unmute the microphone */
@@ -719,6 +720,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 +859,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 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 5bff0814776870e2974e6e436ad99f99f264e05a..bbc4d660221ac4e514e24d49ce140b25ad5364d2 100644 (file)
@@ -208,9 +208,10 @@ get_write_lock:
                if (mapping_cap_account_dirty(mapping)) {
                        unsigned long addr;
                        struct file *file = get_file(vma->vm_file);
+                       /* mmap_region may free vma; grab the info now */
+                       vm_flags = vma->vm_flags;
 
-                       addr = mmap_region(file, start, size,
-                                       vma->vm_flags, pgoff);
+                       addr = mmap_region(file, start, size, vm_flags, pgoff);
                        fput(file);
                        if (IS_ERR_VALUE(addr)) {
                                err = addr;
@@ -218,7 +219,7 @@ get_write_lock:
                                BUG_ON(addr != start);
                                err = 0;
                        }
-                       goto out;
+                       goto out_freed;
                }
                mutex_lock(&mapping->i_mmap_mutex);
                flush_dcache_mmap_lock(mapping);
@@ -253,6 +254,7 @@ get_write_lock:
 out:
        if (vma)
                vm_flags = vma->vm_flags;
+out_freed:
        if (likely(!has_write_lock))
                up_read(&mm->mmap_sem);
        else
index bccd5a628ea6765478d2fa45dc01390a83ee8a5b..95d1acb0f3d237f55f5f1d6405de5774f0f9fc6a 100644 (file)
@@ -882,6 +882,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                ret = 0;
                goto out_unlock;
        }
+
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1153,7 +1154,7 @@ alloc:
                new_page = NULL;
 
        if (unlikely(!new_page)) {
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        ret = do_huge_pmd_wp_zero_page_fallback(mm, vma,
                                        address, pmd, orig_pmd, haddr);
                } else {
@@ -1180,7 +1181,7 @@ alloc:
 
        count_vm_event(THP_FAULT_ALLOC);
 
-       if (is_huge_zero_pmd(orig_pmd))
+       if (!page)
                clear_huge_page(new_page, haddr, HPAGE_PMD_NR);
        else
                copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
@@ -1206,7 +1207,7 @@ alloc:
                page_add_new_anon_rmap(new_page, vma, haddr);
                set_pmd_at(mm, haddr, pmd, entry);
                update_mmu_cache_pmd(vma, address, pmd);
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
                        put_huge_zero_page();
                } else {
@@ -1243,6 +1244,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 +1300,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 +1339,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 +1366,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 +1503,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 +1539,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 +1555,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..7f1a356153c013349ce520c7763002838c02fb76 100644 (file)
@@ -338,7 +338,7 @@ struct mem_cgroup {
 static size_t memcg_size(void)
 {
        return sizeof(struct mem_cgroup) +
-               nr_node_ids * sizeof(struct mem_cgroup_per_node);
+               nr_node_ids * sizeof(struct mem_cgroup_per_node *);
 }
 
 /* internal only representation about the status of kmem accounting. */
@@ -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..fabe55046c1d7b9638172aa8e26ecb4f3d6ed4b9 100644 (file)
@@ -938,6 +938,16 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
                                BUG_ON(!PageHWPoison(p));
                                return SWAP_FAIL;
                        }
+                       /*
+                        * We pinned the head page for hwpoison handling,
+                        * now we split the thp and we are interested in
+                        * the hwpoisoned raw page, so move the refcount
+                        * to it.
+                        */
+                       if (hpage != p) {
+                               put_page(hpage);
+                               get_page(p);
+                       }
                        /* THP is split, so ppage should be the real poisoned page. */
                        ppage = p;
                }
@@ -1505,10 +1515,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 d480cd6fc475854259bdd51021d5125dbdfbe479..192e6eebe4f240e4a8ece7cc0e10e902ff29f308 100644 (file)
@@ -133,7 +133,10 @@ static void __munlock_isolation_failed(struct page *page)
 
 /**
  * munlock_vma_page - munlock a vma page
- * @page - page to be unlocked
+ * @page - page to be unlocked, either a normal page or THP page head
+ *
+ * returns the size of the page as a page mask (0 for normal page,
+ *         HPAGE_PMD_NR - 1 for THP head page)
  *
  * called from munlock()/munmap() path with page supposedly on the LRU.
  * When we munlock a page, because the vma where we found the page is being
@@ -148,21 +151,30 @@ static void __munlock_isolation_failed(struct page *page)
  */
 unsigned int munlock_vma_page(struct page *page)
 {
-       unsigned int page_mask = 0;
+       unsigned int nr_pages;
 
        BUG_ON(!PageLocked(page));
 
        if (TestClearPageMlocked(page)) {
-               unsigned int nr_pages = hpage_nr_pages(page);
+               nr_pages = hpage_nr_pages(page);
                mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
-               page_mask = nr_pages - 1;
                if (!isolate_lru_page(page))
                        __munlock_isolated_page(page);
                else
                        __munlock_isolation_failed(page);
+       } else {
+               nr_pages = hpage_nr_pages(page);
        }
 
-       return page_mask;
+       /*
+        * Regardless of the original PageMlocked flag, we determine nr_pages
+        * after touching the flag. This leaves a possible race with a THP page
+        * split, such that a whole THP page was munlocked, but nr_pages == 1.
+        * Returning a smaller mask due to that is OK, the worst that can
+        * happen is subsequent useless scanning of the former tail pages.
+        * The NR_MLOCK accounting can however become broken.
+        */
+       return nr_pages - 1;
 }
 
 /**
@@ -286,10 +298,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
 {
        int i;
        int nr = pagevec_count(pvec);
-       int delta_munlocked = -nr;
+       int delta_munlocked;
        struct pagevec pvec_putback;
        int pgrescued = 0;
 
+       pagevec_init(&pvec_putback, 0);
+
        /* Phase 1: page isolation */
        spin_lock_irq(&zone->lru_lock);
        for (i = 0; i < nr; i++) {
@@ -318,18 +332,21 @@ skip_munlock:
                        /*
                         * We won't be munlocking this page in the next phase
                         * but we still need to release the follow_page_mask()
-                        * pin.
+                        * pin. We cannot do it under lru_lock however. If it's
+                        * the last pin, __page_cache_release would deadlock.
                         */
+                       pagevec_add(&pvec_putback, pvec->pages[i]);
                        pvec->pages[i] = NULL;
-                       put_page(page);
-                       delta_munlocked++;
                }
        }
+       delta_munlocked = -nr + pagevec_count(&pvec_putback);
        __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
        spin_unlock_irq(&zone->lru_lock);
 
+       /* Now we can release pins of pages that we are not munlocking */
+       pagevec_release(&pvec_putback);
+
        /* Phase 2: page munlock */
-       pagevec_init(&pvec_putback, 0);
        for (i = 0; i < nr; i++) {
                struct page *page = pvec->pages[i];
 
@@ -440,7 +457,8 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
 
        while (start < end) {
                struct page *page = NULL;
-               unsigned int page_mask, page_increm;
+               unsigned int page_mask;
+               unsigned long page_increm;
                struct pagevec pvec;
                struct zone *zone;
                int zoneid;
@@ -490,7 +508,9 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
                                goto next;
                        }
                }
-               page_increm = 1 + (~(start >> PAGE_SHIFT) & page_mask);
+               /* It's a bug to munlock in the middle of a THP page */
+               VM_BUG_ON((start >> PAGE_SHIFT) & page_mask);
+               page_increm = 1 + page_mask;
                start += page_increm * PAGE_SIZE;
 next:
                cond_resched();
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 762896ebfcf505348a659c83d8720b48e8b58c86..47c908f1f626a4d4a2de96b9f4a648ad386d4357 100644 (file)
@@ -530,6 +530,23 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
+static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
+                                    unsigned short type,
+                                    const void *daddr, const void *saddr,
+                                    unsigned int len)
+{
+       struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+       struct net_device *real_dev = vlan->real_dev;
+
+       return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
+}
+
+static const struct header_ops vlan_passthru_header_ops = {
+       .create  = vlan_passthru_hard_header,
+       .rebuild = dev_rebuild_header,
+       .parse   = eth_header_parse,
+};
+
 static struct device_type vlan_type = {
        .name   = "vlan",
 };
@@ -573,7 +590,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->needed_headroom = real_dev->needed_headroom;
        if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
-               dev->header_ops      = real_dev->header_ops;
+               dev->header_ops      = &vlan_passthru_header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
        } else {
                dev->header_ops      = &vlan_header_ops;
index a2b480a908723a37d47d14bd76e63628518e6561..b9c8a6eedf4537e4216f09e65f71ef72a55d4ed3 100644 (file)
@@ -307,9 +307,9 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
-       batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
-       batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
-       batadv_ogm_packet->header.ttl = 2;
+       batadv_ogm_packet->packet_type = BATADV_IV_OGM;
+       batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
+       batadv_ogm_packet->ttl = 2;
        batadv_ogm_packet->flags = BATADV_NO_FLAGS;
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
@@ -346,7 +346,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
-       batadv_ogm_packet->header.ttl = BATADV_TTL;
+       batadv_ogm_packet->ttl = BATADV_TTL;
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -435,7 +435,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
                           fwd_str, (packet_num > 0 ? "aggregated " : ""),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->tq, batadv_ogm_packet->ttl,
                           (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
                            "on" : "off"),
                           hard_iface->net_dev->name,
@@ -491,7 +491,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
        /* multihomed peer assumed
         * non-primary OGMs are only broadcasted on their interface
         */
-       if ((directlink && (batadv_ogm_packet->header.ttl == 1)) ||
+       if ((directlink && (batadv_ogm_packet->ttl == 1)) ||
            (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
                /* FIXME: what about aggregated packets ? */
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -499,7 +499,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
                           (forw_packet->own ? "Sending own" : "Forwarding"),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->ttl,
                           forw_packet->if_incoming->net_dev->name,
                           forw_packet->if_incoming->net_dev->dev_addr);
 
@@ -572,7 +572,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 */
                if ((!directlink) &&
                    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
-                   (batadv_ogm_packet->header.ttl != 1) &&
+                   (batadv_ogm_packet->ttl != 1) &&
 
                    /* own packets originating non-primary
                     * interfaces leave only that interface
@@ -587,7 +587,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 * interface only - we still can aggregate
                 */
                if ((directlink) &&
-                   (new_bat_ogm_packet->header.ttl == 1) &&
+                   (new_bat_ogm_packet->ttl == 1) &&
                    (forw_packet->if_incoming == if_incoming) &&
 
                    /* packets from direct neighbors or
@@ -778,7 +778,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        uint16_t tvlv_len;
 
-       if (batadv_ogm_packet->header.ttl <= 1) {
+       if (batadv_ogm_packet->ttl <= 1) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
                return;
        }
@@ -798,7 +798,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
 
-       batadv_ogm_packet->header.ttl--;
+       batadv_ogm_packet->ttl--;
        memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
 
        /* apply hop penalty */
@@ -807,7 +807,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Forwarding packet: tq: %i, ttl: %i\n",
-                  batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl);
+                  batadv_ogm_packet->tq, batadv_ogm_packet->ttl);
 
        /* switch of primaries first hop flag when forwarding */
        batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
@@ -972,8 +972,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);
 
        if (dup_status == BATADV_NO_DUP) {
-               orig_node->last_ttl = batadv_ogm_packet->header.ttl;
-               neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
+               orig_node->last_ttl = batadv_ogm_packet->ttl;
+               neigh_node->last_ttl = batadv_ogm_packet->ttl;
        }
 
        batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
@@ -1247,7 +1247,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * packet in an aggregation.  Here we expect that the padding
         * is always zero (or not 0x01)
         */
-       if (batadv_ogm_packet->header.packet_type != BATADV_IV_OGM)
+       if (batadv_ogm_packet->packet_type != BATADV_IV_OGM)
                return;
 
        /* could be changed by schedule_own_packet() */
@@ -1267,8 +1267,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                   if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
                   batadv_ogm_packet->prev_sender,
                   ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
-                  batadv_ogm_packet->header.ttl,
-                  batadv_ogm_packet->header.version, has_directlink_flag);
+                  batadv_ogm_packet->ttl,
+                  batadv_ogm_packet->version, has_directlink_flag);
 
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -1433,7 +1433,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * seqno and similar ttl as the non-duplicate
         */
        sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
-       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl;
        if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
                            (sameseq && similar_ttl)))
                batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
index 6c8c3934bd7b44bac8643683683c494e003f1ed2..b316a4cb6f147dbbafadb51cdccf687cef500373 100644 (file)
@@ -349,7 +349,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       switch (unicast_4addr_packet->u.header.packet_type) {
+       switch (unicast_4addr_packet->u.packet_type) {
        case BATADV_UNICAST:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within a UNICAST packet\n");
@@ -374,7 +374,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
                        break;
                default:
                        batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
-                                  unicast_4addr_packet->u.header.packet_type);
+                                  unicast_4addr_packet->u.packet_type);
                }
                break;
        case BATADV_BCAST:
@@ -387,7 +387,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
        default:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within an unknown packet type (0x%x)\n",
-                          unicast_4addr_packet->u.header.packet_type);
+                          unicast_4addr_packet->u.packet_type);
        }
 }
 
index 271d321b3a04063b4f9dfe476c7c07d9e2e50048..6ddb6145ffb564be9397728e83a4040f071c4a96 100644 (file)
@@ -355,7 +355,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
                batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
                                   skb->len + ETH_HLEN);
 
-               packet->header.ttl--;
+               packet->ttl--;
                batadv_send_skb_packet(skb, neigh_node->if_incoming,
                                       neigh_node->addr);
                ret = true;
@@ -444,9 +444,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                goto out_err;
 
        /* Create one header to be copied to all fragments */
-       frag_header.header.packet_type = BATADV_UNICAST_FRAG;
-       frag_header.header.version = BATADV_COMPAT_VERSION;
-       frag_header.header.ttl = BATADV_TTL;
+       frag_header.packet_type = BATADV_UNICAST_FRAG;
+       frag_header.version = BATADV_COMPAT_VERSION;
+       frag_header.ttl = BATADV_TTL;
        frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
        frag_header.reserved = 0;
        frag_header.no = 0;
index 29ae4efe3543e4bfc6ff013b9c97628b9e395209..130cc3217e2b0fb091dccfad6a4f41d4b0c9dbc9 100644 (file)
@@ -194,7 +194,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
                goto free_skb;
        }
 
-       if (icmp_header->header.packet_type != BATADV_ICMP) {
+       if (icmp_header->packet_type != BATADV_ICMP) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
                len = -EINVAL;
@@ -243,9 +243,9 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 
        icmp_header->uid = socket_client->index;
 
-       if (icmp_header->header.version != BATADV_COMPAT_VERSION) {
+       if (icmp_header->version != BATADV_COMPAT_VERSION) {
                icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
-               icmp_header->header.version = BATADV_COMPAT_VERSION;
+               icmp_header->version = BATADV_COMPAT_VERSION;
                batadv_socket_add_packet(socket_client, icmp_header,
                                         packet_len);
                goto free_skb;
index c51a5e568f0a80c08beb4ded5b34b1aff8d5cfdf..1511f64a6ceaae34d26860cd4642cde71c5af9a0 100644 (file)
@@ -383,17 +383,17 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;
 
-       if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
+       if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: incompatible batman version (%i)\n",
-                          batadv_ogm_packet->header.version);
+                          batadv_ogm_packet->version);
                goto err_free;
        }
 
        /* all receive handlers return whether they received or reused
         * the supplied skb. if not, we have to free the skb.
         */
-       idx = batadv_ogm_packet->header.packet_type;
+       idx = batadv_ogm_packet->packet_type;
        ret = (*batadv_rx_handler[idx])(skb, hard_iface);
 
        if (ret == NET_RX_DROP)
@@ -426,8 +426,8 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
 
        /* broadcast packet */
        batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@ -1119,9 +1119,9 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
        skb_reserve(skb, ETH_HLEN);
        tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
        unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
-       unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
-       unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_tvlv_packet->header.ttl = BATADV_TTL;
+       unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
+       unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
+       unicast_tvlv_packet->ttl = BATADV_TTL;
        unicast_tvlv_packet->reserved = 0;
        unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
        unicast_tvlv_packet->align = 0;
index 351e199bc0afff37aa9c1a4b3f40201956dfde91..511d7e1eea38b6d6e13247df0f8d4399deea8382 100644 (file)
@@ -722,7 +722,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
 {
        if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
                return false;
-       if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
+       if (orig_node->last_ttl != ogm_packet->ttl + 1)
                return false;
        if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
                return false;
@@ -1082,9 +1082,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        coded_packet = (struct batadv_coded_packet *)skb_dest->data;
        skb_reset_mac_header(skb_dest);
 
-       coded_packet->header.packet_type = BATADV_CODED;
-       coded_packet->header.version = BATADV_COMPAT_VERSION;
-       coded_packet->header.ttl = packet1->header.ttl;
+       coded_packet->packet_type = BATADV_CODED;
+       coded_packet->version = BATADV_COMPAT_VERSION;
+       coded_packet->ttl = packet1->ttl;
 
        /* Info about first unicast packet */
        memcpy(coded_packet->first_source, first_source, ETH_ALEN);
@@ -1097,7 +1097,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        memcpy(coded_packet->second_source, second_source, ETH_ALEN);
        memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
        coded_packet->second_crc = packet_id2;
-       coded_packet->second_ttl = packet2->header.ttl;
+       coded_packet->second_ttl = packet2->ttl;
        coded_packet->second_ttvn = packet2->ttvn;
        coded_packet->coded_len = htons(coding_len);
 
@@ -1452,7 +1452,7 @@ bool batadv_nc_skb_forward(struct sk_buff *skb,
        /* We only handle unicast packets */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Try to find a coding opportunity and send the skb if one is found */
@@ -1505,7 +1505,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
        /* Check for supported packet type */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Find existing nc_path or create a new */
@@ -1623,7 +1623,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
                ttvn = coded_packet_tmp.second_ttvn;
        } else {
                orig_dest = coded_packet_tmp.first_orig_dest;
-               ttl = coded_packet_tmp.header.ttl;
+               ttl = coded_packet_tmp.ttl;
                ttvn = coded_packet_tmp.first_ttvn;
        }
 
@@ -1648,9 +1648,9 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        /* Create decoded unicast packet */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.packet_type = BATADV_UNICAST;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_packet->header.ttl = ttl;
+       unicast_packet->packet_type = BATADV_UNICAST;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
+       unicast_packet->ttl = ttl;
        memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
        unicast_packet->ttvn = ttvn;
 
index 207459b62966d0975bca70894fcf5ce266a5da29..2dd8f2422550c3157112eb4ce5a27362e6caf8fb 100644 (file)
@@ -155,6 +155,7 @@ enum batadv_tvlv_type {
        BATADV_TVLV_ROAM        = 0x05,
 };
 
+#pragma pack(2)
 /* the destination hardware field in the ARP frame is used to
  * transport the claim type and the group id
  */
@@ -163,24 +164,20 @@ struct batadv_bla_claim_dst {
        uint8_t type;           /* bla_claimframe */
        __be16 group;           /* group id */
 };
-
-struct batadv_header {
-       uint8_t  packet_type;
-       uint8_t  version;  /* batman version field */
-       uint8_t  ttl;
-       /* the parent struct has to add a byte after the header to make
-        * everything 4 bytes aligned again
-        */
-};
+#pragma pack()
 
 /**
  * struct batadv_ogm_packet - ogm (routing protocol) packet
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @flags: contains routing relevant flags - see enum batadv_iv_flags
  * @tvlv_len: length of tvlv data following the ogm header
  */
 struct batadv_ogm_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  flags;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -196,29 +193,51 @@ struct batadv_ogm_packet {
 #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
 
 /**
- * batadv_icmp_header - common ICMP header
- * @header: common batman header
+ * batadv_icmp_header - common members among all the ICMP packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @msg_type: ICMP packet type
  * @dst: address of the destination node
  * @orig: address of the source node
  * @uid: local ICMP socket identifier
+ * @align: not used - useful for alignment purposes only
+ *
+ * This structure is used for ICMP packets parsing only and it is never sent
+ * over the wire. The alignment field at the end is there to ensure that
+ * members are padded the same way as they are in real packets.
  */
 struct batadv_icmp_header {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  msg_type; /* see ICMP message types above */
        uint8_t  dst[ETH_ALEN];
        uint8_t  orig[ETH_ALEN];
        uint8_t  uid;
+       uint8_t  align[3];
 };
 
 /**
  * batadv_icmp_packet - ICMP packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @reserved: not used - useful for alignment
  * @seqno: ICMP sequence number
  */
 struct batadv_icmp_packet {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  reserved;
        __be16   seqno;
 };
@@ -227,13 +246,25 @@ struct batadv_icmp_packet {
 
 /**
  * batadv_icmp_packet_rr - ICMP RouteRecord packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @rr_cur: number of entries the rr array
  * @seqno: ICMP sequence number
  * @rr: route record array
  */
 struct batadv_icmp_packet_rr {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  rr_cur;
        __be16   seqno;
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
@@ -253,8 +284,18 @@ struct batadv_icmp_packet_rr {
  */
 #pragma pack(2)
 
+/**
+ * struct batadv_unicast_packet - unicast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @ttvn: translation table version number
+ * @dest: originator destination of the unicast packet
+ */
 struct batadv_unicast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  ttvn; /* destination translation table version number */
        uint8_t  dest[ETH_ALEN];
        /* "4 bytes boundary + 2 bytes" long to make the payload after the
@@ -280,7 +321,9 @@ struct batadv_unicast_4addr_packet {
 
 /**
  * struct batadv_frag_packet - fragmented packet
- * @header: common batman packet header with type, compatversion, and ttl
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @dest: final destination used when routing fragments
  * @orig: originator of the fragment used when merging the packet
  * @no: fragment number within this sequence
@@ -289,7 +332,9 @@ struct batadv_unicast_4addr_packet {
  * @total_size: size of the merged packet
  */
 struct batadv_frag_packet {
-       struct  batadv_header header;
+       uint8_t packet_type;
+       uint8_t version;  /* batman version field */
+       uint8_t ttl;
 #if defined(__BIG_ENDIAN_BITFIELD)
        uint8_t no:4;
        uint8_t reserved:4;
@@ -305,8 +350,19 @@ struct batadv_frag_packet {
        __be16  total_size;
 };
 
+/**
+ * struct batadv_bcast_packet - broadcast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @reserved: reserved byte for alignment
+ * @seqno: sequence identification
+ * @orig: originator of the broadcast packet
+ */
 struct batadv_bcast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -315,11 +371,11 @@ struct batadv_bcast_packet {
         */
 };
 
-#pragma pack()
-
 /**
  * struct batadv_coded_packet - network coded packet
- * @header: common batman packet header and ttl of first included packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: Align following fields to 2-byte boundaries
  * @first_source: original source of first included packet
  * @first_orig_dest: original destinal of first included packet
@@ -334,7 +390,9 @@ struct batadv_bcast_packet {
  * @coded_len: length of network coded part of the payload
  */
 struct batadv_coded_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  first_ttvn;
        /* uint8_t  first_dest[ETH_ALEN]; - saved in mac header destination */
        uint8_t  first_source[ETH_ALEN];
@@ -349,9 +407,13 @@ struct batadv_coded_packet {
        __be16   coded_len;
 };
 
+#pragma pack()
+
 /**
  * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: reserved field (for packet alignment)
  * @src: address of the source
  * @dst: address of the destination
@@ -359,7 +421,9 @@ struct batadv_coded_packet {
  * @align: 2 bytes to align the header to a 4 byte boundry
  */
 struct batadv_unicast_tvlv_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        uint8_t  dst[ETH_ALEN];
        uint8_t  src[ETH_ALEN];
@@ -420,13 +484,13 @@ struct batadv_tvlv_tt_vlan_data {
  * struct batadv_tvlv_tt_change - translation table diff data
  * @flags: status indicators concerning the non-mesh client (see
  *  batadv_tt_client_flags)
- * @reserved: reserved field
+ * @reserved: reserved field - useful for alignment purposes only
  * @addr: mac address of non-mesh client that triggered this tt change
  * @vid: VLAN identifier
  */
 struct batadv_tvlv_tt_change {
        uint8_t flags;
-       uint8_t reserved;
+       uint8_t reserved[3];
        uint8_t addr[ETH_ALEN];
        __be16 vid;
 };
index d4114d775ad61f659b59437c67aa7054d9a88f92..46278bfb8fdb9469e12f8fbdc8922e49f81f8014 100644 (file)
@@ -308,7 +308,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
                memcpy(icmph->dst, icmph->orig, ETH_ALEN);
                memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
                icmph->msg_type = BATADV_ECHO_REPLY;
-               icmph->header.ttl = BATADV_TTL;
+               icmph->ttl = BATADV_TTL;
 
                res = batadv_send_skb_to_orig(skb, orig_node, NULL);
                if (res != NET_XMIT_DROP)
@@ -338,9 +338,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
        /* send TTL exceeded if packet is an echo request (traceroute) */
-       if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
+       if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
                pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
-                        icmp_packet->icmph.orig, icmp_packet->icmph.dst);
+                        icmp_packet->orig, icmp_packet->dst);
                goto out;
        }
 
@@ -349,7 +349,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
                goto out;
 
        /* get routing information */
-       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
+       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
        if (!orig_node)
                goto out;
 
@@ -359,11 +359,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
-       memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
-       memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+       memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+       memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr,
               ETH_ALEN);
-       icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
-       icmp_packet->icmph.header.ttl = BATADV_TTL;
+       icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
+       icmp_packet->ttl = BATADV_TTL;
 
        if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
@@ -434,7 +434,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
                return batadv_recv_my_icmp_packet(bat_priv, skb);
 
        /* TTL exceeded */
-       if (icmph->header.ttl < 2)
+       if (icmph->ttl < 2)
                return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
 
        /* get routing information */
@@ -449,7 +449,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmph = (struct batadv_icmp_header *)skb->data;
 
        /* decrement ttl */
-       icmph->header.ttl--;
+       icmph->ttl--;
 
        /* route it */
        if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -709,7 +709,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* TTL exceeded */
-       if (unicast_packet->header.ttl < 2) {
+       if (unicast_packet->ttl < 2) {
                pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
                         ethhdr->h_source, unicast_packet->dest);
                goto out;
@@ -727,9 +727,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 
        /* decrement ttl */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.ttl--;
+       unicast_packet->ttl--;
 
-       switch (unicast_packet->header.packet_type) {
+       switch (unicast_packet->packet_type) {
        case BATADV_UNICAST_4ADDR:
                hdr_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
@@ -970,7 +970,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+       is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
        /* the caller function should have already pulled 2 bytes */
        if (is4addr)
                hdr_size = sizeof(*unicast_4addr_packet);
@@ -1160,7 +1160,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
                goto out;
 
-       if (bcast_packet->header.ttl < 2)
+       if (bcast_packet->ttl < 2)
                goto out;
 
        orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
index c83be5ebaa285dffe64d051850e87f2fca02624b..fba4dcfcfac21b6e9c6686c30fc6ca8a1a08f3fa 100644 (file)
@@ -161,11 +161,11 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
                return false;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
        /* batman packet type: unicast */
-       unicast_packet->header.packet_type = BATADV_UNICAST;
+       unicast_packet->packet_type = BATADV_UNICAST;
        /* set unicast ttl */
-       unicast_packet->header.ttl = BATADV_TTL;
+       unicast_packet->ttl = BATADV_TTL;
        /* copy the destination for faster routing */
        memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
        /* set the destination tt version number */
@@ -221,7 +221,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
                goto out;
 
        uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
-       uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+       uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
        memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
        uc_4addr_packet->subtype = packet_subtype;
        uc_4addr_packet->reserved = 0;
@@ -436,7 +436,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
 
        /* as we have a copy now, it is safe to decrease the TTL */
        bcast_packet = (struct batadv_bcast_packet *)newskb->data;
-       bcast_packet->header.ttl--;
+       bcast_packet->ttl--;
 
        skb_reset_mac_header(newskb);
 
index 36f050876f8260245a008de079cf0974fa97b76e..a8f99d1486c0441e9aa192e81d7522ad451f4bd7 100644 (file)
@@ -264,11 +264,11 @@ static int batadv_interface_tx(struct sk_buff *skb,
                        goto dropped;
 
                bcast_packet = (struct batadv_bcast_packet *)skb->data;
-               bcast_packet->header.version = BATADV_COMPAT_VERSION;
-               bcast_packet->header.ttl = BATADV_TTL;
+               bcast_packet->version = BATADV_COMPAT_VERSION;
+               bcast_packet->ttl = BATADV_TTL;
 
                /* batman packet type: broadcast */
-               bcast_packet->header.packet_type = BATADV_BCAST;
+               bcast_packet->packet_type = BATADV_BCAST;
                bcast_packet->reserved = 0;
 
                /* hw address of first interface is the orig mac because only
@@ -328,7 +328,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
                         struct sk_buff *skb, struct batadv_hard_iface *recv_if,
                         int hdr_size, struct batadv_orig_node *orig_node)
 {
-       struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
+       struct batadv_bcast_packet *batadv_bcast_packet;
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        __be16 ethertype = htons(ETH_P_BATMAN);
        struct vlan_ethhdr *vhdr;
@@ -336,7 +336,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
        unsigned short vid;
        bool is_bcast;
 
-       is_bcast = (batadv_header->packet_type == BATADV_BCAST);
+       batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
 
        /* check if enough space is available for pulling, and pull */
        if (!pskb_may_pull(skb, hdr_size))
@@ -345,7 +346,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
-       vid = batadv_get_vid(skb, hdr_size);
+       /* clean the netfilter state now that the batman-adv header has been
+        * removed
+        */
+       nf_reset(skb);
+
+       vid = batadv_get_vid(skb, 0);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
index 4add57d4857f11e5ea9edfa13aae1f46dab3e4f9..ff625fedbc5eeb08a7569c01973f5eb1ddc71eb1 100644 (file)
@@ -333,7 +333,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
                return;
 
        tt_change_node->change.flags = flags;
-       tt_change_node->change.reserved = 0;
+       memset(tt_change_node->change.reserved, 0,
+              sizeof(tt_change_node->change.reserved));
        memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
        tt_change_node->change.vid = htons(common->vid);
 
@@ -2221,7 +2222,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
                               ETH_ALEN);
                        tt_change->flags = tt_common_entry->flags;
                        tt_change->vid = htons(tt_common_entry->vid);
-                       tt_change->reserved = 0;
+                       memset(tt_change->reserved, 0,
+                              sizeof(tt_change->reserved));
 
                        tt_num_entries++;
                        tt_change++;
index 6a6c8bb4fd72d4f2d4294b9f7fed772d81e57b93..7552f9e3089ce790040268f1ce0a067d6ef728cb 100644 (file)
@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
        skb_pull(skb, 1);
 
-       if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
-           bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+       if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+               /* No permission check is needed for user channel
+                * since that gets enforced when binding the socket.
+                *
+                * However check that the packet type is valid.
+                */
+               if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
+                       err = -EINVAL;
+                       goto drop;
+               }
+
+               skb_queue_tail(&hdev->raw_q, skb);
+               queue_work(hdev->workqueue, &hdev->tx_work);
+       } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
                u16 opcode = get_unaligned_le16(skb->data);
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                        goto drop;
                }
 
-               if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
-                   bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
-                       err = -EINVAL;
-                       goto drop;
-               }
-
                skb_queue_tail(&hdev->raw_q, skb);
                queue_work(hdev->workqueue, &hdev->tx_work);
        }
index 4c214b2b88efa01d81be93a8b8d77e57229c1fa4..ef66365b7354da9f2fe2c4d87d2056d9a781f3c8 100644 (file)
@@ -1998,7 +1998,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (!netif_running(br->dev))
                goto unlock;
 
@@ -2030,7 +2030,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
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 ba3b7ea5ebb3139cca38e82ac6f5f5e346f4a4e0..0ce469e5ec8057c674901b404db13061fe8b7392 100644 (file)
@@ -2539,7 +2539,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
 }
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv)
+                       struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
        int rc = NETDEV_TX_OK;
@@ -2605,13 +2605,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        dev_queue_xmit_nit(skb, dev);
 
                skb_len = skb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
-               else
                        rc = ops->ndo_start_xmit(skb, dev);
 
                trace_net_dev_xmit(skb, rc, dev, skb_len);
-               if (rc == NETDEV_TX_OK && txq)
+               if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
        }
@@ -2627,10 +2624,7 @@ gso:
                        dev_queue_xmit_nit(nskb, dev);
 
                skb_len = nskb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
-               else
-                       rc = ops->ndo_start_xmit(nskb, dev);
+               rc = ops->ndo_start_xmit(nskb, dev);
                trace_net_dev_xmit(nskb, rc, dev, skb_len);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
@@ -2811,7 +2805,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);
  *      the BH enable code must have IRQs enabled so that it will not deadlock.
  *          --BLG
  */
-int dev_queue_xmit(struct sk_buff *skb)
+int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 {
        struct net_device *dev = skb->dev;
        struct netdev_queue *txq;
@@ -2827,7 +2821,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
        skb_update_prio(skb);
 
-       txq = netdev_pick_tx(dev, skb);
+       txq = netdev_pick_tx(dev, skb, accel_priv);
        q = rcu_dereference_bh(txq->qdisc);
 
 #ifdef CONFIG_NET_CLS_ACT
@@ -2863,7 +2857,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                        if (!netif_xmit_stopped(txq)) {
                                __this_cpu_inc(xmit_recursion);
-                               rc = dev_hard_start_xmit(skb, dev, txq, NULL);
+                               rc = dev_hard_start_xmit(skb, dev, txq);
                                __this_cpu_dec(xmit_recursion);
                                if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
@@ -2892,8 +2886,19 @@ out:
        rcu_read_unlock_bh();
        return rc;
 }
+
+int dev_queue_xmit(struct sk_buff *skb)
+{
+       return __dev_queue_xmit(skb, NULL);
+}
 EXPORT_SYMBOL(dev_queue_xmit);
 
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
+{
+       return __dev_queue_xmit(skb, accel_priv);
+}
+EXPORT_SYMBOL(dev_queue_xmit_accel);
+
 
 /*=======================================================================
                        Receiver routines
@@ -4500,7 +4505,7 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 {
        struct netdev_adjacent *upper;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
 
        upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
 
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 d6ef173225008ec1946ed232f781cc63754b9575..2fc5beaf578349cd543621a460bf2bb4eaa9d221 100644 (file)
@@ -395,17 +395,21 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb)
+                                   struct sk_buff *skb,
+                                   void *accel_priv)
 {
        int queue_index = 0;
 
        if (dev->real_num_tx_queues != 1) {
                const struct net_device_ops *ops = dev->netdev_ops;
                if (ops->ndo_select_queue)
-                       queue_index = ops->ndo_select_queue(dev, skb);
+                       queue_index = ops->ndo_select_queue(dev, skb,
+                                                           accel_priv);
                else
                        queue_index = __netdev_pick_tx(dev, skb);
-               queue_index = dev_cap_txqueue(dev, queue_index);
+
+               if (!accel_priv)
+                       queue_index = dev_cap_txqueue(dev, queue_index);
        }
 
        skb_set_queue_mapping(skb, queue_index);
index ca15f32821fb8d536586354108488050b7cc6a0e..932c6d7cf6668e073a90432281037b51cf7dfecc 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) {
@@ -1274,7 +1275,7 @@ int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
 
        if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
                            skb->len) < 0 &&
-           dev->header_ops->rebuild(skb))
+           dev_rebuild_header(skb))
                return 0;
 
        return dev_queue_xmit(skb);
index 8f971990677cd48026f651b2dba01d01190bfff6..19fe9c717cedb56051ff6cb5effca0274fd946d8 100644 (file)
@@ -375,7 +375,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
        if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {
                struct netdev_queue *txq;
 
-               txq = netdev_pick_tx(dev, skb);
+               txq = netdev_pick_tx(dev, skb, NULL);
 
                /* try until next clock tick */
                for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                            !vlan_hw_offload_capable(netif_skb_features(skb),
                                                                     skb->vlan_proto)) {
                                                skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb));
-                                               if (unlikely(!skb))
-                                                       break;
+                                               if (unlikely(!skb)) {
+                                                       /* This is actually a packet drop, but we
+                                                        * don't want the code at the end of this
+                                                        * function to try and re-queue a NULL skb.
+                                                        */
+                                                       status = NETDEV_TX_OK;
+                                                       goto unlock_txq;
+                                               }
                                                skb->vlan_tci = 0;
                                        }
 
@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                        if (status == NETDEV_TX_OK)
                                                txq_trans_update(txq);
                                }
+                       unlock_txq:
                                __netif_tx_unlock(txq);
 
                                if (status == NETDEV_TX_OK)
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 4c6bdf97a6577d190332b85654769a92ce553111..595ddf0459db79c724b8eab2c8b0f6a0a7d1df97 100644 (file)
@@ -152,17 +152,6 @@ static const struct file_operations dccpprobe_fops = {
        .llseek  = noop_llseek,
 };
 
-static __init int setup_jprobe(void)
-{
-       int ret = register_jprobe(&dccp_send_probe);
-
-       if (ret) {
-               request_module("dccp");
-               ret = register_jprobe(&dccp_send_probe);
-       }
-       return ret;
-}
-
 static __init int dccpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -174,7 +163,13 @@ static __init int dccpprobe_init(void)
        if (!proc_create(procname, S_IRUSR, init_net.proc_net, &dccpprobe_fops))
                goto err0;
 
-       ret = setup_jprobe();
+       ret = register_jprobe(&dccp_send_probe);
+       if (ret) {
+               ret = request_module("dccp");
+               if (!ret)
+                       ret = register_jprobe(&dccp_send_probe);
+       }
+
        if (ret)
                goto err1;
 
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 459e200c08a40e4e737798582524cd973064b143..a2d2456a557a7621059a5b0bbe033168492f8fe7 100644 (file)
@@ -547,7 +547,7 @@ static int lowpan_header_create(struct sk_buff *skb,
                        hc06_ptr += 3;
                } else {
                        /* compress nothing */
-                       memcpy(hc06_ptr, &hdr, 4);
+                       memcpy(hc06_ptr, hdr, 4);
                        /* replace the top byte with new ECN | DSCP format */
                        *hc06_ptr = tmp;
                        hc06_ptr += 4;
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 e5d436188464eba55eca773f4fb88fd0f0634e97..2cd02f32f99f568c8275389aefd754700a77efa6 100644 (file)
@@ -28,6 +28,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        netdev_features_t enc_features;
        int ghl = GRE_HEADER_SECTION;
        struct gre_base_hdr *greh;
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        __be16 protocol = skb->protocol;
        int tnl_hlen;
@@ -58,13 +59,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        } else
                csum = false;
 
+       if (unlikely(!pskb_may_pull(skb, ghl)))
+               goto out;
+
        /* setup inner skb. */
        skb->protocol = greh->protocol;
        skb->encapsulation = 0;
 
-       if (unlikely(!pskb_may_pull(skb, ghl)))
-               goto out;
-
        __skb_pull(skb, ghl);
        skb_reset_mac_header(skb);
        skb_set_network_header(skb, skb_inner_network_offset(skb));
@@ -73,8 +74,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
                goto out;
+       }
 
        skb = segs;
        tnl_hlen = skb_tnl_header_len(skb);
index 56a964a553d2c739a03b880acd7158a4c9714b66..a0f52dac8940de45ffaa53291c82950b2e6c4c99 100644 (file)
@@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = inet->inet_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
@@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 
        r->idiag_family       = tw->tw_family;
        r->idiag_retrans      = 0;
+
        r->id.idiag_if        = tw->tw_bound_dev_if;
        sock_diag_save_cookie(tw, r->id.idiag_cookie);
+
        r->id.idiag_sport     = tw->tw_sport;
        r->id.idiag_dport     = tw->tw_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0]    = tw->tw_rcv_saddr;
        r->id.idiag_dst[0]    = tw->tw_daddr;
+
        r->idiag_state        = tw->tw_substate;
        r->idiag_timer        = 3;
        r->idiag_expires      = jiffies_to_msecs(tmo);
@@ -726,8 +737,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = ireq->ir_rmt_port;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = ireq->ir_loc_addr;
        r->id.idiag_dst[0] = ireq->ir_rmt_addr;
+
        r->idiag_expires = jiffies_to_msecs(tmo);
        r->idiag_rqueue = 0;
        r->idiag_wqueue = 0;
index d7aea4c5b9400efec37d15db3c5a896769d0da68..e560ef34cf4bd2efe9f1f7a64424441117a4502a 100644 (file)
@@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
                                  iph->saddr, iph->daddr, tpi->key);
 
        if (tunnel) {
+               skb_pop_mac_header(skb);
                ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error);
                return PACKET_RCVD;
        }
index 912402752f2ffce701d697de1bb7a32b05c3b482..df184616493f707ea8a0ea353a33d3a5aa981fc7 100644 (file)
@@ -828,7 +828,7 @@ static int __ip_append_data(struct sock *sk,
 
        if (cork->length + length > maxnonfragsize - fragheaderlen) {
                ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
-                              mtu-exthdrlen);
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
@@ -1151,7 +1151,8 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                         mtu : 0xFFFF;
 
        if (cork->length + size > maxnonfragsize - fragheaderlen) {
-               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu);
+               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
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..a7e4729e974b3206f57e3b3da4026a77432768e1 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,
@@ -2471,6 +2478,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
        __be16 protocol = skb->protocol;
@@ -2490,8 +2498,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
+                                    mac_len);
                goto out;
+       }
 
        outer_hlen = skb_tnl_header_len(skb);
        skb = segs;
index 83206de2bc7679dc20e4fdcf34f8b1f5cd7831ef..79c62bdcd3c549b7dc07c74449d30b77296134eb 100644 (file)
@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
+       int offset;
+       __wsum csum;
+
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) {
+               segs = skb_udp_tunnel_segment(skb, features);
+               goto out;
+       }
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
                goto out;
        }
 
+       /* Do software UFO. Complete and fill in the UDP checksum as
+        * HW cannot do checksum of UDP packets sent as multiple
+        * IP fragments.
+        */
+       offset = skb_checksum_start_offset(skb);
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+       offset += skb->csum_offset;
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+       skb->ip_summed = CHECKSUM_NONE;
+
        /* Fragment the skb. IP headers of the fragments are updated in
         * inet_gso_segment()
         */
-       if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
-               segs = skb_udp_tunnel_segment(skb, features);
-       else {
-               int offset;
-               __wsum csum;
-
-               /* Do software UFO. Complete and fill in the UDP checksum as
-                * HW cannot do checksum of UDP packets sent as multiple
-                * IP fragments.
-                */
-               offset = skb_checksum_start_offset(skb);
-               csum = skb_checksum(skb, offset, skb->len - offset, 0);
-               offset += skb->csum_offset;
-               *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-               skb->ip_summed = CHECKSUM_NONE;
-
-               segs = skb_segment(skb, features);
-       }
+       segs = skb_segment(skb, features);
 out:
        return segs;
 }
index 12c97d8aa6bbb31ff1519459b89b7b9fb33817f5..abe46a4228ce96655d1aacec77052a89e70cfdd4 100644 (file)
@@ -1671,7 +1671,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -1682,7 +1682,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -2509,7 +2509,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        struct inet6_ifaddr *ifp;
 
        ifp = ipv6_add_addr(idev, addr, NULL, plen,
-                           scope, IFA_F_PERMANENT, 0, 0);
+                           scope, IFA_F_PERMANENT,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                spin_lock_bh(&ifp->lock);
                ifp->flags &= ~IFA_F_TENTATIVE;
@@ -2613,7 +2614,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)) {
@@ -2637,7 +2638,8 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr
 #endif
 
 
-       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, 0, 0);
+       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
                addrconf_dad_start(ifp);
@@ -3456,7 +3458,12 @@ restart:
                                         &inet6_addr_lst[i], addr_lst) {
                        unsigned long age;
 
-                       if (ifp->flags & IFA_F_PERMANENT)
+                       /* When setting preferred_lft to a value not zero or
+                        * infinity, while valid_lft is infinity
+                        * IFA_F_PERMANENT has a non-infinity life time.
+                        */
+                       if ((ifp->flags & IFA_F_PERMANENT) &&
+                           (ifp->prefered_lft == INFINITY_LIFE_TIME))
                                continue;
 
                        spin_lock(&ifp->lock);
@@ -3481,7 +3488,8 @@ restart:
                                        ifp->flags |= IFA_F_DEPRECATED;
                                }
 
-                               if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
+                               if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
+                                   (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
                                        next = ifp->tstamp + ifp->valid_lft * HZ;
 
                                spin_unlock(&ifp->lock);
@@ -3761,7 +3769,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
                      ifa->idev->dev->ifindex);
 
-       if (!(ifa->flags&IFA_F_PERMANENT)) {
+       if (!((ifa->flags&IFA_F_PERMANENT) &&
+             (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
                preferred = ifa->prefered_lft;
                valid = ifa->valid_lft;
                if (preferred != INFINITY_LIFE_TIME) {
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..e6f931997996ef46efa1272b16e261bf8f6609a7 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;
 }
@@ -1193,11 +1193,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
        fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
                        (opt ? opt->opt_nflen : 0);
-       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
+       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
+                    sizeof(struct frag_hdr);
 
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
-               if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
-                       ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
+               unsigned int maxnonfragsize, headersize;
+
+               headersize = sizeof(struct ipv6hdr) +
+                            (opt ? opt->tot_len : 0) +
+                            (dst_allfrag(&rt->dst) ?
+                             sizeof(struct frag_hdr) : 0) +
+                            rt->rt6i_nfheader_len;
+
+               maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ?
+                                mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN;
+
+               /* dontfrag active */
+               if ((cork->length + length > mtu - headersize) && dontfrag &&
+                   (sk->sk_protocol == IPPROTO_UDP ||
+                    sk->sk_protocol == IPPROTO_RAW)) {
+                       ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
+                                                  sizeof(struct ipv6hdr));
+                       goto emsgsize;
+               }
+
+               if (cork->length + length > maxnonfragsize - headersize) {
+emsgsize:
+                       ipv6_local_error(sk, EMSGSIZE, fl6,
+                                        mtu - headersize +
+                                        sizeof(struct ipv6hdr));
                        return -EMSGSIZE;
                }
        }
@@ -1222,12 +1246,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         * --yoshfuji
         */
 
-       if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
-                                          sk->sk_protocol == IPPROTO_RAW)) {
-               ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-               return -EMSGSIZE;
-       }
-
        skb = skb_peek_tail(&sk->sk_write_queue);
        cork->length += length;
        if (((length > mtu) ||
index d6062325db08411207fd63b435ec1e5e4e0f2001..7881965a824840a763a7e1183efcf21153f87b47 100644 (file)
@@ -103,16 +103,25 @@ struct ip6_tnl_net {
 
 static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 {
-       struct pcpu_tstats sum = { 0 };
+       struct pcpu_tstats tmp, sum = { 0 };
        int i;
 
        for_each_possible_cpu(i) {
+               unsigned int start;
                const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
 
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
+               do {
+                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
+                       tmp.rx_packets = tstats->rx_packets;
+                       tmp.rx_bytes = tstats->rx_bytes;
+                       tmp.tx_packets = tstats->tx_packets;
+                       tmp.tx_bytes =  tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+               sum.rx_packets += tmp.rx_packets;
+               sum.rx_bytes   += tmp.rx_bytes;
+               sum.tx_packets += tmp.tx_packets;
+               sum.tx_bytes   += tmp.tx_bytes;
        }
        dev->stats.rx_packets = sum.rx_packets;
        dev->stats.rx_bytes   = sum.rx_bytes;
@@ -824,8 +833,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
index ed94ba61dda0ec1c3e2b170fe74eb2334b752700..7b42d5ef868deaa193094a85a00b502aeaba0bdd 100644 (file)
@@ -75,26 +75,6 @@ struct vti6_net {
        struct ip6_tnl __rcu **tnls[2];
 };
 
-static struct net_device_stats *vti6_get_stats(struct net_device *dev)
-{
-       struct pcpu_tstats sum = { 0 };
-       int i;
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
-       }
-       dev->stats.rx_packets = sum.rx_packets;
-       dev->stats.rx_bytes   = sum.rx_bytes;
-       dev->stats.tx_packets = sum.tx_packets;
-       dev->stats.tx_bytes   = sum.tx_bytes;
-       return &dev->stats;
-}
-
 #define for_each_vti6_tunnel_rcu(start) \
        for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
@@ -331,8 +311,10 @@ static int vti6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                skb->mark = 0;
                secpath_reset(skb);
@@ -716,7 +698,7 @@ static const struct net_device_ops vti6_netdev_ops = {
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
        .ndo_change_mtu = vti6_change_mtu,
-       .ndo_get_stats  = vti6_get_stats,
+       .ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 /**
@@ -750,12 +732,18 @@ static void vti6_dev_setup(struct net_device *dev)
 static inline int vti6_dev_init_gen(struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
+       int i;
 
        t->dev = dev;
        t->net = dev_net(dev);
        dev->tstats = alloc_percpu(struct pcpu_tstats);
        if (!dev->tstats)
                return -ENOMEM;
+       for_each_possible_cpu(i) {
+               struct pcpu_tstats *stats;
+               stats = per_cpu_ptr(dev->tstats, i);
+               u64_stats_init(&stats->syncp);
+       }
        return 0;
 }
 
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..4b4944c3e4c4473c8b1ca4fbce8700a8af988604 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;
@@ -1903,9 +1905,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                else
                        rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
-               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
-                   (RTF_DEFAULT | RTF_ADDRCONF))
-                       rt6_set_from(rt, ort);
+               rt6_set_from(rt, ort);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -2144,8 +2144,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 +2155,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 +2164,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..d3005b34476a82f8172cfe8807507d561d307938 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;
 
@@ -670,8 +702,10 @@ static int ipip6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
@@ -892,7 +926,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (tunnel->parms.iph.daddr && skb_dst(skb))
                        skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
 
-               if (skb->len > mtu) {
+               if (skb->len > mtu && !skb_is_gso(skb)) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
@@ -919,7 +953,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)
@@ -934,8 +968,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 
        skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
-       if (IS_ERR(skb))
+       if (IS_ERR(skb)) {
+               ip_rt_put(rt);
                goto out;
+       }
 
        err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
                            ttl, df, !net_eq(tunnel->net, dev_net(dev)));
@@ -945,7 +981,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 +1021,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 7b01b9f5846c845bcf4f04b21cfbcb5786c19421..c71b699eb555165e124ec21109e37212587c7741 100644 (file)
@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        unsigned long cpu_flags;
        size_t copied = 0;
        u32 peek_seq = 0;
-       u32 *seq;
+       u32 *seq, skb_len;
        unsigned long used;
        int target;     /* Read at least this many bytes */
        long timeo;
@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
                continue;
        found_ok_skb:
+               skb_len = skb->len;
                /* Ok so how much can we use? */
                used = skb->len - offset;
                if (len < used)
@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                /* Partial read */
-               if (used + offset < skb->len)
+               if (used + offset < skb_len)
                        continue;
        } while (len > 0);
 
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..a0757913046eab8eee0c99104d8900db4e338c3e 100644 (file)
@@ -1061,7 +1061,8 @@ static void ieee80211_uninit(struct net_device *dev)
 }
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
-                                        struct sk_buff *skb)
+                                        struct sk_buff *skb,
+                                        void *accel_priv)
 {
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1078,7 +1079,8 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 };
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
-                                         struct sk_buff *skb)
+                                         struct sk_buff *skb,
+                                         void *accel_priv)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
@@ -1325,7 +1327,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 c558b246ef0036c38e6c8a00b338b43c46913f78..ca7fa7f0613dba22cdc0e82d8a96e1de9ff011dc 100644 (file)
@@ -463,7 +463,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 {
        struct sta_info *sta = tx->sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
        if (unlikely(!sta))
@@ -474,15 +473,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
-               /* only deauth, disassoc and action are bufferable MMPDUs */
-               if (ieee80211_is_mgmt(hdr->frame_control) &&
-                   !ieee80211_is_deauth(hdr->frame_control) &&
-                   !ieee80211_is_disassoc(hdr->frame_control) &&
-                   !ieee80211_is_action(hdr->frame_control)) {
-                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
-                       return TX_CONTINUE;
-               }
-
                ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -525,9 +515,22 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
        if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
                return TX_CONTINUE;
 
+       /* only deauth, disassoc and action are bufferable MMPDUs */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_deauth(hdr->frame_control) &&
+           !ieee80211_is_disassoc(hdr->frame_control) &&
+           !ieee80211_is_action(hdr->frame_control)) {
+               if (tx->flags & IEEE80211_TX_UNICAST)
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+               return TX_CONTINUE;
+       }
+
        if (tx->flags & IEEE80211_TX_UNICAST)
                return ieee80211_tx_h_unicast_ps_buf(tx);
        else
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 c8beafd401aa283f0befa0494e02649359bab83f..5a355a46d1dc4a70e82fadcd509ddd4fae34c3e1 100644 (file)
@@ -63,6 +63,7 @@
 #include <net/ip_vs.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 
@@ -97,6 +98,11 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
                return;
 
+       /* Applications may adjust TCP seqs */
+       if (cp->app && nf_ct_protonum(ct) == IPPROTO_TCP &&
+           !nfct_seqadj(ct) && !nfct_seqadj_ext_add(ct))
+               return;
+
        /*
         * The connection is not yet in the hashtable, so we update it.
         * CIP->VIP will remain the same, so leave the tuple in
index 17c1bcb182c6b58a782744e23bfe671de160bf92..f6e2ae91a80badd697a1f77e299dc332bc34a8d1 100644 (file)
@@ -36,6 +36,11 @@ int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        if (off == 0)
                return 0;
 
+       if (unlikely(!seqadj)) {
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+               return 0;
+       }
+
        set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
        spin_lock_bh(&ct->lock);
index 902fb0a6b38ad9baac15c3fc3f17a3e695510db8..7a394df0deb7686fa7fe4da162ff77d3c03435c5 100644 (file)
@@ -97,7 +97,6 @@ int nf_conntrack_tstamp_pernet_init(struct net *net)
 void nf_conntrack_tstamp_pernet_fini(struct net *net)
 {
        nf_conntrack_tstamp_fini_sysctl(net);
-       nf_ct_extend_unregister(&tstamp_extend);
 }
 
 int nf_conntrack_tstamp_init(void)
index f02b3605823e5616bc70f128a896e76d8f984ff2..1fb2258c35357c8c6f5072ae6593de2d53ab9f03 100644 (file)
@@ -34,10 +34,14 @@ static unsigned int help(struct sk_buff *skb,
                         struct nf_conntrack_expect *exp)
 {
        char buffer[sizeof("4294967296 65635")];
+       struct nf_conn *ct = exp->master;
+       union nf_inet_addr newaddr;
        u_int16_t port;
        unsigned int ret;
 
        /* Reply comes from server. */
+       newaddr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3;
+
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
@@ -57,17 +61,35 @@ static unsigned int help(struct sk_buff *skb,
        }
 
        if (port == 0) {
-               nf_ct_helper_log(skb, exp->master, "all ports in use");
+               nf_ct_helper_log(skb, ct, "all ports in use");
                return NF_DROP;
        }
 
-       ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
-                                      protoff, matchoff, matchlen, buffer,
-                                      strlen(buffer));
+       /* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
+        * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
+        * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
+        *
+        * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
+        *                        255.255.255.255==4294967296, 10 digits)
+        * P:         bound port (min 1 d, max 5d (65635))
+        * F:         filename   (min 1 d )
+        * S:         size       (min 1 d )
+        * 0x01, \n:  terminators
+        */
+       /* AAA = "us", ie. where server normally talks to. */
+       snprintf(buffer, sizeof(buffer), "%u %u", ntohl(newaddr.ip), port);
+       pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n",
+                buffer, &newaddr.ip, port);
+
+       ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff,
+                                      matchlen, buffer, strlen(buffer));
        if (ret != NF_ACCEPT) {
-               nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
+               nf_ct_helper_log(skb, ct, "cannot mangle packet");
                nf_ct_unexpect_related(exp);
        }
+
        return ret;
 }
 
index dcddc49c0e08363044195695138543e4277f83f0..71a9f49a768b887dec1b361b78147016cb2b9307 100644 (file)
@@ -312,6 +312,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        int err, i = 0;
 
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                err = nf_register_hook(&nft_base_chain(chain)->ops);
                if (err < 0)
                        goto err;
@@ -321,6 +324,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        return 0;
 err:
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                if (i-- <= 0)
                        break;
 
@@ -333,8 +339,10 @@ static int nf_tables_table_disable(struct nft_table *table)
 {
        struct nft_chain *chain;
 
-       list_for_each_entry(chain, &table->chains, list)
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+       list_for_each_entry(chain, &table->chains, list) {
+               if (chain->flags & NFT_BASE_CHAIN)
+                       nf_unregister_hook(&nft_base_chain(chain)->ops);
+       }
 
        return 0;
 }
@@ -1717,6 +1725,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 +1746,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 +1759,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;
                }
@@ -2078,17 +2106,21 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
                                   struct netlink_callback *cb)
 {
        const struct nft_set *set;
-       unsigned int idx = 0, s_idx = cb->args[0];
+       unsigned int idx, s_idx = cb->args[0];
        struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
 
        if (cb->args[1])
                return skb->len;
 
        list_for_each_entry(table, &ctx->afi->tables, list) {
-               if (cur_table && cur_table != table)
-                       continue;
+               if (cur_table) {
+                       if (cur_table != table)
+                               continue;
 
+                       cur_table = NULL;
+               }
                ctx->table = table;
+               idx = 0;
                list_for_each_entry(set, &ctx->table->sets, list) {
                        if (idx < s_idx)
                                goto cont;
@@ -2350,7 +2382,9 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
        enum nft_registers dreg;
 
        dreg = nft_type_to_reg(set->dtype);
-       return nft_validate_data_load(ctx, dreg, &elem->data, set->dtype);
+       return nft_validate_data_load(ctx, dreg, &elem->data,
+                                     set->dtype == NFT_DATA_VERDICT ?
+                                     NFT_DATA_VERDICT : NFT_DATA_VALUE);
 }
 
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
index 3c4b69e5fe17348b422f390bf79ab4269043fe5d..a155d19a225edcfb4b1a550ebc898f40d51c564d 100644 (file)
@@ -1053,6 +1053,7 @@ static void __net_exit nfnl_log_net_exit(struct net *net)
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
 #endif
+       nf_log_unset(net, &nfulnl_logger);
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index 8e0bb75e7c51e61092fb904dc1d93befe1e7320d..55c939f5371fabf35ad996efb51ea52a29630703 100644 (file)
@@ -31,7 +31,7 @@ static void nft_exthdr_eval(const struct nft_expr *expr,
 {
        struct nft_exthdr *priv = nft_expr_priv(expr);
        struct nft_data *dest = &data[priv->dreg];
-       unsigned int offset;
+       unsigned int offset = 0;
        int err;
 
        err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL);
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 872529105abc7c3a2e41b9d579e934e019e8e5ff..83b9927e7d19f3b14c8db4b199385122843d6764 100644 (file)
@@ -384,7 +384,7 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 {
        dev->dep_link_up = true;
 
-       if (!dev->active_target) {
+       if (!dev->active_target && rf_mode == NFC_RF_INITIATOR) {
                struct nfc_target *target;
 
                target = nfc_find_target(dev, target_idx);
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 b4c8b0022feeebea1aec424542e37a8391d87297..ba2dffeff60876ca669993d1863dcbb6cb76a740 100644 (file)
@@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 addr)
        ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
        /* due to this, we will claim to support iWARP devices unless we
           check node_type. */
-       if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA)
+       if (ret || !cm_id->device ||
+           cm_id->device->node_type != RDMA_NODE_IB_CA)
                ret = -EADDRNOTAVAIL;
 
        rdsdebug("addr %pI4 ret %d node type %d\n",
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 33af77246bfeb90c6b31bfe6163dc2c9cfbda787..62ced6516c586f5c7b5cb779e079ad57b72b7518 100644 (file)
@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (msg->msg_name) {
                struct sockaddr_rose *srose;
+               struct full_sockaddr_rose *full_srose = msg->msg_name;
 
                memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
                srose = msg->msg_name;
@@ -1260,18 +1261,9 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
                srose->srose_addr   = rose->dest_addr;
                srose->srose_call   = rose->dest_call;
                srose->srose_ndigis = rose->dest_ndigis;
-               if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) {
-                       struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name;
-                       for (n = 0 ; n < rose->dest_ndigis ; n++)
-                               full_srose->srose_digis[n] = rose->dest_digis[n];
-                       msg->msg_namelen = sizeof(struct full_sockaddr_rose);
-               } else {
-                       if (rose->dest_ndigis >= 1) {
-                               srose->srose_ndigis = 1;
-                               srose->srose_digi = rose->dest_digis[0];
-                       }
-                       msg->msg_namelen = sizeof(struct sockaddr_rose);
-               }
+               for (n = 0 ; n < rose->dest_ndigis ; n++)
+                       full_srose->srose_digis[n] = rose->dest_digis[n];
+               msg->msg_namelen = sizeof(struct full_sockaddr_rose);
        }
 
        skb_free_datagram(sk, skb);
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..11fe1a416433f1fe2ea46c86ee753826e523b716 100644 (file)
@@ -77,16 +77,16 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
                                     &csum_idx_gen, &csum_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_csum(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_csum(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &csum_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &csum_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
+       p = to_tcf_csum(pc);
        spin_lock_bh(&p->tcf_lock);
        p->tcf_action = parm->action;
        p->update_flags = parm->update_flags;
@@ -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..eb9ba60ebab4394527d10f25511b36b5aff84a32 100644 (file)
@@ -102,10 +102,11 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &gact_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &gact_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        gact = to_gact(pc);
@@ -206,9 +207,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..dcbfe8ce04a6a30ee9ce273f8e82196a5ba4a319 100644 (file)
@@ -141,10 +141,12 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_ipt_release(to_ipt(pc), bind);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_ipt_release(to_ipt(pc), bind);
+
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        ipt = to_ipt(pc);
 
@@ -298,9 +300,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 +312,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..76869538d0287148e48bf43660d3e243912a6e30 100644 (file)
@@ -70,15 +70,15 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                                     &nat_idx_gen, &nat_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_nat(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_nat(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &nat_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &nat_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
+       p = to_tcf_nat(pc);
 
        spin_lock_bh(&p->tcf_lock);
        p->old_addr = parm->old_addr;
@@ -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..7aa2dcd989f842976c57d449452d2e0458a7b32c 100644 (file)
@@ -84,10 +84,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                p = to_pedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &pedit_hash_info);
+               tcf_hash_release(pc, bind, &pedit_hash_info);
+               if (bind)
+                       return 0;
+               if (!ovr)
                        return -EEXIST;
-               }
+
                if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
                        keys = kmalloc(ksize, GFP_KERNEL);
                        if (keys == NULL)
@@ -243,9 +245,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..ef246d87e68bbdf628bc00eebb05e9cb88a3cb87 100644 (file)
@@ -177,10 +177,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
+                               return 0;
                        }
                        if (ovr)
                                goto override;
-                       return ret;
+                       /* not replacing */
+                       return -EEXIST;
                }
        }
 
@@ -407,7 +409,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..f7b45ab85388748e9f730939b7f214952f8df84e 100644 (file)
@@ -142,10 +142,13 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
-               if (!ovr) {
-                       tcf_simp_release(d, bind);
+
+               if (bind)
+                       return 0;
+               tcf_simp_release(d, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
+
                reset_policy(d, defdata, parm);
        }
 
@@ -201,7 +204,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..8fe9d25c3008ece001d4da815cdf4f50c893fdab 100644 (file)
@@ -120,10 +120,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_skbedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        spin_lock_bh(&d->tcf_lock);
@@ -203,7 +204,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 922a09406ba70573499877ac3e561c9ee7b61a5c..7fc899a943a8fa8368415bc0c6c8a939bd042963 100644 (file)
@@ -126,7 +126,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
 
        HARD_TX_LOCK(dev, txq, smp_processor_id());
        if (!netif_xmit_frozen_or_stopped(txq))
-               ret = dev_hard_start_xmit(skb, dev, txq, NULL);
+               ret = dev_hard_start_xmit(skb, dev, txq);
 
        HARD_TX_UNLOCK(dev, txq);
 
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..59268f6e2c36a0b32ac6b768dea15b7b6be0021d 100644 (file)
@@ -208,8 +208,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
        INIT_LIST_HEAD(&q->retransmit);
        INIT_LIST_HEAD(&q->sacked);
        INIT_LIST_HEAD(&q->abandoned);
-
-       q->empty = 1;
 }
 
 /* Free the outqueue structure and any related pending chunks.
@@ -332,7 +330,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                                SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
                        else
                                SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
-                       q->empty = 0;
                        break;
                }
        } else {
@@ -446,6 +443,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.
                         */
@@ -652,7 +651,6 @@ redo:
                        if (chunk->fast_retransmit == SCTP_NEED_FRTX)
                                chunk->fast_retransmit = SCTP_DONT_FRTX;
 
-                       q->empty = 0;
                        q->asoc->stats.rtxchunks++;
                        break;
                }
@@ -1063,8 +1061,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                        sctp_transport_reset_timers(transport);
 
-                       q->empty = 0;
-
                        /* Only let one DATA chunk get bundled with a
                         * COOKIE-ECHO chunk.
                         */
@@ -1273,29 +1269,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
                 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,
                 asoc->adv_peer_ack_point);
 
-       /* See if all chunks are acked.
-        * Make sure the empty queue handler will get run later.
-        */
-       q->empty = (list_empty(&q->out_chunk_list) &&
-                   list_empty(&q->retransmit));
-       if (!q->empty)
-               goto finish;
-
-       list_for_each_entry(transport, transport_list, transports) {
-               q->empty = q->empty && list_empty(&transport->transmitted);
-               if (!q->empty)
-                       goto finish;
-       }
-
-       pr_debug("%s: sack queue is empty\n", __func__);
-finish:
-       return q->empty;
+       return sctp_outq_is_empty(q);
 }
 
-/* Is the outqueue empty?  */
+/* Is the outqueue empty?
+ * The queue is empty when we have not pending data, no in-flight data
+ * and nothing pending retransmissions.
+ */
 int sctp_outq_is_empty(const struct sctp_outq *q)
 {
-       return q->empty;
+       return q->out_qlen == 0 && q->outstanding_bytes == 0 &&
+              list_empty(&q->retransmit);
 }
 
 /********************************************************************
@@ -1375,6 +1359,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 +1376,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 69cd9bf3f561d64d377ddb65091b98e1017e15cf..13b9877458201fa4d5bb14a36892825272229050 100644 (file)
@@ -1498,6 +1498,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
                int type;
 
                head = head->next;
+               buf->next = NULL;
 
                /* Ensure bearer is still enabled */
                if (unlikely(!b_ptr->active))
index c081a7632302ca0798c193b039214466c3180184..d43f3182b1d4cc1628817d882c9d006006e27e1e 100644 (file)
@@ -251,18 +251,15 @@ struct tipc_port *tipc_createport(struct sock *sk,
        return p_ptr;
 }
 
-int tipc_deleteport(u32 ref)
+int tipc_deleteport(struct tipc_port *p_ptr)
 {
-       struct tipc_port *p_ptr;
        struct sk_buff *buf = NULL;
 
-       tipc_withdraw(ref, 0, NULL);
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
+       tipc_withdraw(p_ptr, 0, NULL);
 
-       tipc_ref_discard(ref);
-       tipc_port_unlock(p_ptr);
+       spin_lock_bh(p_ptr->lock);
+       tipc_ref_discard(p_ptr->ref);
+       spin_unlock_bh(p_ptr->lock);
 
        k_cancel_timer(&p_ptr->timer);
        if (p_ptr->connected) {
@@ -704,47 +701,36 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 }
 
 
-int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
+                struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        u32 key;
-       int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
+       if (p_ptr->connected)
                return -EINVAL;
+       key = p_ptr->ref + p_ptr->pub_count + 1;
+       if (key == p_ptr->ref)
+               return -EADDRINUSE;
 
-       if (p_ptr->connected)
-               goto exit;
-       key = ref + p_ptr->pub_count + 1;
-       if (key == ref) {
-               res = -EADDRINUSE;
-               goto exit;
-       }
        publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
                                    scope, p_ptr->ref, key);
        if (publ) {
                list_add(&publ->pport_list, &p_ptr->publications);
                p_ptr->pub_count++;
                p_ptr->published = 1;
-               res = 0;
+               return 0;
        }
-exit:
-       tipc_port_unlock(p_ptr);
-       return res;
+       return -EINVAL;
 }
 
-int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
+                 struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        struct publication *tpubl;
        int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
        if (!seq) {
                list_for_each_entry_safe(publ, tpubl,
                                         &p_ptr->publications, pport_list) {
@@ -771,7 +757,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
        }
        if (list_empty(&p_ptr->publications))
                p_ptr->published = 0;
-       tipc_port_unlock(p_ptr);
        return res;
 }
 
index 9122535973430edff99e8ee6070a091975dea457..34f12bd4074e49ff8b4c7809bfe0bc706941ec7c 100644 (file)
@@ -116,7 +116,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err);
 
 void tipc_acknowledge(u32 port_ref, u32 ack);
 
-int tipc_deleteport(u32 portref);
+int tipc_deleteport(struct tipc_port *p_ptr);
 
 int tipc_portimportance(u32 portref, unsigned int *importance);
 int tipc_set_portimportance(u32 portref, unsigned int importance);
@@ -127,9 +127,9 @@ int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
 int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
 int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
 
-int tipc_publish(u32 portref, unsigned int scope,
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
                 struct tipc_name_seq const *name_seq);
-int tipc_withdraw(u32 portref, unsigned int scope,
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
                  struct tipc_name_seq const *name_seq);
 
 int tipc_connect(u32 portref, struct tipc_portid const *port);
index 3b61851bb9276ec733f7ab8c9d2179a5dd7fef4d..e741416d1d24d4655cd4096b07f84cd978c90cc7 100644 (file)
@@ -354,7 +354,7 @@ static int release(struct socket *sock)
         * Delete TIPC port; this ensures no more messages are queued
         * (also disconnects an active connection & sends a 'FIN-' to peer)
         */
-       res = tipc_deleteport(tport->ref);
+       res = tipc_deleteport(tport);
 
        /* Discard any remaining (connection-based) messages in receive queue */
        __skb_queue_purge(&sk->sk_receive_queue);
@@ -386,30 +386,46 @@ static int release(struct socket *sock)
  */
 static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
 {
+       struct sock *sk = sock->sk;
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
-       u32 portref = tipc_sk_port(sock->sk)->ref;
+       struct tipc_port *tport = tipc_sk_port(sock->sk);
+       int res = -EINVAL;
 
-       if (unlikely(!uaddr_len))
-               return tipc_withdraw(portref, 0, NULL);
+       lock_sock(sk);
+       if (unlikely(!uaddr_len)) {
+               res = tipc_withdraw(tport, 0, NULL);
+               goto exit;
+       }
 
-       if (uaddr_len < sizeof(struct sockaddr_tipc))
-               return -EINVAL;
-       if (addr->family != AF_TIPC)
-               return -EAFNOSUPPORT;
+       if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+               res = -EINVAL;
+               goto exit;
+       }
+       if (addr->family != AF_TIPC) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if (addr->addrtype == TIPC_ADDR_NAME)
                addr->addr.nameseq.upper = addr->addr.nameseq.lower;
-       else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
-               return -EAFNOSUPPORT;
+       else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
            (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
-           (addr->addr.nameseq.type != TIPC_CFG_SRV))
-               return -EACCES;
+           (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
+               res = -EACCES;
+               goto exit;
+       }
 
-       return (addr->scope > 0) ?
-               tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
-               tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+       res = (addr->scope > 0) ?
+               tipc_publish(tport, addr->scope, &addr->addr.nameseq) :
+               tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq);
+exit:
+       release_sock(sk);
+       return res;
 }
 
 /**
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 a271c27fac774ce987c0db6f1330ffbfca6dc7f7..722da616438cd1e933fb4d5e60a2c4846f44d186 100644 (file)
@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
        /* find payload start allowing for extended bitmap(s) */
 
        if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+               if ((unsigned long)iterator->_arg -
+                   (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+                   (unsigned long)iterator->_max_length)
+                       return -EINVAL;
                while (get_unaligned_le32(iterator->_arg) &
                                        (1 << IEEE80211_RADIOTAP_EXT)) {
                        iterator->_arg += sizeof(uint32_t);
index 65f800890d70d857c9b42d379caad887f5a98c74..d3c5bd7c6b513cd376a2e37857cb8f19919b5a43 100644 (file)
@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
        }
 #endif
 
+       if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
+               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+                                      wdev->ssid, wdev->ssid_len,
+                                      WLAN_CAPABILITY_ESS,
+                                      WLAN_CAPABILITY_ESS);
+               if (bss)
+                       cfg80211_hold_bss(bss_from_pub(bss));
+       }
+
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                return;
        }
 
-       if (!bss) {
-               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
-               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-                                      wdev->ssid, wdev->ssid_len,
-                                      WLAN_CAPABILITY_ESS,
-                                      WLAN_CAPABILITY_ESS);
-               if (WARN_ON(!bss))
-                       return;
-               cfg80211_hold_bss(bss_from_pub(bss));
-       }
+       if (WARN_ON(!bss))
+               return;
 
        wdev->current_bss = bss_from_pub(bss);
 
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..57b0b49f4e6e23a9c6dd974e3f9dd78664f1f59a 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 */
@@ -237,6 +234,14 @@ static int inode_alloc_security(struct inode *inode)
        return 0;
 }
 
+static void inode_free_rcu(struct rcu_head *head)
+{
+       struct inode_security_struct *isec;
+
+       isec = container_of(head, struct inode_security_struct, rcu);
+       kmem_cache_free(sel_inode_cache, isec);
+}
+
 static void inode_free_security(struct inode *inode)
 {
        struct inode_security_struct *isec = inode->i_security;
@@ -247,8 +252,16 @@ static void inode_free_security(struct inode *inode)
                list_del_init(&isec->list);
        spin_unlock(&sbsec->isec_lock);
 
-       inode->i_security = NULL;
-       kmem_cache_free(sel_inode_cache, isec);
+       /*
+        * The inode may still be referenced in a path walk and
+        * a call to selinux_inode_permission() can be made
+        * after inode_free_security() is called. Ideally, the VFS
+        * wouldn't do this, but fixing that is a much harder
+        * job. For now, simply free the i_security via RCU, and
+        * leave the current inode->i_security pointer intact.
+        * The inode will be freed after the RCU grace period too.
+        */
+       call_rcu(&isec->rcu, inode_free_rcu);
 }
 
 static int file_alloc_security(struct file *file)
@@ -413,8 +426,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 +435,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 +613,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 +672,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 +820,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 +2493,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 +2532,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 +3841,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 +3859,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 +4350,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 +4491,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 +4501,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 +4765,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 +4774,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 +4864,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 +4902,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 +5604,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 b1dfe104945078ead53647c247c46aa6134fac2e..078e553f52f27a03ab83490f20bb2353782d2ef2 100644 (file)
@@ -38,7 +38,10 @@ struct task_security_struct {
 
 struct inode_security_struct {
        struct inode *inode;    /* back pointer to inode object */
-       struct list_head list;  /* list of inode_security_struct */
+       union {
+               struct list_head list;  /* list of inode_security_struct */
+               struct rcu_head rcu;    /* for freeing the inode_security_struct */
+       };
        u32 task_sid;           /* SID of creating task */
        u32 sid;                /* SID of this object */
        u16 sclass;             /* security class of this object */
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 872d59e35ee23583cc60a2be24afa5ba1bf3c88d..721d8fd45685f769cbc616a6ba0552b85cd5c841 100644 (file)
@@ -357,7 +357,8 @@ static int set_sample_rates(struct atmel_abdac *dac)
                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 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 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 77db69480c195cde15ee64dd13bb18b2f81aa2de..7aa9870040c102df5b02aa0a94778c8e14c36024 100644 (file)
@@ -698,7 +698,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 */
 };
index 3067ed4fe3b2f7fdb7edfca13e2b14575b9707a1..c7f6d1cab6063a6483802ee6c80391c18c2de884 100644 (file)
@@ -474,6 +474,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)
@@ -1192,7 +1206,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 +2527,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 +2781,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 +2801,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 +2829,42 @@ 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))
+               *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+       if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
+               *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 +2872,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 +2885,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;
@@ -4271,6 +4318,26 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
        return AC_PWRST_D3;
 }
 
+/* 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
@@ -4383,6 +4450,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 +4476,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);
 
index 7e45cb44d1514497385f2f6bc2b63251391cdaba..0929a06df8128495f5e717768fcfa28eaed7360d 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;
 
index 7a09404579a73ac729ad437c358f38ac3b2b807b..956871d8b3d26a9255723eb4bdfdf963c50f031b 100644 (file)
@@ -2994,8 +2994,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 +3433,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 */
@@ -3877,7 +3880,8 @@ static int azx_probe(struct pci_dev *pci,
        }
 
        dev++;
-       complete_all(&chip->probe_wait);
+       if (chip->disabled)
+               complete_all(&chip->probe_wait);
        return 0;
 
 out_free:
@@ -3954,10 +3958,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;
 }
 
index 1a83559f4cbd27e455a941adaddc6d0513d9dd81..699262a3e07abcd9558bb538de0916d96bc63bcd 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);
@@ -338,6 +340,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,6 +368,11 @@ 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);
@@ -962,6 +977,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:
index c205bb1747fdf6a7d367d6ef54d718331d671c0b..3fbf2883e06e855e7a79213b0414e3049b539f28 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),
@@ -3244,9 +3243,29 @@ enum {
 #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)
 {
        struct hda_codec *codec = private_data;
@@ -3279,6 +3298,8 @@ static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
        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) {
@@ -3494,6 +3515,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..f281c8068557e63b72370e25a9973372dbaf0bae 100644 (file)
@@ -1142,32 +1142,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)
@@ -2095,7 +2097,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;
 }
@@ -2334,8 +2337,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);
index 5e42059f10a1fc4e5e6f127a6c6b536ae0dd537f..c5646941539a87df9505eece6241dd5e9230c4ff 100644 (file)
@@ -1780,8 +1780,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 +1885,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 +1900,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 +1934,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,
@@ -2097,6 +2119,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 +2133,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 +2179,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 +2195,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),
@@ -3268,6 +3310,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 +3339,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;
@@ -3581,11 +3625,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 +3633,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 +3660,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;
        }
 }
@@ -3796,11 +3849,14 @@ 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,
@@ -4056,6 +4112,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 +4137,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 +4162,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,
@@ -4141,6 +4215,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),
@@ -4172,11 +4247,16 @@ 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, 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),
+       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 +4264,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 +4371,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"},
        {}
 };
 
@@ -4467,6 +4548,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 +4598,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 +4809,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) {
@@ -4923,7 +5017,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 +5030,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 +5046,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_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        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_DELL_MIC_NO_PRESENCE),
        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 +5215,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 +5273,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..088a5afbd1b94846462cc290b7ca0eceab5ffaa7 100644 (file)
@@ -2094,7 +2094,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;
        }
 }
 
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..7d6a9055874b822bb440eab72a66dc5c034127ed 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");
index c3c7396a618115d06171bb87314b363cc8ac9f6d..0ab2dc296474373e1e407abf0762afeeffead4c6 100644 (file)
@@ -248,19 +248,6 @@ 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_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
             ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -293,18 +280,6 @@ 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,
@@ -1037,7 +1012,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" },
index 456bb8c6d759176a3bf31c5f7003a6e8cfc2d799..bc7472c968e37300edfdd38f9108bee0af77bb4f 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;
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 543c5c2631b61827bcebca8af1926ea02b5655e9..0f17ed3e29f41dc9d7ddebb505b7fad8fc545b02 100644 (file)
@@ -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;
index 253c88bb7a4cbdb06d3d1df2862f10e80095aaa8..4f05fb88bddf1394509b9eb14c7b746909074873 100644 (file)
@@ -1259,6 +1259,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);
+
+               codec->cache_sync = 1;
                break;
        }
 
index 46ec0e9744d4b88b50cc922cfdc65a0b4247e567..4fbcab63e61f1c5d8b4843fdec5c6d3dbfa498ed 100644 (file)
@@ -1474,13 +1474,17 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
                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");
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 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 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 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 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 4e53d87e881d0891a3d8437881d12d41225303cc..a66783e13a9cca182e3077b3e998c804aa40ff1d 100644 (file)
@@ -3212,11 +3212,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;
index b1d732255c0275fd06039efe36988b1a8ba3e8d2..3449c1e909ae10c71a695f6dc2eedecba9e8c163 100644 (file)
@@ -66,7 +66,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);
@@ -75,7 +75,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 cbc9c96ce1f412123a1704b171220a2990ad503d..41949af3baaed2580dae2df585222339ade75208 100644 (file)
@@ -305,6 +305,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
        }
 }
 
+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;
+       }
+}
+
 /**
  * snd_dmaengine_pcm_register - Register a dmaengine based PCM device
  * @dev: The parent device for the PCM device
@@ -315,6 +329,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,11 +341,20 @@ int snd_dmaengine_pcm_register(struct device *dev,
        dmaengine_pcm_request_chan_of(pcm, dev);
 
        if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_no_residue_pcm_platform);
        else
-               return snd_soc_add_platform(dev, &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);
 
@@ -345,7 +369,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)
@@ -353,15 +376,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 42782c01e41320e924efb4b93c839802f0df5722..891b9a9bcbf885df92bad9007b3f23054ce68c18 100644 (file)
@@ -148,12 +148,12 @@ 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,
@@ -166,6 +166,13 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
        if (cpu_stream->rates
                & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
                hw->rates |= codec_stream->rates;
+
+       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 +242,14 @@ 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);
        }
 
        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);
@@ -594,12 +600,13 @@ 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);
 
        /* 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 */
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;
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 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 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);