Merge remote-tracking branches 'asoc/topic/pxa' and 'asoc/topic/qcom' into asoc-next
authorMark Brown <broonie@kernel.org>
Sun, 13 Mar 2016 08:17:28 +0000 (15:17 +0700)
committerMark Brown <broonie@kernel.org>
Sun, 13 Mar 2016 08:17:28 +0000 (15:17 +0700)
1021 files changed:
Documentation/DocBook/media/v4l/media-types.xml
Documentation/cgroup-v2.txt
Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
Documentation/devicetree/bindings/net/renesas,ravb.txt
Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt
Documentation/devicetree/bindings/pci/rcar-pci.txt
Documentation/devicetree/bindings/regmap/regmap.txt
Documentation/devicetree/bindings/regulator/tps65217.txt
Documentation/devicetree/bindings/rtc/s3c-rtc.txt
Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
Documentation/devicetree/bindings/sound/adi,adau17x1.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
Documentation/devicetree/bindings/sound/max9867.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/max98926.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/mt8173-rt5650.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/pcm179x.txt
Documentation/devicetree/bindings/sound/ti,ads117x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/thermal/rcar-thermal.txt
Documentation/filesystems/efivarfs.txt
Documentation/kernel-parameters.txt
Documentation/timers/hpet.txt
Documentation/watchdog/watchdog-parameters.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/configs/axs101_defconfig
arch/arc/configs/axs103_defconfig
arch/arc/configs/axs103_smp_defconfig
arch/arc/configs/nsim_700_defconfig
arch/arc/configs/nsim_hs_defconfig
arch/arc/configs/nsim_hs_smp_defconfig
arch/arc/configs/nsimosci_defconfig
arch/arc/configs/nsimosci_hs_defconfig
arch/arc/configs/nsimosci_hs_smp_defconfig
arch/arc/configs/tb10x_defconfig
arch/arc/configs/vdk_hs38_smp_defconfig
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/irq.h
arch/arc/include/asm/irqflags-arcv2.h
arch/arc/include/asm/mcip.h
arch/arc/include/asm/pgtable.h
arch/arc/kernel/entry-arcv2.S
arch/arc/kernel/intc-arcv2.c
arch/arc/kernel/intc-compact.c
arch/arc/kernel/mcip.c
arch/arc/kernel/setup.c
arch/arc/kernel/smp.c
arch/arc/kernel/time.c
arch/arm/boot/compressed/Makefile
arch/arm/boot/dts/am335x-bone-common.dtsi
arch/arm/boot/dts/am335x-chilisom.dtsi
arch/arm/boot/dts/am335x-nano.dts
arch/arm/boot/dts/am335x-pepper.dts
arch/arm/boot/dts/am335x-shc.dts
arch/arm/boot/dts/am335x-sl50.dts
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/am57xx-cl-som-am57x.dts
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/kirkwood-ds112.dts
arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts
arch/arm/boot/dts/r8a7791-porter.dts
arch/arm/boot/dts/sama5d2-pinfunc.h
arch/arm/boot/dts/tps65217.dtsi [new file with mode: 0644]
arch/arm/common/icst.c
arch/arm/configs/omap2plus_defconfig
arch/arm/crypto/aes-ce-glue.c
arch/arm/include/asm/arch_gicv3.h
arch/arm/include/asm/xen/page-coherent.h
arch/arm/kernel/Makefile
arch/arm/kvm/guest.c
arch/arm/kvm/mmio.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-shmobile/common.h
arch/arm/mach-shmobile/headsmp-scu.S
arch/arm/mach-shmobile/headsmp.S
arch/arm/mach-shmobile/platsmp-apmu.c
arch/arm/mach-shmobile/platsmp-scu.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mm/mmap.c
arch/arm/mm/pageattr.c
arch/arm64/Makefile
arch/arm64/boot/Makefile
arch/arm64/boot/install.sh
arch/arm64/crypto/aes-glue.c
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/image.h
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/traps.c
arch/arm64/kvm/guest.c
arch/arm64/kvm/hyp-init.S
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/vgic-v3-sr.c
arch/arm64/kvm/inject_fault.c
arch/arm64/kvm/sys_regs.c
arch/arm64/lib/strnlen.S
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/fault.c
arch/arm64/mm/init.c
arch/arm64/mm/mmap.c
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/mips/Kconfig
arch/mips/boot/dts/brcm/bcm6328.dtsi
arch/mips/boot/dts/brcm/bcm6368.dtsi
arch/mips/boot/dts/brcm/bcm7125.dtsi
arch/mips/boot/dts/brcm/bcm7346.dtsi
arch/mips/boot/dts/brcm/bcm7358.dtsi
arch/mips/boot/dts/brcm/bcm7360.dtsi
arch/mips/boot/dts/brcm/bcm7362.dtsi
arch/mips/boot/dts/brcm/bcm7420.dtsi
arch/mips/boot/dts/brcm/bcm7425.dtsi
arch/mips/boot/dts/brcm/bcm7435.dtsi
arch/mips/include/asm/elf.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/octeon/octeon-feature.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/stackframe.h
arch/mips/include/asm/syscall.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/jz4740/gpio.c
arch/mips/kernel/binfmt_elfn32.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/process.c
arch/mips/kernel/r2300_fpu.S
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/traps.c
arch/mips/kvm/mips.c
arch/mips/mm/mmap.c
arch/mips/mm/sc-mips.c
arch/mips/mti-malta/malta-init.c
arch/mips/pci/pci-mt7620.c
arch/parisc/include/asm/floppy.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/syscall_table.S
arch/powerpc/Kconfig
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/trace.h
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/process.c
arch/powerpc/mm/hash64_64k.c
arch/powerpc/mm/hugepage-hash64.c
arch/powerpc/mm/hugetlbpage-book3e.c
arch/powerpc/mm/mmap.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/s390/include/asm/fpu/internal.h
arch/s390/include/asm/livepatch.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/perf_event.c
arch/s390/kernel/stacktrace.c
arch/s390/kernel/trace.c
arch/s390/mm/maccess.c
arch/s390/oprofile/backtrace.c
arch/sparc/Makefile
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/entry.S
arch/sparc/kernel/hvcalls.S
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/syscalls.S
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/um/kernel/reboot.c
arch/um/kernel/signal.c
arch/x86/Kconfig
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64_compat.S
arch/x86/include/asm/livepatch.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/uaccess_32.h
arch/x86/include/asm/xen/pci.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/cpu/perf_event_amd_uncore.c
arch/x86/kvm/emulate.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/copy_user_64.S
arch/x86/mm/fault.c
arch/x86/mm/gup.c
arch/x86/mm/mmap.c
arch/x86/mm/mpx.c
arch/x86/mm/numa.c
arch/x86/mm/pageattr.c
arch/x86/pci/common.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
arch/x86/pci/xen.c
arch/x86/platform/intel-quark/imr.c
arch/x86/um/os-Linux/task_size.c
block/Kconfig
block/bio.c
block/blk-cgroup.c
block/blk-core.c
block/blk-map.c
block/blk-merge.c
block/blk-mq.c
block/blk-settings.c
block/blk-sysfs.c
block/deadline-iosched.c
crypto/algif_skcipher.c
crypto/crypto_user.c
drivers/acpi/nfit.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/android/binder.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_brcmstb.c
drivers/ata/ahci_xgene.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_rb532_cf.c
drivers/base/component.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap.c
drivers/block/floppy.c
drivers/block/null_blk.c
drivers/block/xen-blkfront.c
drivers/char/hpet.c
drivers/char/random.c
drivers/clk/Makefile
drivers/clk/clk-gpio.c
drivers/clk/clk-scpi.c
drivers/clk/mvebu/dove-divider.c
drivers/clk/qcom/gcc-apq8084.c
drivers/clk/qcom/gcc-ipq806x.c
drivers/clk/qcom/gcc-msm8660.c
drivers/clk/qcom/gcc-msm8916.c
drivers/clk/qcom/gcc-msm8960.c
drivers/clk/qcom/gcc-msm8974.c
drivers/clk/qcom/lcc-ipq806x.c
drivers/clk/qcom/lcc-msm8960.c
drivers/clk/qcom/mmcc-apq8084.c
drivers/clk/qcom/mmcc-msm8960.c
drivers/clk/qcom/mmcc-msm8974.c
drivers/clk/rockchip/clk-rk3036.c
drivers/clk/rockchip/clk-rk3368.c
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-id.h
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-super-gen4.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/ti/dpll3xxx.c
drivers/clk/versatile/clk-icst.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/mt8173-cpufreq.c
drivers/crypto/atmel-sha.c
drivers/crypto/marvell/cesa.c
drivers/devfreq/tegra-devfreq.c
drivers/dma/dw/core.c
drivers/dma/dw/pci.c
drivers/dma/edma.c
drivers/dma/ioat/dma.c
drivers/dma/pxa_dma.c
drivers/firmware/efi/efivars.c
drivers/firmware/efi/vars.c
drivers/gpio/gpio-altera.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-rcar.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/cik_sdma.c
drivers/gpu/drm/amd/amdgpu/cz_dpm.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
drivers/gpu/drm/amd/amdgpu/kv_dpm.c
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/include/cgs_common.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_csr.c
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_dp_link_training.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_platform.c
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/qxl/qxl_prime.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_sa.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/vc4/vc4_irq.c
drivers/gpu/drm/vc4/vc4_render_cl.c
drivers/gpu/drm/vc4/vc4_v3d.c
drivers/gpu/drm/vc4/vc4_validate.c
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/dev.c
drivers/gpu/host1x/dev.h
drivers/hwmon/ads1015.c
drivers/hwmon/gpio-fan.c
drivers/i2c/busses/i2c-brcmstb.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-uniphier-f.c
drivers/i2c/busses/i2c-uniphier.c
drivers/infiniband/core/device.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mlx5/srq.c
drivers/infiniband/hw/ocrdma/ocrdma.h
drivers/infiniband/hw/ocrdma/ocrdma_main.c
drivers/infiniband/hw/ocrdma/ocrdma_stats.c
drivers/infiniband/hw/ocrdma/ocrdma_stats.h
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/cap11xx.c
drivers/input/misc/Kconfig
drivers/input/misc/sirfsoc-onkey.c
drivers/input/mouse/vmmouse.c
drivers/input/serio/serio.c
drivers/input/touchscreen/colibri-vf50-ts.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/dmar.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/intel_irq_remapping.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-sun4i.c
drivers/isdn/gigaset/ser-gigaset.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/lightnvm/core.c
drivers/lightnvm/rrpc.c
drivers/lightnvm/rrpc.h
drivers/md/dm.c
drivers/media/i2c/adp1653.c
drivers/media/i2c/adv7604.c
drivers/media/usb/au0828/au0828-video.c
drivers/mfd/db8500-prcmu.c
drivers/misc/atmel-ssc.c
drivers/misc/cxl/pci.c
drivers/misc/mei/main.c
drivers/mmc/card/block.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-of-at91.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mtd/ubi/upd.c
drivers/net/bonding/bond_main.c
drivers/net/can/usb/ems_usb.c
drivers/net/dsa/mv88e6352.c
drivers/net/dsa/mv88e6xxx.c
drivers/net/ethernet/8390/pcnet_cs.c
drivers/net/ethernet/agere/et131x.c
drivers/net/ethernet/amd/am79c961a.c
drivers/net/ethernet/amd/lance.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cavium/liquidio/lio_main.c
drivers/net/ethernet/cavium/liquidio/octeon_droq.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.h
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
drivers/net/ethernet/cisco/enic/enic.h
drivers/net/ethernet/cisco/enic/vnic_dev.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/fujitsu/fmvj18x_cs.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx4/catas.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_clock.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_port.c
drivers/net/ethernet/mellanox/mlx4/en_resources.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/pd.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlxsw/port.h
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/synopsys/dwc_eth_qos.c
drivers/net/ethernet/ti/cpsw-phy-sel.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/geneve.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/bcm7xxx.c
drivers/net/phy/marvell.c
drivers/net/phy/phy_device.c
drivers/net/ppp/pppoe.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/qmi_wwan.c
drivers/net/vmxnet3/vmxnet3_defs.h
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vxlan.c
drivers/net/wan/dscc4.c
drivers/net/wireless/intel/iwlwifi/Kconfig
drivers/net/wireless/intel/iwlwifi/iwl-8000.c
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/realtek/rtlwifi/rc.c
drivers/net/wireless/ti/wlcore/io.c
drivers/net/wireless/ti/wlcore/io.h
drivers/nvdimm/bus.c
drivers/nvdimm/pmem.c
drivers/nvme/host/Kconfig
drivers/nvme/host/core.c
drivers/nvme/host/lightnvm.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvmem/core.c
drivers/nvmem/qfprom.c
drivers/of/irq.c
drivers/of/of_mdio.c
drivers/pci/host/Kconfig
drivers/pci/host/pci-keystone-dw.c
drivers/pci/host/pci-layerscape.c
drivers/pci/host/pcie-iproc.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/xen-pcifront.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/phy/phy-twl4030-usb.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/mvebu/pinctrl-mvebu.c
drivers/pinctrl/nomadik/pinctrl-abx500.c
drivers/pinctrl/pxa/pinctrl-pxa2xx.c
drivers/pinctrl/samsung/pinctrl-samsung.c
drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel_scu_ipcutil.c
drivers/power/bq27xxx_battery_i2c.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_alias.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/hisi_sas/Kconfig
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
drivers/scsi/ipr.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/qla_tmpl.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/scsi/storvsc_drv.c
drivers/sh/pm_runtime.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835aux.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-imx.c
drivers/spi/spi-loopback-test.c
drivers/spi/spi-omap2-mcspi.c
drivers/staging/media/davinci_vpfe/vpfe_video.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_internal.h
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/thermal/Kconfig
drivers/thermal/cpu_cooling.c
drivers/thermal/of-thermal.c
drivers/thermal/rcar_thermal.c
drivers/thermal/spear_thermal.c
drivers/tty/pty.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/omap-serial.c
drivers/tty/tty_io.c
drivers/tty/tty_mutex.c
drivers/usb/chipidea/ci_hdrc_pci.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/otg.c
drivers/usb/core/hub.c
drivers/usb/dwc2/Kconfig
drivers/usb/dwc2/core.c
drivers/usb/dwc2/hcd_ddma.c
drivers/usb/dwc2/hcd_intr.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/fsl_qe_udc.c
drivers/usb/gadget/udc/net2280.h
drivers/usb/gadget/udc/udc-core.c
drivers/usb/musb/musb_host.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/cp210x.c
drivers/usb/serial/mxu11x0.c [deleted file]
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/vhost.c
drivers/video/console/fbcon.c
drivers/video/fbdev/da8xx-fb.c
drivers/video/fbdev/exynos/s6e8ax0.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/mmp/hw/mmp_ctrl.c
drivers/video/fbdev/ocfb.c
drivers/virtio/virtio_pci_modern.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/sun4v_wdt.c [new file with mode: 0644]
drivers/xen/xen-pciback/pciback_ops.c
drivers/xen/xen-scsiback.c
drivers/xen/xenbus/xenbus_dev_frontend.c
fs/affs/file.c
fs/binfmt_elf.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/compression.c
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-inode.h
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/root-tree.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/smb2pdu.c
fs/dax.c
fs/dcache.c
fs/devpts/inode.c
fs/direct-io.c
fs/efivarfs/file.c
fs/efivarfs/inode.c
fs/efivarfs/internal.h
fs/efivarfs/super.c
fs/ext2/file.c
fs/ext2/inode.c
fs/ext4/balloc.c
fs/ext4/crypto.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/move_extent.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/fs-writeback.c
fs/hpfs/namei.c
fs/inode.c
fs/jffs2/README.Locking
fs/jffs2/build.c
fs/jffs2/file.c
fs/jffs2/gc.c
fs/jffs2/nodelist.h
fs/namei.c
fs/nfs/blocklayout/extent_tree.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/notify/mark.c
fs/ocfs2/aops.c
fs/pnode.c
fs/read_write.c
fs/super.c
fs/userfaultfd.c
fs/xattr.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_aops.h
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_log_recover.c
include/asm-generic/cputime_nsecs.h
include/asm-generic/pgtable.h
include/drm/drm_crtc.h
include/drm/drm_edid.h
include/dt-bindings/clock/tegra210-car.h
include/linux/ata.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/ceph/ceph_features.h
include/linux/cgroup-defs.h
include/linux/compiler.h
include/linux/cpuset.h
include/linux/dax.h
include/linux/dcache.h
include/linux/devpts_fs.h
include/linux/efi.h
include/linux/fsnotify_backend.h
include/linux/ftrace.h
include/linux/intel-iommu.h
include/linux/libata.h
include/linux/libnvdimm.h
include/linux/lightnvm.h
include/linux/lockdep.h
include/linux/mlx4/device.h
include/linux/mlx5/mlx5_ifc.h
include/linux/module.h
include/linux/netdevice.h
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/pci.h
include/linux/perf_event.h
include/linux/pfn.h
include/linux/pfn_t.h
include/linux/platform_data/adau17x1.h
include/linux/power/bq27xxx_battery.h
include/linux/random.h
include/linux/skbuff.h
include/linux/soc/ti/knav_dma.h
include/linux/trace_events.h
include/linux/tracepoint.h
include/linux/ucs2_string.h
include/linux/workqueue.h
include/linux/writeback.h
include/net/af_unix.h
include/net/inet_connection_sock.h
include/net/ip_fib.h
include/net/ip_tunnels.h
include/net/scm.h
include/net/tcp.h
include/sound/hdaudio.h
include/sound/pcm.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/trace/events/asoc.h
include/uapi/linux/media.h
include/uapi/linux/ndctl.h
ipc/shm.c
kernel/bpf/verifier.c
kernel/cgroup.c
kernel/cpuset.c
kernel/events/core.c
kernel/locking/lockdep.c
kernel/memremap.c
kernel/module.c
kernel/resource.c
kernel/sched/deadline.c
kernel/trace/ftrace.c
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_stack.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Kconfig.ubsan
lib/klist.c
lib/scatterlist.c
lib/ucs2_string.c
lib/vsprintf.c
mm/backing-dev.c
mm/filemap.c
mm/huge_memory.c
mm/hugetlb.c
mm/memory.c
mm/migrate.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/pgtable-generic.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slob.c
mm/slub.c
net/appletalk/ddp.c
net/batman-adv/gateway_client.c
net/batman-adv/hard-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_core.c
net/bridge/br_mdb.c
net/caif/cfrfml.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/core/flow_dissector.c
net/core/scm.c
net/core/skbuff.c
net/core/sysctl_net_core.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dsa/slave.c
net/ipv4/devinet.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_gre.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_tunnel.c
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_gre.c
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
net/ipv6/tcp_ipv6.c
net/l2tp/l2tp_netlink.c
net/netfilter/Kconfig
net/netfilter/nf_conntrack_core.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/nft_counter.c
net/netfilter/xt_TEE.c
net/openvswitch/vport-vxlan.c
net/sched/sch_api.c
net/sctp/protocol.c
net/sctp/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/cache.c
net/sunrpc/xprtrdma/backchannel.c
net/tipc/link.c
net/tipc/node.c
net/unix/af_unix.c
net/unix/diag.c
net/unix/garbage.c
net/vmw_vsock/af_vsock.c
scripts/prune-kernel [new file with mode: 0755]
security/integrity/evm/evm_main.c
security/selinux/hooks.c
security/selinux/nlmsgtab.c
sound/core/control_compat.c
sound/core/pcm_compat.c
sound/core/pcm_misc.c
sound/core/pcm_native.c
sound/core/rawmidi_compat.c
sound/core/seq/oss/seq_oss.c
sound/core/seq/oss/seq_oss_device.h
sound/core/seq/oss/seq_oss_init.c
sound/core/seq/seq_memory.c
sound/core/seq/seq_ports.c
sound/core/timer.c
sound/core/timer_compat.c
sound/drivers/dummy.c
sound/firewire/digi00x/amdtp-dot.c
sound/firewire/tascam/tascam-transaction.c
sound/firewire/tascam/tascam.c
sound/firewire/tascam/tascam.h
sound/hda/hdac_controller.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_jack.h
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/bcm/bcm2835-i2s.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/adau1761-i2c.c
sound/soc/codecs/adau1761-spi.c
sound/soc/codecs/adau1761.c
sound/soc/codecs/adau1781-i2c.c
sound/soc/codecs/adau1781-spi.c
sound/soc/codecs/adau1781.c
sound/soc/codecs/adau17x1.h
sound/soc/codecs/ads117x.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42xx8.c
sound/soc/codecs/cs47l24.c
sound/soc/codecs/da732x.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/hdac_hdmi.h [new file with mode: 0644]
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/max9867.c [new file with mode: 0755]
sound/soc/codecs/max9867.h [new file with mode: 0755]
sound/soc/codecs/max98926.c [new file with mode: 0644]
sound/soc/codecs/max98926.h [new file with mode: 0644]
sound/soc/codecs/nau8825.c
sound/soc/codecs/nau8825.h
sound/soc/codecs/pcm179x-i2c.c [new file with mode: 0644]
sound/soc/codecs/pcm179x-spi.c [new file with mode: 0644]
sound/soc/codecs/pcm179x.c
sound/soc/codecs/pcm179x.h
sound/soc/codecs/pcm3168a.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8983.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm8997.c
sound/soc/codecs/wm8998.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.h
sound/soc/davinci/Kconfig
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/Kconfig
sound/soc/fsl/fsl-asoc-card.c
sound/soc/fsl/fsl_sai.c
sound/soc/fsl/mpc5200_psc_ac97.c
sound/soc/intel/Kconfig
sound/soc/intel/atom/sst/sst_acpi.c
sound/soc/intel/atom/sst/sst_ipc.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/mfld_machine.c
sound/soc/intel/boards/skl_nau88l25_max98357a.c
sound/soc/intel/boards/skl_nau88l25_ssm4567.c
sound/soc/intel/boards/skl_rt286.c
sound/soc/intel/common/sst-acpi.h
sound/soc/intel/common/sst-dsp-priv.h
sound/soc/intel/common/sst-match-acpi.c
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-sst-dsp.c
sound/soc/intel/skylake/skl-sst-dsp.h
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-tplg-interface.h
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h
sound/soc/mediatek/Kconfig
sound/soc/mediatek/Makefile
sound/soc/mediatek/mt8173-rt5650-rt5514.c [new file with mode: 0644]
sound/soc/mediatek/mt8173-rt5650-rt5676.c
sound/soc/mediatek/mt8173-rt5650.c [new file with mode: 0644]
sound/soc/mediatek/mtk-afe-common.h
sound/soc/mediatek/mtk-afe-pcm.c
sound/soc/mxs/mxs-saif.c
sound/soc/omap/n810.c
sound/soc/omap/omap-hdmi-audio.c
sound/soc/omap/rx51.c
sound/soc/pxa/brownstone.c
sound/soc/pxa/corgi.c
sound/soc/pxa/magician.c
sound/soc/pxa/poodle.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/samsung/i2s.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/usb/midi.c
sound/usb/quirks.c
tools/perf/util/intel-pt.c
tools/perf/util/parse-events.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/stat.c
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/efivarfs/efivarfs.sh
tools/testing/selftests/efivarfs/open-unlink.c
tools/testing/selftests/ftrace/test.d/instances/instance.tc
virt/kvm/arm/arch_timer.c
virt/kvm/arm/vgic.c
virt/kvm/async_pf.c

index 1af3842509105ea45fd815ad953781d901b03bfe..0ee0f3386cdf3c7881e88546c03e5347c3e5e721 100644 (file)
            <entry><constant>MEDIA_ENT_F_CONN_COMPOSITE</constant></entry>
            <entry>Connector for a RGB composite signal.</entry>
          </row>
-         <row>
-           <entry><constant>MEDIA_ENT_F_CONN_TEST</constant></entry>
-           <entry>Connector for a test generator.</entry>
-         </row>
          <row>
            <entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry>
            <entry>Camera video sensor entity.</entry>
index e8d25e78421454635236295d0d63ad76fd604af4..ff49cf901148d895b765800ec6ddb79c0e38ed53 100644 (file)
@@ -7,7 +7,7 @@ This is the authoritative documentation on the design, interface and
 conventions of cgroup v2.  It describes all userland-visible aspects
 of cgroup including core and specific controller behaviors.  All
 future changes must be reflected in this document.  Documentation for
-v1 is available under Documentation/cgroup-legacy/.
+v1 is available under Documentation/cgroup-v1/.
 
 CONTENTS
 
index ace05992a262592fb22f88db5c2e13036e20c015..20df350b9ef3d491b3e2e714f8877d74477afcd8 100644 (file)
@@ -30,7 +30,7 @@ that they are defined using standard clock bindings with following
 clock-output-names:
  - "xin24m" - crystal input - required,
  - "ext_i2s" - external I2S clock - optional,
- - "ext_gmac" - external GMAC clock - optional
+ - "rmii_clkin" - external EMAC clock - optional
 
 Example: Clock controller node:
 
index 7803e77d85cbe9d69dfcd42405ece4de0ddfe329..007a5b46256ad57effb087c5beb2eae8c7e3d1e7 100644 (file)
@@ -24,9 +24,8 @@ Main node required properties:
                1 = edge triggered
                4 = level triggered
 
-  Cells 4 and beyond are reserved for future use. When the 1st cell
-  has a value of 0 or 1, cells 4 and beyond act as padding, and may be
-  ignored. It is recommended that padding cells have a value of 0.
+  Cells 4 and beyond are reserved for future use and must have a value
+  of 0 if present.
 
 - reg : Specifies base physical address(s) and size of the GIC
   registers, in the following order:
index 81a9f9e6b45ff85c83da488fbafc2c2b89839600..c8ac222eac67a0c330bec3d641d0ed65cc399281 100644 (file)
@@ -82,8 +82,8 @@ Example:
                                  "ch16", "ch17", "ch18", "ch19",
                                  "ch20", "ch21", "ch22", "ch23",
                                  "ch24";
-               clocks = <&mstp8_clks R8A7795_CLK_ETHERAVB>;
-               power-domains = <&cpg_clocks>;
+               clocks = <&cpg CPG_MOD 812>;
+               power-domains = <&cpg>;
                phy-mode = "rgmii-id";
                phy-handle = <&phy0>;
 
index 4e8b90e43dd83c72d81df6d644317ba60b489559..07a75094c5a8ed07e927c0641584d5e8348e3dc6 100644 (file)
@@ -8,6 +8,7 @@ OHCI and EHCI controllers.
 Required properties:
 - compatible: "renesas,pci-r8a7790" for the R8A7790 SoC;
              "renesas,pci-r8a7791" for the R8A7791 SoC;
+             "renesas,pci-r8a7793" for the R8A7793 SoC;
              "renesas,pci-r8a7794" for the R8A7794 SoC;
              "renesas,pci-rcar-gen2" for a generic R-Car Gen2 compatible device
 
index 558fe528ae1951104b6266a2f5ed4849017c6b35..6cf99690eef94fa4ed033fb91e08c2aa010395bf 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
 compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC;
            "renesas,pcie-r8a7790" for the R8A7790 SoC;
            "renesas,pcie-r8a7791" for the R8A7791 SoC;
+           "renesas,pcie-r8a7793" for the R8A7793 SoC;
            "renesas,pcie-r8a7795" for the R8A7795 SoC;
            "renesas,pcie-rcar-gen2" for a generic R-Car Gen2 compatible device.
 
index b494f8b8ef72d8869756c7b18181649e41ef8164..e98a9652ccc8c4d3a2263fe5a67b9064b27d1f04 100644 (file)
@@ -5,15 +5,18 @@ Index     Device     Endianness properties
 ---------------------------------------------------
 1         BE         'big-endian'
 2         LE         'little-endian'
+3        Native     'native-endian'
 
 For one device driver, which will run in different scenarios above
 on different SoCs using the devicetree, we need one way to simplify
 this.
 
-Required properties:
-- {big,little}-endian: these are boolean properties, if absent
-  meaning that the CPU and the Device are in the same endianness mode,
-  these properties are for register values and all the buffers only.
+Optional properties:
+- {big,little,native}-endian: these are boolean properties, if absent
+  then the implementation will choose a default based on the device
+  being controlled.  These properties are for register values and all
+  the buffers only.  Native endian means that the CPU and device have
+  the same endianness.
 
 Examples:
 Scenario 1 : CPU in LE mode & device in LE mode.
index d18109657da6c0154d3abebd980178f91b4a9102..4f05d208c95cfeac7ebbc217003d34f08e0f4772 100644 (file)
@@ -26,11 +26,7 @@ Example:
                ti,pmic-shutdown-controller;
 
                regulators {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
                        dcdc1_reg: dcdc1 {
-                               reg = <0>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <1800000>;
                                regulator-boot-on;
@@ -38,7 +34,6 @@ Example:
                        };
 
                        dcdc2_reg: dcdc2 {
-                               reg = <1>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -46,7 +41,6 @@ Example:
                        };
 
                        dcdc3_reg: dcc3 {
-                               reg = <2>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-boot-on;
@@ -54,7 +48,6 @@ Example:
                        };
 
                        ldo1_reg: ldo1 {
-                               reg = <3>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -62,7 +55,6 @@ Example:
                        };
 
                        ldo2_reg: ldo2 {
-                               reg = <4>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -70,7 +62,6 @@ Example:
                        };
 
                        ldo3_reg: ldo3 {
-                               reg = <5>;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -78,7 +69,6 @@ Example:
                        };
 
                        ldo4_reg: ldo4 {
-                               reg = <6>;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
index ac2fcd6ff4b8cde39bf8446c406571fefa7684a9..1068ffce9f9125559e301f60f9c0ce6ca40d2374 100644 (file)
@@ -14,6 +14,10 @@ Required properties:
   interrupt number is the rtc alarm interrupt and second interrupt number
   is the rtc tick interrupt. The number of cells representing a interrupt
   depends on the parent interrupt controller.
+- clocks: Must contain a list of phandle and clock specifier for the rtc
+          and source clocks.
+- clock-names: Must contain "rtc" and "rtc_src" entries sorted in the
+               same order as the clocks property.
 
 Example:
 
@@ -21,4 +25,6 @@ Example:
                compatible = "samsung,s3c6410-rtc";
                reg = <0x10070000 0x100>;
                interrupts = <44 0 45 0>;
+               clocks = <&clock CLK_RTC>, <&s2mps11_osc S2MPS11_CLK_AP>;
+               clock-names = "rtc", "rtc_src";
        };
index 35ae1fb3537f3217a50fe92fd8f4042b52e6e6d0..ed94c217c98d18a655aa4df150de7b62f1e17440 100644 (file)
@@ -9,7 +9,7 @@ Optional properties:
 - fsl,uart-has-rtscts : Indicate the uart has rts and cts
 - fsl,irda-mode : Indicate the uart supports irda mode
 - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works
-                  is DCE mode by default.
+                  in DCE mode by default.
 
 Note: Each uart controller should have an alias correctly numbered
 in "aliases" node.
diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt
new file mode 100644 (file)
index 0000000..8dbce0e
--- /dev/null
@@ -0,0 +1,24 @@
+Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781
+
+Required properties:
+
+ - compatible:         Should contain one of the following:
+                       "adi,adau1361"
+                       "adi,adau1461"
+                       "adi,adau1761"
+                       "adi,adau1961"
+                       "adi,adau1381"
+                       "adi,adau1781"
+
+ - reg:                        The i2c address. Value depends on the state of ADDR0
+                       and ADDR1, as wired in hardware.
+
+Examples:
+#include <dt-bindings/sound/adau17x1.h>
+
+       i2c_bus {
+               adau1361@38 {
+                       compatible = "adi,adau1761";
+                       reg = <0x38>;
+               };
+       };
index 4da41bf1888e9baaf2471a73db7d8019be9d6d0c..ceaef512698967ff16677b3771d2fd8c5227aaac 100644 (file)
@@ -24,6 +24,9 @@ The compatible list for this generic sound card currently:
 
  "fsl,imx-audio-cs42888"
 
+ "fsl,imx-audio-cs427x"
+ (compatible with CS4271 and CS4272)
+
  "fsl,imx-audio-wm8962"
  (compatible with Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt)
 
@@ -63,6 +66,12 @@ Optional properties:
   - audio-asrc         : The phandle of ASRC. It can be absent if there's no
                          need to add ASRC support via DPCM.
 
+Optional unless SSI is selected as a CPU DAI:
+
+  - mux-int-port       : The internal port of the i.MX audio muxer (AUDMUX)
+
+  - mux-ext-port       : The external port of the i.MX audio muxer
+
 Example:
 sound-cs42888 {
        compatible = "fsl,imx-audio-cs42888";
diff --git a/Documentation/devicetree/bindings/sound/max9867.txt b/Documentation/devicetree/bindings/sound/max9867.txt
new file mode 100644 (file)
index 0000000..394cd4e
--- /dev/null
@@ -0,0 +1,17 @@
+max9867 codec
+
+This device supports I2C mode only.
+
+Required properties:
+
+- compatible : "maxim,max9867"
+- reg : The chip select number on the I2C bus
+
+Example:
+
+&i2c {
+       max9867: max9867@0x18 {
+               compatible = "maxim,max9867";
+               reg = <0x18>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/max98926.txt b/Documentation/devicetree/bindings/sound/max98926.txt
new file mode 100644 (file)
index 0000000..0b7f4e4
--- /dev/null
@@ -0,0 +1,32 @@
+max98926 audio CODEC
+
+This device supports I2C.
+
+Required properties:
+
+  - compatible : "maxim,max98926"
+
+  - vmon-slot-no : slot number used to send voltage information
+                   or in inteleave mode this will be used as
+                   interleave slot.
+
+  - imon-slot-no : slot number used to send current information
+
+  - interleave-mode : When using two MAX98926 in a system it is
+                      possible to create ADC data that that will
+                      overflow the frame size. Digital Audio Interleave
+                      mode provides a means to output VMON and IMON data
+                      from two devices on a single DOUT line when running
+                      smaller frames sizes such as 32 BCLKS per LRCLK or
+                      48 BCLKS per LRCLK.
+
+  - reg : the I2C address of the device for I2C
+
+Example:
+
+codec: max98926@1a {
+   compatible = "maxim,max98926";
+   vmon-slot-no = <0>;
+   imon-slot-no = <2>;
+   reg = <0x1a>;
+};
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt
new file mode 100644 (file)
index 0000000..e8b3c80
--- /dev/null
@@ -0,0 +1,15 @@
+MT8173 with RT5650 RT5514 CODECS
+
+Required properties:
+- compatible : "mediatek,mt8173-rt5650-rt5514"
+- mediatek,audio-codec: the phandles of rt5650 and rt5514 codecs
+- mediatek,platform: the phandle of MT8173 ASoC platform
+
+Example:
+
+       sound {
+               compatible = "mediatek,mt8173-rt5650-rt5514";
+               mediatek,audio-codec = <&rt5650 &rt5514>;
+               mediatek,platform = <&afe>;
+       };
+
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt
new file mode 100644 (file)
index 0000000..fe5a5ef
--- /dev/null
@@ -0,0 +1,15 @@
+MT8173 with RT5650 CODECS
+
+Required properties:
+- compatible : "mediatek,mt8173-rt5650"
+- mediatek,audio-codec: the phandles of rt5650 codecs
+- mediatek,platform: the phandle of MT8173 ASoC platform
+
+Example:
+
+       sound {
+               compatible = "mediatek,mt8173-rt5650";
+               mediatek,audio-codec = <&rt5650>;
+               mediatek,platform = <&afe>;
+       };
+
index 4ae70d3462d65e6539278f4036e3fe26dc73f0ca..436c2b247693f5a9a60a58b28c365aecd1741644 100644 (file)
@@ -1,6 +1,6 @@
 Texas Instruments pcm179x DT bindings
 
-This driver supports the SPI bus.
+This driver supports both the I2C and SPI bus.
 
 Required properties:
 
@@ -9,6 +9,11 @@ Required properties:
 For required properties on SPI, please consult
 Documentation/devicetree/bindings/spi/spi-bus.txt
 
+Required properties on I2C:
+
+ - reg: the I2C address
+
+
 Examples:
 
        codec_spi: 1792a@0 {
@@ -16,3 +21,7 @@ Examples:
                spi-max-frequency = <600000>;
        };
 
+       codec_i2c: 1792a@4c {
+               compatible = "ti,pcm1792a";
+               reg = <0x4c>;
+       };
diff --git a/Documentation/devicetree/bindings/sound/ti,ads117x.txt b/Documentation/devicetree/bindings/sound/ti,ads117x.txt
new file mode 100644 (file)
index 0000000..7db19b5
--- /dev/null
@@ -0,0 +1,11 @@
+Texas Intstruments ADS117x ADC
+
+Required properties:
+
+  - compatible : "ti,ads1174" or "ti,ads1178"
+
+Example:
+
+ads1178 {
+       compatible = "ti,ads1178";
+};
index 332e625f6ed01cb4e442c0ea530ab29eb92f2a77..e5ee3f15989337f37b9d5e43036c31a2b4c9ff11 100644 (file)
@@ -1,8 +1,9 @@
 * Renesas R-Car Thermal
 
 Required properties:
-- compatible           : "renesas,thermal-<soctype>", "renesas,rcar-thermal"
-                         as fallback.
+- compatible           : "renesas,thermal-<soctype>",
+                          "renesas,rcar-gen2-thermal" (with thermal-zone) or
+                          "renesas,rcar-thermal" (without thermal-zone) as fallback.
                          Examples with soctypes are:
                            - "renesas,thermal-r8a73a4" (R-Mobile APE6)
                            - "renesas,thermal-r8a7779" (R-Car H1)
@@ -36,3 +37,35 @@ thermal@e61f0000 {
                0xe61f0300 0x38>;
        interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
 };
+
+Example (with thermal-zone):
+
+thermal-zones {
+       cpu_thermal: cpu-thermal {
+               polling-delay-passive   = <1000>;
+               polling-delay           = <5000>;
+
+               thermal-sensors = <&thermal>;
+
+               trips {
+                       cpu-crit {
+                               temperature     = <115000>;
+                               hysteresis      = <0>;
+                               type            = "critical";
+                       };
+               };
+               cooling-maps {
+               };
+       };
+};
+
+thermal: thermal@e61f0000 {
+       compatible =    "renesas,thermal-r8a7790",
+                       "renesas,rcar-gen2-thermal",
+                       "renesas,rcar-thermal";
+       reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
+       interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+       clocks = <&mstp5_clks R8A7790_CLK_THERMAL>;
+       power-domains = <&cpg_clocks>;
+       #thermal-sensor-cells = <0>;
+};
index c477af086e6569398d85b3f938e9f067b1976f7e..686a64bba775e0af9990cf305ab81f1ac4c8c278 100644 (file)
@@ -14,3 +14,10 @@ filesystem.
 efivarfs is typically mounted like this,
 
        mount -t efivarfs none /sys/firmware/efi/efivars
+
+Due to the presence of numerous firmware bugs where removing non-standard
+UEFI variables causes the system firmware to fail to POST, efivarfs
+files that are not well-known standardized variables are created
+as immutable files.  This doesn't prevent removal - "chattr -i" will work -
+but it does prevent this kind of failure from being accomplished
+accidentally.
index 551ecf09c8dd820be865ebbbc22fa6b5f608dd98..9a53c929f017d16527270bc2244352edf1d34cd8 100644 (file)
@@ -4235,6 +4235,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        The default value of this parameter is determined by
                        the config option CONFIG_WQ_POWER_EFFICIENT_DEFAULT.
 
+       workqueue.debug_force_rr_cpu
+                       Workqueue used to implicitly guarantee that work
+                       items queued without explicit CPU specified are put
+                       on the local CPU.  This guarantee is no longer true
+                       and while local CPU is still preferred work items
+                       may be put on foreign CPUs.  This debug option
+                       forces round-robin CPU selection to flush out
+                       usages which depend on the now broken guarantee.
+                       When enabled, memory and cache locality will be
+                       impacted.
+
        x2apic_phys     [X86-64,APIC] Use x2apic physical mode instead of
                        default x2apic cluster mode on platforms
                        supporting x2apic.
index 767392ffd31e1451aa14da7453fc581264b4491c..a484d2c109d7ff0689d8997c04ce477ca6e79d1c 100644 (file)
@@ -1,9 +1,7 @@
                High Precision Event Timer Driver for Linux
 
 The High Precision Event Timer (HPET) hardware follows a specification
-by Intel and Microsoft which can be found at
-
-       http://www.intel.com/hardwaredesign/hpetspec_1.pdf
+by Intel and Microsoft, revision 1.
 
 Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
 and up to 32 comparators.  Normally three or more comparators are provided,
index 9f9ec9f76039404a15114c97fe67535fe41fa88c..4e4b6f10d8410f84d8ea64ac51c68a6932bf2158 100644 (file)
@@ -400,3 +400,7 @@ wm8350_wdt:
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
 -------------------------------------------------
+sun4v_wdt:
+timeout_ms: Watchdog timeout in milliseconds 1..180000, default=60000)
+nowayout: Watchdog cannot be stopped once started
+-------------------------------------------------
index 7f1fa4ff300affdb1857eec9ac42278dc0a6c770..f5e6a535bc3479d37f1e76a8ed93209cb21d132b 100644 (file)
@@ -920,17 +920,24 @@ M:        Emilio López <emilio@elopez.com.ar>
 S:     Maintained
 F:     drivers/clk/sunxi/
 
-ARM/Amlogic MesonX SoC support
+ARM/Amlogic Meson SoC support
 M:     Carlo Caione <carlo@caione.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-meson@googlegroups.com
+W:     http://linux-meson.com/
 S:     Maintained
-F:     drivers/media/rc/meson-ir.c
-N:     meson[x68]
+F:     arch/arm/mach-meson/
+F:     arch/arm/boot/dts/meson*
+N:     meson
 
 ARM/Annapurna Labs ALPINE ARCHITECTURE
 M:     Tsahee Zidenberg <tsahee@annapurnalabs.com>
+M:     Antoine Tenart <antoine.tenart@free-electrons.com>
 S:     Maintained
 F:     arch/arm/mach-alpine/
+F:     arch/arm/boot/dts/alpine*
+F:     arch/arm64/boot/dts/al/
+F:     drivers/*/*alpine*
 
 ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -1442,8 +1449,8 @@ S:        Maintained
 ARM/RENESAS ARM64 ARCHITECTURE
 M:     Simon Horman <horms@verge.net.au>
 M:     Magnus Damm <magnus.damm@gmail.com>
-L:     linux-sh@vger.kernel.org
-Q:     http://patchwork.kernel.org/project/linux-sh/list/
+L:     linux-renesas-soc@vger.kernel.org
+Q:     http://patchwork.kernel.org/project/linux-renesas-soc/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
 S:     Supported
 F:     arch/arm64/boot/dts/renesas/
@@ -2362,14 +2369,6 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
 S:     Maintained
 N:     bcm2835
 
-BROADCOM BCM33XX MIPS ARCHITECTURE
-M:     Kevin Cernekee <cernekee@gmail.com>
-L:     linux-mips@linux-mips.org
-S:     Maintained
-F:     arch/mips/bcm3384/*
-F:     arch/mips/include/asm/mach-bcm3384/*
-F:     arch/mips/kernel/*bmips*
-
 BROADCOM BCM47XX MIPS ARCHITECTURE
 M:     Hauke Mehrtens <hauke@hauke-m.de>
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
@@ -3452,7 +3451,6 @@ F:        drivers/usb/dwc2/
 DESIGNWARE USB3 DRD IP DRIVER
 M:     Felipe Balbi <balbi@kernel.org>
 L:     linux-usb@vger.kernel.org
-L:     linux-omap@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
 F:     drivers/usb/dwc3/
@@ -4520,6 +4518,12 @@ L:       linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/dma/fsldma.*
 
+FREESCALE GPMI NAND DRIVER
+M:     Han Xu <han.xu@nxp.com>
+L:     linux-mtd@lists.infradead.org
+S:     Maintained
+F:     drivers/mtd/nand/gpmi-nand/*
+
 FREESCALE I2C CPM DRIVER
 M:     Jochen Friedrich <jochen@scram.de>
 L:     linuxppc-dev@lists.ozlabs.org
@@ -4536,7 +4540,7 @@ F:        include/linux/platform_data/video-imxfb.h
 F:     drivers/video/fbdev/imxfb.c
 
 FREESCALE QUAD SPI DRIVER
-M:     Han Xu <han.xu@freescale.com>
+M:     Han Xu <han.xu@nxp.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     drivers/mtd/spi-nor/fsl-quadspi.c
@@ -6136,7 +6140,7 @@ F:        include/uapi/linux/sunrpc/
 
 KERNEL SELFTEST FRAMEWORK
 M:     Shuah Khan <shuahkh@osg.samsung.com>
-L:     linux-api@vger.kernel.org
+L:     linux-kselftest@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/shuah/linux-kselftest
 S:     Maintained
 F:     tools/testing/selftests
@@ -7362,7 +7366,7 @@ F:        drivers/tty/isicom.c
 F:     include/linux/isicom.h
 
 MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
-M:     Felipe Balbi <balbi@kernel.org>
+M:     Bin Liu <b-liu@ti.com>
 L:     linux-usb@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
@@ -7694,13 +7698,13 @@ S:      Maintained
 F:     arch/nios2/
 
 NOKIA N900 POWER SUPPLY DRIVERS
-M:     Pali Rohár <pali.rohar@gmail.com>
-S:     Maintained
+R:     Pali Rohár <pali.rohar@gmail.com>
 F:     include/linux/power/bq2415x_charger.h
 F:     include/linux/power/bq27xxx_battery.h
 F:     include/linux/power/isp1704_charger.h
 F:     drivers/power/bq2415x_charger.c
 F:     drivers/power/bq27xxx_battery.c
+F:     drivers/power/bq27xxx_battery_i2c.c
 F:     drivers/power/isp1704_charger.c
 F:     drivers/power/rx51_battery.c
 
@@ -7931,11 +7935,9 @@ F:       drivers/media/platform/omap3isp/
 F:     drivers/staging/media/omap4iss/
 
 OMAP USB SUPPORT
-M:     Felipe Balbi <balbi@kernel.org>
 L:     linux-usb@vger.kernel.org
 L:     linux-omap@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
-S:     Maintained
+S:     Orphan
 F:     drivers/usb/*/*omap*
 F:     arch/arm/*omap*/usb*
 
@@ -9566,6 +9568,12 @@ M:       Andreas Noever <andreas.noever@gmail.com>
 S:     Maintained
 F:     drivers/thunderbolt/
 
+TI BQ27XXX POWER SUPPLY DRIVER
+R:     Andrew F. Davis <afd@ti.com>
+F:     include/linux/power/bq27xxx_battery.h
+F:     drivers/power/bq27xxx_battery.c
+F:     drivers/power/bq27xxx_battery_i2c.c
+
 TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
 M:     John Stultz <john.stultz@linaro.org>
 M:     Thomas Gleixner <tglx@linutronix.de>
@@ -9787,10 +9795,11 @@ S:      Supported
 F:     drivers/scsi/be2iscsi/
 
 Emulex 10Gbps NIC BE2, BE3-R, Lancer, Skyhawk-R DRIVER
-M:     Sathya Perla <sathya.perla@avagotech.com>
-M:     Ajit Khaparde <ajit.khaparde@avagotech.com>
-M:     Padmanabh Ratnakar <padmanabh.ratnakar@avagotech.com>
-M:     Sriharsha Basavapatna <sriharsha.basavapatna@avagotech.com>
+M:     Sathya Perla <sathya.perla@broadcom.com>
+M:     Ajit Khaparde <ajit.khaparde@broadcom.com>
+M:     Padmanabh Ratnakar <padmanabh.ratnakar@broadcom.com>
+M:     Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
+M:     Somnath Kotur <somnath.kotur@broadcom.com>
 L:     netdev@vger.kernel.org
 W:     http://www.emulex.com
 S:     Supported
@@ -12020,7 +12029,6 @@ F:      arch/arm64/xen/
 F:     arch/arm64/include/asm/xen/
 
 XEN NETWORK BACKEND DRIVER
-M:     Ian Campbell <ian.campbell@citrix.com>
 M:     Wei Liu <wei.liu2@citrix.com>
 L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
 L:     netdev@vger.kernel.org
index 682840850f580d6c5361d0e6db4084694e90a1c4..2d519d2fb3a9be1a64100c85141b824a37924602 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc7
 NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
index 76dde9db79349d0977687623307c934de91e314a..8a188bc1786a2c5cb181f21e10e5ba254b368199 100644 (file)
@@ -12,8 +12,6 @@ config ARC
        select BUILDTIME_EXTABLE_SORT
        select COMMON_CLK
        select CLONE_BACKWARDS
-       # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
-       select DEVTMPFS if !INITRAMFS_SOURCE=""
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
        select GENERIC_FIND_FIRST_BIT
@@ -275,14 +273,6 @@ config ARC_DCCM_BASE
        default "0xA0000000"
        depends on ARC_HAS_DCCM
 
-config ARC_HAS_HW_MPY
-       bool "Use Hardware Multiplier (Normal or Faster XMAC)"
-       default y
-       help
-         Influences how gcc generates code for MPY operations.
-         If enabled, MPYxx insns are generated, provided by Standard/XMAC
-         Multipler. Otherwise software multipy lib is used
-
 choice
        prompt "MMU Version"
        default ARC_MMU_V3 if ARC_CPU_770
@@ -338,6 +328,19 @@ config ARC_PAGE_SIZE_4K
 
 endchoice
 
+choice
+       prompt "MMU Super Page Size"
+       depends on ISA_ARCV2 && TRANSPARENT_HUGEPAGE
+       default ARC_HUGEPAGE_2M
+
+config ARC_HUGEPAGE_2M
+       bool "2MB"
+
+config ARC_HUGEPAGE_16M
+       bool "16MB"
+
+endchoice
+
 if ISA_ARCOMPACT
 
 config ARC_COMPACT_IRQ_LEVELS
@@ -410,7 +413,7 @@ config ARC_HAS_RTC
        default n
        depends on !SMP
 
-config ARC_HAS_GRTC
+config ARC_HAS_GFRC
        bool "SMP synchronized 64-bit cycle counter"
        default y
        depends on SMP
@@ -529,14 +532,6 @@ config ARC_DBG_TLB_MISS_COUNT
          Counts number of I and D TLB Misses and exports them via Debugfs
          The counters can be cleared via Debugfs as well
 
-if SMP
-
-config ARC_IPI_DBG
-       bool "Debug Inter Core interrupts"
-       default n
-
-endif
-
 endif
 
 config ARC_UBOOT_SUPPORT
@@ -566,6 +561,12 @@ endmenu
 endmenu         # "ARC Architecture Configuration"
 
 source "mm/Kconfig"
+
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       default "12" if ARC_HUGEPAGE_16M
+       default "11"
+
 source "net/Kconfig"
 source "drivers/Kconfig"
 source "fs/Kconfig"
index aeb19021099e315967ba95524e9528c48da0d159..c8230f3395f281f9c11ee6de130137d84e1bb543 100644 (file)
@@ -74,10 +74,6 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN)     += -EB
 # --build-id w/o "-marclinux". Default arc-elf32-ld is OK
 ldflags-$(upto_gcc44)                  += -marclinux
 
-ifndef CONFIG_ARC_HAS_HW_MPY
-       cflags-y        += -mno-mpy
-endif
-
 LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
 
 # Modules with short calls might break for calls into builtin-kernel
index f1ac9818b751e1fab854f2c1a4440b9ca8af3e85..5d4e2a07ad3eb8d11c605f385b881769d44b16ae 100644 (file)
@@ -39,6 +39,7 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -73,7 +74,6 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
@@ -91,12 +91,10 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
index 323486d6ee83419a9e50d5c53fa042f53e08ebed..87ee46b237ef7baa6dc5008f968e5c914d03aee4 100644 (file)
@@ -39,14 +39,10 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_AXS=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
@@ -78,14 +74,12 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
@@ -97,12 +91,10 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
index 66191cd0447eaabc524a36ec497e7047043dc9a4..d80daf4f7e735aa3787df6f75957c2b9a273b361 100644 (file)
@@ -40,14 +40,10 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_AXS=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
@@ -79,14 +75,12 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
@@ -98,12 +92,10 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
index 138f9d8879570a8b329415d9238c710fa6e5b032..f41095340b6a7a8662fc4e51e16e39524f359ae7 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -26,7 +27,6 @@ CONFIG_ARC_PLAT_SIM=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsim_700"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -34,6 +34,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -51,7 +52,6 @@ CONFIG_SERIAL_ARC=y
 CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
@@ -63,4 +63,3 @@ CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_XZ_DEC=y
index f68838e8068af53eb2ebb29c83d88cb10dc0bfac..cfaa33cb59217c6261667ec4d51b2762fea985ab 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -49,7 +50,6 @@ CONFIG_SERIAL_ARC=y
 CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
@@ -61,4 +61,3 @@ CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_XZ_DEC=y
index 96bd1c20fb0badeb5d3ebf41f2671f6558939c22..bb2a8dc778b5be48943f25f4415abbe73c476969 100644 (file)
@@ -2,6 +2,7 @@ CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -21,13 +22,11 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_SIM=y
-CONFIG_ARC_BOARD_ML509=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsim_hs_idu"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -35,6 +34,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -49,7 +49,6 @@ CONFIG_SERIAL_ARC=y
 CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
@@ -60,4 +59,3 @@ CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_XZ_DEC=y
index 31e1d95764ff91dc10fe80d936a5613e6f713cc4..646182e93753af74110471f7739fab2454246b1b 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -58,7 +59,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_HID is not set
index fcae66683ca0bd5865924a88816a388e763604cd..ceca2541950d1bbe7f950bad17ab2c598c79c65a 100644 (file)
@@ -34,12 +34,12 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_OSCI_LAN=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_MOUSE_PS2_ALPS is not set
 # CONFIG_MOUSE_PS2_LOGIPS2PP is not set
@@ -58,7 +58,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_HID is not set
index b01b659168ea4a1c36ac85e0ee41c545aa697ec8..4b6da90f6f261e3d9783719a5bbc2060bf2e8408 100644 (file)
@@ -2,6 +2,7 @@ CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
@@ -18,15 +19,11 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_SIM=y
-CONFIG_ARC_BOARD_ML509=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
-CONFIG_ARC_HAS_LL64=y
-# CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=y
@@ -40,6 +37,7 @@ CONFIG_INET=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -56,14 +54,11 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
-CONFIG_NET_OSCI_LAN=y
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_MOUSE_PS2_TOUCHKIT=y
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIO_ARC_PS2=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
@@ -75,9 +70,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-CONFIG_ARCPGU_RGB888=y
-CONFIG_ARCPGU_DISPTYPE=0
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_HID is not set
index 3b4dc9cebcf15234f3d42a4efd2e40b9c5bd4150..9b342eaf95aec97830e155a00250d3d419e6d24d 100644 (file)
@@ -3,6 +3,7 @@ CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="tb10x"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -26,12 +27,10 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLOCK is not set
 CONFIG_ARC_PLAT_TB10X=y
 CONFIG_ARC_CACHE_LINE_SHIFT=5
-CONFIG_ARC_STACK_NONEXEC=y
 CONFIG_HZ=250
 CONFIG_ARC_BUILTIN_DTB_NAME="abilis_tb100_dvk"
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -44,8 +43,8 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_PROC_DEVICETREE=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
@@ -55,9 +54,6 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_STMMAC_ETH=y
-CONFIG_STMMAC_DEBUG_FS=y
-CONFIG_STMMAC_DA=y
-CONFIG_STMMAC_CHAINED=y
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
@@ -91,7 +87,6 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_LEDS_TRIGGER_TRANSIENT=y
 CONFIG_DMADEVICES=y
 CONFIG_DW_DMAC=y
-CONFIG_NET_DMA=y
 CONFIG_ASYNC_TX_DMA=y
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
@@ -100,17 +95,16 @@ CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_DEBUG_INFO=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_DEBUG_STACKOVERFLOW=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
index f36c047b33cad0c469bd2368bb3e5fa4260535e5..735985974a3136d2a1b1d6184ff754efd0a02743 100644 (file)
@@ -16,7 +16,7 @@ CONFIG_ARC_PLAT_AXS10X=y
 CONFIG_AXS103=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
-# CONFIG_ARC_HAS_GRTC is not set
+# CONFIG_ARC_HAS_GFRC is not set
 CONFIG_ARC_UBOOT_SUPPORT=y
 CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp"
 CONFIG_PREEMPT=y
index 7fac7d85ed6a32bb1abaa4f8e36c5d243cec06c0..f9f4c6f59fdbb3f450ec13420e94f2ee1cb4428c 100644 (file)
@@ -10,7 +10,8 @@
 #define _ASM_ARC_ARCREGS_H
 
 /* Build Configuration Registers */
-#define ARC_REG_DCCMBASE_BCR   0x61    /* DCCM Base Addr */
+#define ARC_REG_AUX_DCCM       0x18    /* DCCM Base Addr ARCv2 */
+#define ARC_REG_DCCM_BASE_BUILD        0x61    /* DCCM Base Addr ARCompact */
 #define ARC_REG_CRC_BCR                0x62
 #define ARC_REG_VECBASE_BCR    0x68
 #define ARC_REG_PERIBASE_BCR   0x69
 #define ARC_REG_DPFP_BCR       0x6C    /* ARCompact: Dbl Precision FPU */
 #define ARC_REG_FP_V2_BCR      0xc8    /* ARCv2 FPU */
 #define ARC_REG_SLC_BCR                0xce
-#define ARC_REG_DCCM_BCR       0x74    /* DCCM Present + SZ */
+#define ARC_REG_DCCM_BUILD     0x74    /* DCCM size (common) */
 #define ARC_REG_TIMERS_BCR     0x75
 #define ARC_REG_AP_BCR         0x76
-#define ARC_REG_ICCM_BCR       0x78
+#define ARC_REG_ICCM_BUILD     0x78    /* ICCM size (common) */
 #define ARC_REG_XY_MEM_BCR     0x79
 #define ARC_REG_MAC_BCR                0x7a
 #define ARC_REG_MUL_BCR                0x7b
@@ -36,6 +37,7 @@
 #define ARC_REG_IRQ_BCR                0xF3
 #define ARC_REG_SMART_BCR      0xFF
 #define ARC_REG_CLUSTER_BCR    0xcf
+#define ARC_REG_AUX_ICCM       0x208   /* ICCM Base Addr (ARCv2) */
 
 /* status32 Bits Positions */
 #define STATUS_AE_BIT          5       /* Exception active */
@@ -246,7 +248,7 @@ struct bcr_perip {
 #endif
 };
 
-struct bcr_iccm {
+struct bcr_iccm_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int base:16, pad:5, sz:3, ver:8;
 #else
@@ -254,17 +256,15 @@ struct bcr_iccm {
 #endif
 };
 
-/* DCCM Base Address Register: ARC_REG_DCCMBASE_BCR */
-struct bcr_dccm_base {
+struct bcr_iccm_arcv2 {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int addr:24, ver:8;
+       unsigned int pad:8, sz11:4, sz01:4, sz10:4, sz00:4, ver:8;
 #else
-       unsigned int ver:8, addr:24;
+       unsigned int ver:8, sz00:4, sz10:4, sz01:4, sz11:4, pad:8;
 #endif
 };
 
-/* DCCM RAM Configuration Register: ARC_REG_DCCM_BCR */
-struct bcr_dccm {
+struct bcr_dccm_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int res:21, sz:3, ver:8;
 #else
@@ -272,6 +272,14 @@ struct bcr_dccm {
 #endif
 };
 
+struct bcr_dccm_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:12, cyc:3, pad1:1, sz1:4, sz0:4, ver:8;
+#else
+       unsigned int ver:8, sz0:4, sz1:4, pad1:1, cyc:3, pad2:12;
+#endif
+};
+
 /* ARCompact: Both SP and DP FPU BCRs have same format */
 struct bcr_fp_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -315,9 +323,9 @@ struct bcr_bpu_arcv2 {
 
 struct bcr_generic {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad:24, ver:8;
+       unsigned int info:24, ver:8;
 #else
-       unsigned int ver:8, pad:24;
+       unsigned int ver:8, info:24;
 #endif
 };
 
@@ -349,14 +357,13 @@ struct cpuinfo_arc {
        struct cpuinfo_arc_bpu bpu;
        struct bcr_identity core;
        struct bcr_isa isa;
-       struct bcr_timer timers;
        unsigned int vec_base;
        struct cpuinfo_arc_ccm iccm, dccm;
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
                             fpu_sp:1, fpu_dp:1, pad2:6,
                             debug:1, ap:1, smart:1, rtt:1, pad3:4,
-                            pad4:8;
+                            timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
        } extn;
        struct bcr_mpy extn_mpy;
        struct bcr_extn_xymem extn_xymem;
index 4fd7d62a6e30aa513b9e04f6ee881c219b96da96..49014f0ef36d19458203b904f41513f776aeedff 100644 (file)
 #ifdef CONFIG_ISA_ARCOMPACT
 #define TIMER0_IRQ      3
 #define TIMER1_IRQ      4
-#define IPI_IRQ                (NR_CPU_IRQS-1) /* dummy to enable SMP build for up hardware */
 #else
 #define TIMER0_IRQ      16
 #define TIMER1_IRQ      17
-#define IPI_IRQ         19
 #endif
 
 #include <linux/interrupt.h>
index 258b0e5ad3329a614e59204df55d91873e969623..37c2f751eebf03d8f9f16d997bacdcb5b8f6323f 100644 (file)
@@ -22,6 +22,7 @@
 #define AUX_IRQ_CTRL           0x00E
 #define AUX_IRQ_ACT            0x043   /* Active Intr across all levels */
 #define AUX_IRQ_LVL_PEND       0x200   /* Pending Intr across all levels */
+#define AUX_IRQ_HINT           0x201   /* For generating Soft Interrupts */
 #define AUX_IRQ_PRIORITY       0x206
 #define ICAUSE                 0x40a
 #define AUX_IRQ_SELECT         0x40b
 /* Was Intr taken in User Mode */
 #define AUX_IRQ_ACT_BIT_U      31
 
-/* 0 is highest level, but taken by FIRQs, if present in design */
-#define ARCV2_IRQ_DEF_PRIO             0
+/*
+ * User space should be interruptable even by lowest prio interrupt
+ * Safe even if actual interrupt priorities is fewer or even one
+ */
+#define ARCV2_IRQ_DEF_PRIO     15
 
 /* seed value for status register */
 #define ISA_INIT_STATUS_BITS   (STATUS_IE_MASK | STATUS_AD_MASK | \
@@ -112,6 +116,16 @@ static inline int arch_irqs_disabled(void)
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
+static inline void arc_softirq_trigger(int irq)
+{
+       write_aux_reg(AUX_IRQ_HINT, irq);
+}
+
+static inline void arc_softirq_clear(int irq)
+{
+       write_aux_reg(AUX_IRQ_HINT, 0);
+}
+
 #else
 
 .macro IRQ_DISABLE  scratch
index 46f4e5351b2a56e96d440a27201fc612d2e9c195..847e3bbe387fc92f9b4433bf7e08fc0b11e3ec70 100644 (file)
@@ -39,8 +39,8 @@ struct mcip_cmd {
 #define CMD_DEBUG_SET_MASK             0x34
 #define CMD_DEBUG_SET_SELECT           0x36
 
-#define CMD_GRTC_READ_LO               0x42
-#define CMD_GRTC_READ_HI               0x43
+#define CMD_GFRC_READ_LO               0x42
+#define CMD_GFRC_READ_HI               0x43
 
 #define CMD_IDU_ENABLE                 0x71
 #define CMD_IDU_DISABLE                        0x72
index 57af2f05ae8459e2ee2427d231370269894ba95f..d426d4215513333289ac85bebea412015e7562d2 100644 (file)
 #define __S111  PAGE_U_X_W_R
 
 /****************************************************************
- * Page Table Lookup split
+ * 2 tier (PGD:PTE) software page walker
  *
- * We implement 2 tier paging and since this is all software, we are free
- * to customize the span of a PGD / PTE entry to suit us
- *
- *                     32 bit virtual address
+ * [31]                    32 bit virtual address              [0]
  * -------------------------------------------------------
- * | BITS_FOR_PGD    |  BITS_FOR_PTE    |  BITS_IN_PAGE  |
+ * |               | <------------ PGDIR_SHIFT ----------> |
+ * |              |                                     |
+ * | BITS_FOR_PGD  |  BITS_FOR_PTE  | <-- PAGE_SHIFT --> |
  * -------------------------------------------------------
  *       |                  |                |
  *       |                  |                --> off in page frame
- *       |                 |
  *       |                  ---> index into Page Table
- *       |
  *       ----> index into Page Directory
+ *
+ * In a single page size configuration, only PAGE_SHIFT is fixed
+ * So both PGD and PTE sizing can be tweaked
+ *  e.g. 8K page (PAGE_SHIFT 13) can have
+ *  - PGDIR_SHIFT 21  -> 11:8:13 address split
+ *  - PGDIR_SHIFT 24  -> 8:11:13 address split
+ *
+ * If Super Page is configured, PGDIR_SHIFT becomes fixed too,
+ * so the sizing flexibility is gone.
  */
 
-#define BITS_IN_PAGE   PAGE_SHIFT
-
-/* Optimal Sizing of Pg Tbl - based on MMU page size */
-#if defined(CONFIG_ARC_PAGE_SIZE_8K)
-#define BITS_FOR_PTE   8               /* 11:8:13 */
-#elif defined(CONFIG_ARC_PAGE_SIZE_16K)
-#define BITS_FOR_PTE   8               /* 10:8:14 */
-#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
-#define BITS_FOR_PTE   9               /* 11:9:12 */
+#if defined(CONFIG_ARC_HUGEPAGE_16M)
+#define PGDIR_SHIFT    24
+#elif defined(CONFIG_ARC_HUGEPAGE_2M)
+#define PGDIR_SHIFT    21
+#else
+/*
+ * Only Normal page support so "hackable" (see comment above)
+ * Default value provides 11:8:13 (8K), 11:9:12 (4K)
+ */
+#define PGDIR_SHIFT    21
 #endif
 
-#define BITS_FOR_PGD   (32 - BITS_FOR_PTE - BITS_IN_PAGE)
+#define BITS_FOR_PTE   (PGDIR_SHIFT - PAGE_SHIFT)
+#define BITS_FOR_PGD   (32 - PGDIR_SHIFT)
 
-#define PGDIR_SHIFT    (32 - BITS_FOR_PGD)
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)    /* vaddr span, not PDG sz */
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
index cbfec79137bf77735fa675d0eb2be57da217ba63..c1264607bbff3dca457fd47b8f078b62993b7af7 100644 (file)
@@ -45,11 +45,12 @@ VECTOR      reserved                ; Reserved slots
 VECTOR handle_interrupt        ; (16) Timer0
 VECTOR handle_interrupt        ; unused (Timer1)
 VECTOR handle_interrupt        ; unused (WDT)
-VECTOR handle_interrupt        ; (19) ICI (inter core interrupt)
-VECTOR handle_interrupt
-VECTOR handle_interrupt
-VECTOR handle_interrupt
-VECTOR handle_interrupt        ; (23) End of fixed IRQs
+VECTOR handle_interrupt        ; (19) Inter core Interrupt (IPI)
+VECTOR handle_interrupt        ; (20) perf Interrupt
+VECTOR handle_interrupt        ; (21) Software Triggered Intr (Self IPI)
+VECTOR handle_interrupt        ; unused
+VECTOR handle_interrupt        ; (23) unused
+# End of fixed IRQs
 
 .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
        VECTOR  handle_interrupt
@@ -211,7 +212,11 @@ debug_marker_syscall:
 ; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig
 ; entry was via Exception in DS which got preempted in kernel).
 ;
-; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling
+; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround
+;
+; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline
+; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly
+
 .Lintr_ret_to_delay_slot:
 debug_marker_ds:
 
@@ -222,18 +227,23 @@ debug_marker_ds:
        ld      r2, [sp, PT_ret]
        ld      r3, [sp, PT_status32]
 
+       ; STAT32 for Int return created from scratch
+       ; (No delay dlot, disable Further intr in trampoline)
+
        bic     r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK
        st      r0, [sp, PT_status32]
 
        mov     r1, .Lintr_ret_to_delay_slot_2
        st      r1, [sp, PT_ret]
 
+       ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots
        st      r2, [sp, 0]
        st      r3, [sp, 4]
 
        b       .Lisr_ret_fast_path
 
 .Lintr_ret_to_delay_slot_2:
+       ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP
        sub     sp, sp, SZ_PT_REGS
        st      r9, [sp, -4]
 
@@ -243,11 +253,19 @@ debug_marker_ds:
        ld      r9, [sp, 4]
        sr      r9, [erstatus]
 
+       ; restore AUX_USER_SP if returning to U mode
+       bbit0   r9, STATUS_U_BIT, 1f
+       ld      r9, [sp, PT_sp]
+       sr      r9, [AUX_USER_SP]
+
+1:
        ld      r9, [sp, 8]
        sr      r9, [erbta]
 
        ld      r9, [sp, -4]
        add     sp, sp, SZ_PT_REGS
+
+       ; return from pure kernel mode to delay slot
        rtie
 
 END(ret_from_exception)
index 0394f9f61b466dea018af3ec371c65a8dbc17acb..942526322ae7125cb1e7910adb0523ed16ae7435 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/irqchip.h>
 #include <asm/irq.h>
 
+static int irq_prio;
+
 /*
  * Early Hardware specific Interrupt setup
  * -Called very early (start_kernel -> setup_arch -> setup_processor)
@@ -24,6 +26,14 @@ void arc_init_IRQ(void)
 {
        unsigned int tmp;
 
+       struct irq_build {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int pad:3, firq:1, prio:4, exts:8, irqs:8, ver:8;
+#else
+               unsigned int ver:8, irqs:8, exts:8, prio:4, firq:1, pad:3;
+#endif
+       } irq_bcr;
+
        struct aux_irq_ctrl {
 #ifdef CONFIG_CPU_BIG_ENDIAN
                unsigned int res3:18, save_idx_regs:1, res2:1,
@@ -46,28 +56,25 @@ void arc_init_IRQ(void)
 
        WRITE_AUX(AUX_IRQ_CTRL, ictrl);
 
-       /* setup status32, don't enable intr yet as kernel doesn't want */
-       tmp = read_aux_reg(0xa);
-       tmp |= ISA_INIT_STATUS_BITS;
-       tmp &= ~STATUS_IE_MASK;
-       asm volatile("flag %0   \n"::"r"(tmp));
-
        /*
         * ARCv2 core intc provides multiple interrupt priorities (upto 16).
         * Typical builds though have only two levels (0-high, 1-low)
         * Linux by default uses lower prio 1 for most irqs, reserving 0 for
         * NMI style interrupts in future (say perf)
-        *
-        * Read the intc BCR to confirm that Linux default priority is avail
-        * in h/w
-        *
-        * Note:
-        *  IRQ_BCR[27..24] contains N-1 (for N priority levels) and prio level
-        *  is 0 based.
         */
-       tmp = (read_aux_reg(ARC_REG_IRQ_BCR) >> 24 ) & 0xF;
-       if (ARCV2_IRQ_DEF_PRIO > tmp)
-               panic("Linux default irq prio incorrect\n");
+
+       READ_BCR(ARC_REG_IRQ_BCR, irq_bcr);
+
+       irq_prio = irq_bcr.prio;        /* Encoded as N-1 for N levels */
+       pr_info("archs-intc\t: %d priority levels (default %d)%s\n",
+               irq_prio + 1, irq_prio,
+               irq_bcr.firq ? " FIRQ (not used)":"");
+
+       /* setup status32, don't enable intr yet as kernel doesn't want */
+       tmp = read_aux_reg(0xa);
+       tmp |= STATUS_AD_MASK | (irq_prio << 1);
+       tmp &= ~STATUS_IE_MASK;
+       asm volatile("flag %0   \n"::"r"(tmp));
 }
 
 static void arcv2_irq_mask(struct irq_data *data)
@@ -86,7 +93,7 @@ void arcv2_irq_enable(struct irq_data *data)
 {
        /* set default priority */
        write_aux_reg(AUX_IRQ_SELECT, data->irq);
-       write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+       write_aux_reg(AUX_IRQ_PRIORITY, irq_prio);
 
        /*
         * hw auto enables (linux unmask) all by default
index 06bcedf19b622b4ef26503660349bc07a8a52d2e..224d1c3aa9c41dafdf52554450c2fa3b32ac8689 100644 (file)
@@ -81,9 +81,6 @@ static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
 {
        switch (irq) {
        case TIMER0_IRQ:
-#ifdef CONFIG_SMP
-       case IPI_IRQ:
-#endif
                irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
                break;
        default:
index bd237acdf4f2f9601efbf4c25c45067ddd2b69d9..c41c364b926cab9f50b6550e501f3ea1a8300017 100644 (file)
 #include <linux/smp.h>
 #include <linux/irq.h>
 #include <linux/spinlock.h>
+#include <asm/irqflags-arcv2.h>
 #include <asm/mcip.h>
 #include <asm/setup.h>
 
+#define IPI_IRQ                19
+#define SOFTIRQ_IRQ    21
+
 static char smp_cpuinfo_buf[128];
 static int idu_detected;
 
@@ -22,6 +26,7 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
 static void mcip_setup_per_cpu(int cpu)
 {
        smp_ipi_irq_setup(cpu, IPI_IRQ);
+       smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
 }
 
 static void mcip_ipi_send(int cpu)
@@ -29,46 +34,44 @@ static void mcip_ipi_send(int cpu)
        unsigned long flags;
        int ipi_was_pending;
 
+       /* ARConnect can only send IPI to others */
+       if (unlikely(cpu == raw_smp_processor_id())) {
+               arc_softirq_trigger(SOFTIRQ_IRQ);
+               return;
+       }
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+
        /*
-        * NOTE: We must spin here if the other cpu hasn't yet
-        * serviced a previous message. This can burn lots
-        * of time, but we MUST follows this protocol or
-        * ipi messages can be lost!!!
-        * Also, we must release the lock in this loop because
-        * the other side may get to this same loop and not
-        * be able to ack -- thus causing deadlock.
+        * If receiver already has a pending interrupt, elide sending this one.
+        * Linux cross core calling works well with concurrent IPIs
+        * coalesced into one
+        * see arch/arc/kernel/smp.c: ipi_send_msg_one()
         */
+       __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu);
+       ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK);
+       if (!ipi_was_pending)
+               __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu);
 
-       do {
-               raw_spin_lock_irqsave(&mcip_lock, flags);
-               __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu);
-               ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK);
-               if (ipi_was_pending == 0)
-                       break; /* break out but keep lock */
-               raw_spin_unlock_irqrestore(&mcip_lock, flags);
-       } while (1);
-
-       __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu);
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
-
-#ifdef CONFIG_ARC_IPI_DBG
-       if (ipi_was_pending)
-               pr_info("IPI ACK delayed from cpu %d\n", cpu);
-#endif
 }
 
 static void mcip_ipi_clear(int irq)
 {
        unsigned int cpu, c;
        unsigned long flags;
-       unsigned int __maybe_unused copy;
+
+       if (unlikely(irq == SOFTIRQ_IRQ)) {
+               arc_softirq_clear(irq);
+               return;
+       }
 
        raw_spin_lock_irqsave(&mcip_lock, flags);
 
        /* Who sent the IPI */
        __mcip_cmd(CMD_INTRPT_CHECK_SOURCE, 0);
 
-       copy = cpu = read_aux_reg(ARC_REG_MCIP_READBACK);       /* 1,2,4,8... */
+       cpu = read_aux_reg(ARC_REG_MCIP_READBACK);      /* 1,2,4,8... */
 
        /*
         * In rare case, multiple concurrent IPIs sent to same target can
@@ -82,12 +85,6 @@ static void mcip_ipi_clear(int irq)
        } while (cpu);
 
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
-
-#ifdef CONFIG_ARC_IPI_DBG
-       if (c != __ffs(copy))
-               pr_info("IPIs from %x coalesced to %x\n",
-                       copy, raw_smp_processor_id());
-#endif
 }
 
 static void mcip_probe_n_setup(void)
@@ -96,13 +93,13 @@ static void mcip_probe_n_setup(void)
 #ifdef CONFIG_CPU_BIG_ENDIAN
                unsigned int pad3:8,
                             idu:1, llm:1, num_cores:6,
-                            iocoh:1,  grtc:1, dbg:1, pad2:1,
+                            iocoh:1,  gfrc:1, dbg:1, pad2:1,
                             msg:1, sem:1, ipi:1, pad:1,
                             ver:8;
 #else
                unsigned int ver:8,
                             pad:1, ipi:1, sem:1, msg:1,
-                            pad2:1, dbg:1, grtc:1, iocoh:1,
+                            pad2:1, dbg:1, gfrc:1, iocoh:1,
                             num_cores:6, llm:1, idu:1,
                             pad3:8;
 #endif
@@ -111,12 +108,13 @@ static void mcip_probe_n_setup(void)
        READ_BCR(ARC_REG_MCIP_BCR, mp);
 
        sprintf(smp_cpuinfo_buf,
-               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n",
+               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s%s\n",
                mp.ver, mp.num_cores,
                IS_AVAIL1(mp.ipi, "IPI "),
                IS_AVAIL1(mp.idu, "IDU "),
+               IS_AVAIL1(mp.llm, "LLM "),
                IS_AVAIL1(mp.dbg, "DEBUG "),
-               IS_AVAIL1(mp.grtc, "GRTC"));
+               IS_AVAIL1(mp.gfrc, "GFRC"));
 
        idu_detected = mp.idu;
 
@@ -125,8 +123,8 @@ static void mcip_probe_n_setup(void)
                __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf);
        }
 
-       if (IS_ENABLED(CONFIG_ARC_HAS_GRTC) && !mp.grtc)
-               panic("kernel trying to use non-existent GRTC\n");
+       if (IS_ENABLED(CONFIG_ARC_HAS_GFRC) && !mp.gfrc)
+               panic("kernel trying to use non-existent GFRC\n");
 }
 
 struct plat_smp_ops plat_smp_ops = {
index e1b87444ea9a0740b9651ad6b68fd39f701121a0..cdc821df1809209df9792bcf9ecada0bc991753f 100644 (file)
@@ -42,9 +42,57 @@ struct task_struct *_current_task[NR_CPUS];  /* For stack switching */
 
 struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
 
+static void read_decode_ccm_bcr(struct cpuinfo_arc *cpu)
+{
+       if (is_isa_arcompact()) {
+               struct bcr_iccm_arcompact iccm;
+               struct bcr_dccm_arcompact dccm;
+
+               READ_BCR(ARC_REG_ICCM_BUILD, iccm);
+               if (iccm.ver) {
+                       cpu->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */
+                       cpu->iccm.base_addr = iccm.base << 16;
+               }
+
+               READ_BCR(ARC_REG_DCCM_BUILD, dccm);
+               if (dccm.ver) {
+                       unsigned long base;
+                       cpu->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */
+
+                       base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD);
+                       cpu->dccm.base_addr = base & ~0xF;
+               }
+       } else {
+               struct bcr_iccm_arcv2 iccm;
+               struct bcr_dccm_arcv2 dccm;
+               unsigned long region;
+
+               READ_BCR(ARC_REG_ICCM_BUILD, iccm);
+               if (iccm.ver) {
+                       cpu->iccm.sz = 256 << iccm.sz00;        /* 512B to 16M */
+                       if (iccm.sz00 == 0xF && iccm.sz01 > 0)
+                               cpu->iccm.sz <<= iccm.sz01;
+
+                       region = read_aux_reg(ARC_REG_AUX_ICCM);
+                       cpu->iccm.base_addr = region & 0xF0000000;
+               }
+
+               READ_BCR(ARC_REG_DCCM_BUILD, dccm);
+               if (dccm.ver) {
+                       cpu->dccm.sz = 256 << dccm.sz0;
+                       if (dccm.sz0 == 0xF && dccm.sz1 > 0)
+                               cpu->dccm.sz <<= dccm.sz1;
+
+                       region = read_aux_reg(ARC_REG_AUX_DCCM);
+                       cpu->dccm.base_addr = region & 0xF0000000;
+               }
+       }
+}
+
 static void read_arc_build_cfg_regs(void)
 {
        struct bcr_perip uncached_space;
+       struct bcr_timer timer;
        struct bcr_generic bcr;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        unsigned long perip_space;
@@ -53,7 +101,11 @@ static void read_arc_build_cfg_regs(void)
        READ_BCR(AUX_IDENTITY, cpu->core);
        READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
 
-       READ_BCR(ARC_REG_TIMERS_BCR, cpu->timers);
+       READ_BCR(ARC_REG_TIMERS_BCR, timer);
+       cpu->extn.timer0 = timer.t0;
+       cpu->extn.timer1 = timer.t1;
+       cpu->extn.rtc = timer.rtc;
+
        cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
 
        READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
@@ -71,36 +123,11 @@ static void read_arc_build_cfg_regs(void)
        cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0;        /* 1,3 */
        cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
        cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
-
-       /* Note that we read the CCM BCRs independent of kernel config
-        * This is to catch the cases where user doesn't know that
-        * CCMs are present in hardware build
-        */
-       {
-               struct bcr_iccm iccm;
-               struct bcr_dccm dccm;
-               struct bcr_dccm_base dccm_base;
-               unsigned int bcr_32bit_val;
-
-               bcr_32bit_val = read_aux_reg(ARC_REG_ICCM_BCR);
-               if (bcr_32bit_val) {
-                       iccm = *((struct bcr_iccm *)&bcr_32bit_val);
-                       cpu->iccm.base_addr = iccm.base << 16;
-                       cpu->iccm.sz = 0x2000 << (iccm.sz - 1);
-               }
-
-               bcr_32bit_val = read_aux_reg(ARC_REG_DCCM_BCR);
-               if (bcr_32bit_val) {
-                       dccm = *((struct bcr_dccm *)&bcr_32bit_val);
-                       cpu->dccm.sz = 0x800 << (dccm.sz);
-
-                       READ_BCR(ARC_REG_DCCMBASE_BCR, dccm_base);
-                       cpu->dccm.base_addr = dccm_base.addr << 8;
-               }
-       }
-
        READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem);
 
+       /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */
+       read_decode_ccm_bcr(cpu);
+
        read_decode_mmu_bcr();
        read_decode_cache_bcr();
 
@@ -208,9 +235,9 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       (unsigned int)(arc_get_core_freq() / 10000) % 100);
 
        n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
-                      IS_AVAIL1(cpu->timers.t0, "Timer0 "),
-                      IS_AVAIL1(cpu->timers.t1, "Timer1 "),
-                      IS_AVAIL2(cpu->timers.rtc, "64-bit RTC ",
+                      IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
+                      IS_AVAIL1(cpu->extn.timer1, "Timer1 "),
+                      IS_AVAIL2(cpu->extn.rtc, "Local-64-bit-Ctr ",
                                 CONFIG_ARC_HAS_RTC));
 
        n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
@@ -232,8 +259,6 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
                        n += scnprintf(buf + n, len - n, "mpy[opt %d] ", opt);
                }
-               n += scnprintf(buf + n, len - n, "%s",
-                              IS_USED_CFG(CONFIG_ARC_HAS_HW_MPY));
        }
 
        n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
@@ -293,13 +318,13 @@ static void arc_chk_core_config(void)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        int fpu_enabled;
 
-       if (!cpu->timers.t0)
+       if (!cpu->extn.timer0)
                panic("Timer0 is not present!\n");
 
-       if (!cpu->timers.t1)
+       if (!cpu->extn.timer1)
                panic("Timer1 is not present!\n");
 
-       if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->timers.rtc)
+       if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->extn.rtc)
                panic("RTC is not present\n");
 
 #ifdef CONFIG_ARC_HAS_DCCM
@@ -334,6 +359,7 @@ static void arc_chk_core_config(void)
                panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
 
        if (is_isa_arcv2() && IS_ENABLED(CONFIG_SMP) && cpu->isa.atomic &&
+           IS_ENABLED(CONFIG_ARC_HAS_LLSC) &&
            !IS_ENABLED(CONFIG_ARC_STAR_9000923308))
                panic("llock/scond livelock workaround missing\n");
 }
index ef6e9e15b82abf72d946ab45c3e20096854605c5..424e937da5c897d02cca7b1bd5781614f8d5d045 100644 (file)
@@ -336,11 +336,8 @@ irqreturn_t do_IPI(int irq, void *dev_id)
                int rc;
 
                rc = __do_IPI(msg);
-#ifdef CONFIG_ARC_IPI_DBG
-               /* IPI received but no valid @msg */
                if (rc)
                        pr_info("IPI with bogus msg %ld in %ld\n", msg, copy);
-#endif
                pending &= ~(1U << msg);
        } while (pending);
 
index dfad287f1db1c6b55b86faacc0b40d2472636795..156d9833ff84b5c77b7a7bd95d2be15c81d7cbf9 100644 (file)
@@ -62,7 +62,7 @@
 
 /********** Clock Source Device *********/
 
-#ifdef CONFIG_ARC_HAS_GRTC
+#ifdef CONFIG_ARC_HAS_GFRC
 
 static int arc_counter_setup(void)
 {
@@ -83,10 +83,10 @@ static cycle_t arc_counter_read(struct clocksource *cs)
 
        local_irq_save(flags);
 
-       __mcip_cmd(CMD_GRTC_READ_LO, 0);
+       __mcip_cmd(CMD_GFRC_READ_LO, 0);
        stamp.l = read_aux_reg(ARC_REG_MCIP_READBACK);
 
-       __mcip_cmd(CMD_GRTC_READ_HI, 0);
+       __mcip_cmd(CMD_GFRC_READ_HI, 0);
        stamp.h = read_aux_reg(ARC_REG_MCIP_READBACK);
 
        local_irq_restore(flags);
@@ -95,7 +95,7 @@ static cycle_t arc_counter_read(struct clocksource *cs)
 }
 
 static struct clocksource arc_counter = {
-       .name   = "ARConnect GRTC",
+       .name   = "ARConnect GFRC",
        .rating = 400,
        .read   = arc_counter_read,
        .mask   = CLOCKSOURCE_MASK(64),
index 7a6a58ef8aaf815728fd59b0ca7af752495595b0..43788b1a1ac5e64372e1f3d3b012ba97a2e2d6ea 100644 (file)
@@ -195,5 +195,7 @@ CFLAGS_font.o := -Dstatic=
 $(obj)/font.c: $(FONTC)
        $(call cmd,shipped)
 
+AFLAGS_hyp-stub.o := -Wa,-march=armv7-a
+
 $(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
        $(call cmd,shipped)
index f3db13d2d90e7d457954c2cd93f3b9df45cb57d2..0cc150b87b86271a7b177afbbc5da952f70aa636 100644 (file)
        };
 };
 
+
+/include/ "tps65217.dtsi"
+
 &tps {
-       compatible = "ti,tps65217";
        /*
         * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
         * mode") at poweroff.  Most BeagleBone versions do not support RTC-only
        ti,pmic-shutdown-controller;
 
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        regulator-name = "vdds_dpr";
                        regulator-always-on;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        regulator-name = "vio,vrtc,vdds";
                        regulator-always-on;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        regulator-name = "vdd_3v3aux";
                        regulator-always-on;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        regulator-name = "vdd_1v8";
                        regulator-always-on;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        regulator-name = "vdd_3v3a";
                        regulator-always-on;
                };
index fda457b07e15c282887ede12eee576d56c6f3855..857d9894103a9edf6a7754585b5dddd6276d74e6 100644 (file)
 
 };
 
-&tps {
-       compatible = "ti,tps65217";
+/include/ "tps65217.dtsi"
 
+&tps {
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        regulator-name = "vdds_dpr";
                        regulator-always-on;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        regulator-name = "vio,vrtc,vdds";
                        regulator-boot-on;
                        regulator-always-on;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        regulator-name = "vdd_3v3aux";
                        regulator-boot-on;
                        regulator-always-on;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        regulator-name = "vdd_1v8";
                        regulator-boot-on;
                        regulator-always-on;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        regulator-name = "vdd_3v3d";
                        regulator-boot-on;
                        regulator-always-on;
index 77559a1ded60fb4530d90aef42323ca187ed6ac9..f313999c503e1df2add311257af95594d51e464e 100644 (file)
        wp-gpios = <&gpio3 18 0>;
 };
 
-&tps {
-       compatible = "ti,tps65217";
+#include "tps65217.dtsi"
 
+&tps {
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        /* +1.5V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <1450000>;
                        regulator-max-microvolt = <1550000>;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.1V with Â±4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <915000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with Â±4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <915000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        /* +1.8V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <1750000>;
                        regulator-max-microvolt = <1870000>;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        /* +3.3V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <3175000>;
                        regulator-max-microvolt = <3430000>;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        /* +1.8V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <1750000>;
                        regulator-max-microvolt = <1870000>;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        /* +3.3V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <3175000>;
                        regulator-max-microvolt = <3430000>;
index 471a3a70ea1f173ce15190f77443e6860e15c328..8867aaaec54d565de7f147af80e2e1cb6c4b2967 100644 (file)
        vin-supply = <&vbat>;
 };
 
-&tps {
-       compatible = "ti,tps65217";
+/include/ "tps65217.dtsi"
 
+&tps {
        backlight {
                isel = <1>; /* ISET1 */
                fdim = <200>; /* TPS65217_BL_FDIM_200HZ */
        };
 
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        /* VDD_1V8 system supply */
                        regulator-always-on;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        /* VRTC 1.8V always-on supply */
                        regulator-name = "vrtc,vdds";
                        regulator-always-on;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        /* 3.3V rail */
                        regulator-name = "vdd_3v3aux";
                        regulator-always-on;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        /* VDD_3V3A 3.3V rail */
                        regulator-name = "vdd_3v3a";
                        regulator-min-microvolt = <3300000>;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        /* VDD_3V3B 3.3V rail */
                        regulator-name = "vdd_3v3b";
                        regulator-always-on;
index 1b5b044fcd910bc316863370ba4cfe6cab976530..865de8500f1c85cb8505dcf5d35c07c4a660aed9 100644 (file)
@@ -46,7 +46,7 @@
                        gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
                        linux,code = <KEY_BACK>;
                        debounce-interval = <1000>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                front_button {
@@ -54,7 +54,7 @@
                        gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
                        linux,code = <KEY_FRONT>;
                        debounce-interval = <1000>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index d38edfa53bb9a95df14936af36dc600c55e8e2bc..3303c281697b017901f103aa96fee5af0a25ef8a 100644 (file)
        pinctrl-0 = <&uart4_pins>;
 };
 
+#include "tps65217.dtsi"
+
 &tps {
-       compatible = "ti,tps65217";
        ti,pmic-shutdown-controller;
 
        interrupt-parent = <&intc>;
        interrupts = <7>;       /* NNMI */
 
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        /* VDDS_DDR */
                        regulator-min-microvolt = <1500000>;
                        regulator-max-microvolt = <1500000>;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        /* VRTC / VIO / VDDS*/
                        regulator-always-on;
                        regulator-min-microvolt = <1800000>;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        /* VDD_3V3AUX */
                        regulator-always-on;
                        regulator-min-microvolt = <3300000>;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        /* VDD_1V8 */
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        /* VDD_3V3A */
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
index 36c0fa6c362ae32000701ffec7e81df73f2a187a..a0986c65be0cfa71856947c58f57abe8df61c7fd 100644 (file)
 
                sound0_master: simple-audio-card,codec {
                        sound-dai = <&tlv320aic3104>;
+                       assigned-clocks = <&clkoutmux2_clk_mux>;
+                       assigned-clock-parents = <&sys_clk2_dclk_div>;
                        clocks = <&clkout2_clk>;
                };
        };
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&mcasp3_pins_default>;
        pinctrl-1 = <&mcasp3_pins_sleep>;
+       assigned-clocks = <&mcasp3_ahclkx_mux>;
+       assigned-clock-parents = <&sys_clkin2>;
        status = "okay";
 
        op-mode = <0>;  /* MCASP_IIS_MODE */
index 8d93882dc8d541a77c870e635813c32a7c77b79d..1c06cb76da07c14132e60cd29f5406dab9e9db66 100644 (file)
                ti,debounce-tol = /bits/ 16 <10>;
                ti,debounce-rep = /bits/ 16 <1>;
 
-               linux,wakeup;
+               wakeup-source;
        };
 };
 
index 4f6ae921656f16dfd3814d7a70972be798e0fce9..f74d3db4846dacacd54b37e9cb1d35d707689368 100644 (file)
                                #size-cells = <1>;
                                reg = <0x2100000 0x10000>;
                                ranges = <0 0x2100000 0x10000>;
-                               interrupt-parent = <&intc>;
                                clocks = <&clks IMX6QDL_CLK_CAAM_MEM>,
                                         <&clks IMX6QDL_CLK_CAAM_ACLK>,
                                         <&clks IMX6QDL_CLK_CAAM_IPG>,
index bf4143c6cb8f10991d4abbaae126966f9f9c753c..b84af3da8c84d596b2b950489541c4efd9216783 100644 (file)
@@ -14,7 +14,7 @@
 #include "kirkwood-synology.dtsi"
 
 / {
-       model = "Synology DS111";
+       model = "Synology DS112";
        compatible = "synology,ds111", "marvell,kirkwood";
 
        memory {
index 420788229e6f8a30b6c3a114018c209ebad151c4..aae8a7aceab75d53f84a2eb94fc0d6e020e773a9 100644 (file)
        };
 };
 
+&devbus_bootcs {
+       status = "okay";
+       devbus,keep-config;
+
+       flash@0 {
+               compatible = "jedec-flash";
+               reg = <0 0x40000>;
+               bank-width = <1>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       header@0 {
+                               reg = <0 0x30000>;
+                               read-only;
+                       };
+
+                       uboot@30000 {
+                               reg = <0x30000 0xF000>;
+                               read-only;
+                       };
+
+                       uboot_env@3F000 {
+                               reg = <0x3F000 0x1000>;
+                       };
+               };
+       };
+};
+
 &mdio {
        status = "okay";
 
index 6713b1ea732b0b1d2282368ce5b50e42a9ae6043..01d239c3eaaaa3fe4ca8ab7854fbca9faa3e23e4 100644 (file)
        pinctrl-names = "default";
 
        status = "okay";
-       renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>;
 };
 
 &usbphy {
index 1afe24629d1f85de2a9ec3f8ef62c6372d014abd..b0c912feaa2f0e016b65ff27e272b82c2b0795ed 100644 (file)
@@ -90,7 +90,7 @@
 #define PIN_PA14__I2SC1_MCK            PINMUX_PIN(PIN_PA14, 4, 2)
 #define PIN_PA14__FLEXCOM3_IO2         PINMUX_PIN(PIN_PA14, 5, 1)
 #define PIN_PA14__D9                   PINMUX_PIN(PIN_PA14, 6, 2)
-#define PIN_PA15                       14
+#define PIN_PA15                       15
 #define PIN_PA15__GPIO                 PINMUX_PIN(PIN_PA15, 0, 0)
 #define PIN_PA15__SPI0_MOSI            PINMUX_PIN(PIN_PA15, 1, 1)
 #define PIN_PA15__TF1                  PINMUX_PIN(PIN_PA15, 2, 1)
diff --git a/arch/arm/boot/dts/tps65217.dtsi b/arch/arm/boot/dts/tps65217.dtsi
new file mode 100644 (file)
index 0000000..a632724
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65217.pdf
+ */
+
+&tps {
+       compatible = "ti,tps65217";
+
+       regulators {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               dcdc1_reg: regulator@0 {
+                       reg = <0>;
+                       regulator-compatible = "dcdc1";
+               };
+
+               dcdc2_reg: regulator@1 {
+                       reg = <1>;
+                       regulator-compatible = "dcdc2";
+               };
+
+               dcdc3_reg: regulator@2 {
+                       reg = <2>;
+                       regulator-compatible = "dcdc3";
+               };
+
+               ldo1_reg: regulator@3 {
+                       reg = <3>;
+                       regulator-compatible = "ldo1";
+               };
+
+               ldo2_reg: regulator@4 {
+                       reg = <4>;
+                       regulator-compatible = "ldo2";
+               };
+
+               ldo3_reg: regulator@5 {
+                       reg = <5>;
+                       regulator-compatible = "ldo3";
+               };
+
+               ldo4_reg: regulator@6 {
+                       reg = <6>;
+                       regulator-compatible = "ldo4";
+               };
+       };
+};
index 2dc6da70ae598af4a43f3b8a9bde05d26d386c77..d7ed252708c57fa86cff5d51887bd756b53b48e7 100644 (file)
@@ -16,7 +16,7 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-
+#include <asm/div64.h>
 #include <asm/hardware/icst.h>
 
 /*
@@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
 
 unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
 {
-       return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
+       u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
+       u32 divisor = (vco.r + 2) * p->s2div[vco.s];
+
+       do_div(dividend, divisor);
+       return (unsigned long)dividend;
 }
 
 EXPORT_SYMBOL(icst_hz);
@@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params *p, unsigned long freq)
 
                if (f > p->vco_min && f <= p->vco_max)
                        break;
+               i++;
        } while (i < 8);
 
        if (i >= 8)
index a7151744b85c17d8c7041f33141e7c4cf7809fec..d18d6b42fcf52f9db076af65a0f6aad022a1173c 100644 (file)
@@ -292,24 +292,23 @@ CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
-CONFIG_OMAP2_DSS=m
-CONFIG_OMAP5_DSS_HDMI=y
-CONFIG_OMAP2_DSS_SDI=y
-CONFIG_OMAP2_DSS_DSI=y
+CONFIG_FB_OMAP5_DSS_HDMI=y
+CONFIG_FB_OMAP2_DSS_SDI=y
+CONFIG_FB_OMAP2_DSS_DSI=y
 CONFIG_FB_OMAP2=m
-CONFIG_DISPLAY_ENCODER_TFP410=m
-CONFIG_DISPLAY_ENCODER_TPD12S015=m
-CONFIG_DISPLAY_CONNECTOR_DVI=m
-CONFIG_DISPLAY_CONNECTOR_HDMI=m
-CONFIG_DISPLAY_CONNECTOR_ANALOG_TV=m
-CONFIG_DISPLAY_PANEL_DPI=m
-CONFIG_DISPLAY_PANEL_DSI_CM=m
-CONFIG_DISPLAY_PANEL_SONY_ACX565AKM=m
-CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02=m
-CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01=m
-CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1=m
-CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1=m
-CONFIG_DISPLAY_PANEL_NEC_NL8048HL11=m
+CONFIG_FB_OMAP2_ENCODER_TFP410=m
+CONFIG_FB_OMAP2_ENCODER_TPD12S015=m
+CONFIG_FB_OMAP2_CONNECTOR_DVI=m
+CONFIG_FB_OMAP2_CONNECTOR_HDMI=m
+CONFIG_FB_OMAP2_CONNECTOR_ANALOG_TV=m
+CONFIG_FB_OMAP2_PANEL_DPI=m
+CONFIG_FB_OMAP2_PANEL_DSI_CM=m
+CONFIG_FB_OMAP2_PANEL_SONY_ACX565AKM=m
+CONFIG_FB_OMAP2_PANEL_LGPHILIPS_LB035Q02=m
+CONFIG_FB_OMAP2_PANEL_SHARP_LS037V7DW01=m
+CONFIG_FB_OMAP2_PANEL_TPO_TD028TTEC1=m
+CONFIG_FB_OMAP2_PANEL_TPO_TD043MTEA1=m
+CONFIG_FB_OMAP2_PANEL_NEC_NL8048HL11=m
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_PLATFORM=y
index b445a5d56f4342b71540e40c1ce298e0ad786688..89a3a3e592d6646783b9b08533a9704d929da70b 100644 (file)
@@ -364,7 +364,7 @@ static struct crypto_alg aes_algs[] = { {
        .cra_blkcipher = {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
-               .ivsize         = AES_BLOCK_SIZE,
+               .ivsize         = 0,
                .setkey         = ce_aes_setkey,
                .encrypt        = ecb_encrypt,
                .decrypt        = ecb_decrypt,
@@ -441,7 +441,7 @@ static struct crypto_alg aes_algs[] = { {
        .cra_ablkcipher = {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
-               .ivsize         = AES_BLOCK_SIZE,
+               .ivsize         = 0,
                .setkey         = ablk_set_key,
                .encrypt        = ablk_encrypt,
                .decrypt        = ablk_decrypt,
index 7da5503c0591411f43df6bc767fb8c4eef314789..e08d151840567dcb6085271200601666836b0771 100644 (file)
@@ -117,6 +117,7 @@ static inline u32 gic_read_iar(void)
        u32 irqstat;
 
        asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat));
+       dsb(sy);
        return irqstat;
 }
 
index 0375c8caa06194591e065f94bbb3d57a0565c847..9408a994cc91792bcf89a57d67982e21c677d9d7 100644 (file)
@@ -35,14 +35,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
             dma_addr_t dev_addr, unsigned long offset, size_t size,
             enum dma_data_direction dir, struct dma_attrs *attrs)
 {
-       bool local = XEN_PFN_DOWN(dev_addr) == page_to_xen_pfn(page);
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
        /*
-        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
-        * multiple Xen page, it's not possible to have a mix of local and
-        * foreign Xen page. So if the first xen_pfn == mfn the page is local
-        * otherwise it's a foreign page grant-mapped in dom0. If the page is
-        * local we can safely call the native dma_ops function, otherwise we
-        * call the xen specific function.
+        * Dom0 is mapped 1:1, while the Linux page can span across
+        * multiple Xen pages, it's not possible for it to contain a
+        * mix of local and foreign Xen pages. So if the first xen_pfn
+        * == mfn the page is local otherwise it's a foreign page
+        * grant-mapped in dom0. If the page is local we can safely
+        * call the native dma_ops function, otherwise we call the xen
+        * specific function.
         */
        if (local)
                __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
index 2c5f160be65e44cbabc2c5d01b023d56df0a1985..ad325a8c7e1e5d1dfbad11e8846169696d36e6bc 100644 (file)
@@ -88,6 +88,7 @@ obj-$(CONFIG_DEBUG_LL)        += debug.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
 obj-$(CONFIG_ARM_VIRT_EXT)     += hyp-stub.o
+AFLAGS_hyp-stub.o              :=-Wa,-march=armv7-a
 ifeq ($(CONFIG_ARM_PSCI),y)
 obj-$(CONFIG_SMP)              += psci_smp.o
 endif
index 5fa69d7bae58a06ef19f7ca72fd04cf6603d6963..99361f11354a0d8928c9aaead7fdf5e09436b3ac 100644 (file)
@@ -161,7 +161,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
        u64 val;
 
        val = kvm_arm_timer_get_reg(vcpu, reg->id);
-       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
+       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
 static unsigned long num_core_regs(void)
index 7f33b2056ae6d92f568ad71fbf28cd52044b11fb..0f6600f05137921b61fe5c9a80b87302e7d03234 100644 (file)
@@ -206,7 +206,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
        run->mmio.is_write      = is_write;
        run->mmio.phys_addr     = fault_ipa;
        run->mmio.len           = len;
-       memcpy(run->mmio.data, data_buf, len);
+       if (is_write)
+               memcpy(run->mmio.data, data_buf, len);
 
        if (!ret) {
                /* We handled the access successfully in the kernel. */
index 809827265fb39d1b8a7178481bb91e87951c4a14..bab814d2f37dcc9a18229d5e912422a653307088 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/setup.h>
 #include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include "common.h"
 
@@ -77,12 +78,31 @@ static const char *const n900_boards_compat[] __initconst = {
        NULL,
 };
 
+/* Set system_rev from atags */
+static void __init rx51_set_system_rev(const struct tag *tags)
+{
+       const struct tag *tag;
+
+       if (tags->hdr.tag != ATAG_CORE)
+               return;
+
+       for_each_tag(tag, tags) {
+               if (tag->hdr.tag == ATAG_REVISION) {
+                       system_rev = tag->u.revision.rev;
+                       break;
+               }
+       }
+}
+
 /* Legacy userspace on Nokia N900 needs ATAGS exported in /proc/atags,
  * save them while the data is still not overwritten
  */
 static void __init rx51_reserve(void)
 {
-       save_atags((const struct tag *)(PAGE_OFFSET + 0x100));
+       const struct tag *tags = (const struct tag *)(PAGE_OFFSET + 0x100);
+
+       save_atags(tags);
+       rx51_set_system_rev(tags);
        omap_reserve();
 }
 
index 7b76ce01c21dd3aa3b4cad36ce2431f3c8350900..8633c703546a65c2e5b0071ffca0d5a12b664884 100644 (file)
@@ -101,10 +101,8 @@ static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
 
 static void set_onenand_cfg(void __iomem *onenand_base)
 {
-       u32 reg;
+       u32 reg = ONENAND_SYS_CFG1_RDY | ONENAND_SYS_CFG1_INT;
 
-       reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
-       reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
        reg |=  (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
                ONENAND_SYS_CFG1_BL_16;
        if (onenand_flags & ONENAND_FLAG_SYNCREAD)
@@ -123,6 +121,7 @@ static void set_onenand_cfg(void __iomem *onenand_base)
                reg |= ONENAND_SYS_CFG1_VHF;
        else
                reg &= ~ONENAND_SYS_CFG1_VHF;
+
        writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 }
 
@@ -289,6 +288,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
                }
        }
 
+       onenand_async.sync_write = true;
        omap2_onenand_calc_async_timings(&t);
 
        ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
index 0437537751bc0c593dbe3554e216727b845f3a78..f7ff3b9dad8784aeab4d3752061514a8498774ae 100644 (file)
@@ -191,12 +191,22 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct omap_device *od;
+       int err;
 
        switch (event) {
        case BUS_NOTIFY_DEL_DEVICE:
                if (pdev->archdata.od)
                        omap_device_delete(pdev->archdata.od);
                break;
+       case BUS_NOTIFY_UNBOUND_DRIVER:
+               od = to_omap_device(pdev);
+               if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) {
+                       dev_info(dev, "enabled after unload, idling\n");
+                       err = omap_device_idle(pdev);
+                       if (err)
+                               dev_err(dev, "failed to idle\n");
+               }
+               break;
        case BUS_NOTIFY_ADD_DEVICE:
                if (pdev->dev.of_node)
                        omap_device_build_from_dt(pdev);
@@ -602,8 +612,10 @@ static int _od_runtime_resume(struct device *dev)
        int ret;
 
        ret = omap_device_enable(pdev);
-       if (ret)
+       if (ret) {
+               dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n");
                return ret;
+       }
 
        return pm_generic_runtime_resume(dev);
 }
index 9cb11215cebaeb2e4e0a8355589ce6d7e5270b78..b3a4ed5289ec7c8c35661a1b6062d4387d13d097 100644 (file)
@@ -4,7 +4,6 @@
 extern void shmobile_init_delay(void);
 extern void shmobile_boot_vector(void);
 extern unsigned long shmobile_boot_fn;
-extern unsigned long shmobile_boot_arg;
 extern unsigned long shmobile_boot_size;
 extern void shmobile_smp_boot(void);
 extern void shmobile_smp_sleep(void);
index fa5248c52399c9b5e78e3c1cd7c167523f306424..5e503d91ad70ddf2b8f375ffaf36a09361c9be8c 100644 (file)
@@ -38,9 +38,3 @@ ENTRY(shmobile_boot_scu)
 
        b       secondary_startup
 ENDPROC(shmobile_boot_scu)
-
-       .text
-       .align  2
-       .globl  shmobile_scu_base
-shmobile_scu_base:
-       .space  4
index 330c1fc63197df89684e03578c1c0693b8e6f24f..32e0bf6e3ccb9bd317c68be65ef7071a0c05eeed 100644 (file)
@@ -24,7 +24,6 @@
        .arm
        .align  12
 ENTRY(shmobile_boot_vector)
-       ldr     r0, 2f
        ldr     r1, 1f
        bx      r1
 
@@ -34,9 +33,6 @@ ENDPROC(shmobile_boot_vector)
        .globl  shmobile_boot_fn
 shmobile_boot_fn:
 1:     .space  4
-       .globl  shmobile_boot_arg
-shmobile_boot_arg:
-2:     .space  4
        .globl  shmobile_boot_size
 shmobile_boot_size:
        .long   . - shmobile_boot_vector
@@ -46,13 +42,15 @@ shmobile_boot_size:
  */
 
 ENTRY(shmobile_smp_boot)
-                                               @ r0 = MPIDR_HWID_BITMASK
        mrc     p15, 0, r1, c0, c0, 5           @ r1 = MPIDR
-       and     r0, r1, r0                      @ r0 = cpu_logical_map() value
+       and     r0, r1, #0xffffff               @ MPIDR_HWID_BITMASK
+                                               @ r0 = cpu_logical_map() value
        mov     r1, #0                          @ r1 = CPU index
-       adr     r5, 1f                          @ array of per-cpu mpidr values
-       adr     r6, 2f                          @ array of per-cpu functions
-       adr     r7, 3f                          @ array of per-cpu arguments
+       adr     r2, 1f
+       ldmia   r2, {r5, r6, r7}
+       add     r5, r5, r2                      @ array of per-cpu mpidr values
+       add     r6, r6, r2                      @ array of per-cpu functions
+       add     r7, r7, r2                      @ array of per-cpu arguments
 
 shmobile_smp_boot_find_mpidr:
        ldr     r8, [r5, r1, lsl #2]
@@ -80,12 +78,18 @@ ENTRY(shmobile_smp_sleep)
        b       shmobile_smp_boot
 ENDPROC(shmobile_smp_sleep)
 
+       .align  2
+1:     .long   shmobile_smp_mpidr - .
+       .long   shmobile_smp_fn - 1b
+       .long   shmobile_smp_arg - 1b
+
+       .bss
        .globl  shmobile_smp_mpidr
 shmobile_smp_mpidr:
-1:     .space  NR_CPUS * 4
+       .space  NR_CPUS * 4
        .globl  shmobile_smp_fn
 shmobile_smp_fn:
-2:     .space  NR_CPUS * 4
+       .space  NR_CPUS * 4
        .globl  shmobile_smp_arg
 shmobile_smp_arg:
-3:     .space  NR_CPUS * 4
+       .space  NR_CPUS * 4
index 911884f7e28b174c271c6724c863520afe859868..aba75c89f9c1c5eb2d7070def50bb8e77118df3c 100644 (file)
@@ -123,7 +123,6 @@ void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
 {
        /* install boot code shared by all CPUs */
        shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
-       shmobile_boot_arg = MPIDR_HWID_BITMASK;
 
        /* perform per-cpu setup */
        apmu_parse_cfg(apmu_init_cpu, apmu_config, num);
index 64663110ab6ca0e1d8f06cc04e69175165e2cace..081a097c9219f41785229c9492b95b250151c1f4 100644 (file)
@@ -17,6 +17,9 @@
 #include <asm/smp_scu.h>
 #include "common.h"
 
+
+void __iomem *shmobile_scu_base;
+
 static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
                                          unsigned long action, void *hcpu)
 {
@@ -41,7 +44,6 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
 {
        /* install boot code shared by all CPUs */
        shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
-       shmobile_boot_arg = MPIDR_HWID_BITMASK;
 
        /* enable SCU and cache coherency on booting CPU */
        scu_enable(shmobile_scu_base);
index b854fe2095ad14616b7c4aae209b47f7e4f7ded3..0b024a9dbd4397e7235827dbdaf62d65a5ad3d16 100644 (file)
@@ -92,8 +92,6 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
        /* Map the reset vector (in headsmp-scu.S, headsmp.S) */
        __raw_writel(__pa(shmobile_boot_vector), AVECR);
-       shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
-       shmobile_boot_arg = (unsigned long)shmobile_scu_base;
 
        /* setup r8a7779 specific SCU bits */
        shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
index 4b4058db0781f63e307d4f5101a74d5330ddf337..66353caa35b9f78fa2aa4754dea3ce813593303f 100644 (file)
@@ -173,7 +173,7 @@ unsigned long arch_mmap_rnd(void)
 {
        unsigned long rnd;
 
-       rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+       rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
 
        return rnd << PAGE_SHIFT;
 }
index cf30daff8932504f95422c2aa3b5882b154713b5..d19b1ad29b075fd8624d34edb0d9c18c9ef11e51 100644 (file)
@@ -49,6 +49,9 @@ static int change_memory_common(unsigned long addr, int numpages,
                WARN_ON_ONCE(1);
        }
 
+       if (!numpages)
+               return 0;
+
        if (start < MODULES_VADDR || start >= MODULES_END)
                return -EINVAL;
 
index 307237cfe728b152e350b5fb4f1c1abc18d6fb4c..b5e3f6d42b88bef5f17d3c21a80f9e97a013b676 100644 (file)
@@ -88,7 +88,7 @@ Image: vmlinux
 Image.%: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
-zinstall install: vmlinux
+zinstall install:
        $(Q)$(MAKE) $(build)=$(boot) $@
 
 %.dtb: scripts
index abcbba2f01baad4c76f0c414372ba4713beafa11..305c552b5ec16ee903c4b6d0a73066a191dd7d31 100644 (file)
@@ -34,10 +34,10 @@ $(obj)/Image.lzma: $(obj)/Image FORCE
 $(obj)/Image.lzo: $(obj)/Image FORCE
        $(call if_changed,lzo)
 
-install: $(obj)/Image
+install:
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image System.map "$(INSTALL_PATH)"
 
-zinstall: $(obj)/Image.gz
+zinstall:
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image.gz System.map "$(INSTALL_PATH)"
index 12ed78aa6f0c27d4a76066b8064d8a3654db9ed0..d91e1f0225733750097f4533c7a2a9045c9ab175 100644 (file)
 #   $4 - default install path (blank if root directory)
 #
 
+verify () {
+       if [ ! -f "$1" ]; then
+               echo ""                                                   1>&2
+               echo " *** Missing file: $1"                              1>&2
+               echo ' *** You need to run "make" before "make install".' 1>&2
+               echo ""                                                   1>&2
+               exit 1
+       fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
 # User may have a custom install script
 if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
 if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
index 05d9e16c0dfdd81a8a6ffe141e5c6f5cc96b3e7e..7a3d22a46faf502224fa397c527ab6338bac8933 100644 (file)
@@ -294,7 +294,7 @@ static struct crypto_alg aes_algs[] = { {
        .cra_blkcipher = {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
-               .ivsize         = AES_BLOCK_SIZE,
+               .ivsize         = 0,
                .setkey         = aes_setkey,
                .encrypt        = ecb_encrypt,
                .decrypt        = ecb_decrypt,
@@ -371,7 +371,7 @@ static struct crypto_alg aes_algs[] = { {
        .cra_ablkcipher = {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
-               .ivsize         = AES_BLOCK_SIZE,
+               .ivsize         = 0,
                .setkey         = ablk_set_key,
                .encrypt        = ablk_encrypt,
                .decrypt        = ablk_decrypt,
index 2731d3b25ed2e338e76966b5efd86658b7e22263..8ec88e5b290f9bc12a416841e73ef56414972b59 100644 (file)
@@ -103,6 +103,7 @@ static inline u64 gic_read_iar_common(void)
        u64 irqstat;
 
        asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+       dsb(sy);
        return irqstat;
 }
 
index 738a95f93e493e3002ac8749857f8599c5ae3404..d201d4b396d15fee10129494b6d274bbf77a2320 100644 (file)
 #define TCR_EL2_MASK   (TCR_EL2_TG0 | TCR_EL2_SH0 | \
                         TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ)
 
-#define TCR_EL2_FLAGS  (TCR_EL2_RES1 | TCR_EL2_PS_40B)
-
 /* VTCR_EL2 Registers bits */
 #define VTCR_EL2_RES1          (1 << 31)
 #define VTCR_EL2_PS_MASK       (7 << 16)
 #define CPTR_EL2_TCPAC (1 << 31)
 #define CPTR_EL2_TTA   (1 << 20)
 #define CPTR_EL2_TFP   (1 << CPTR_EL2_TFP_SHIFT)
+#define CPTR_EL2_DEFAULT       0x000033ff
 
 /* Hyp Debug Configuration Register bits */
 #define MDCR_EL2_TDRA          (1 << 11)
index 3066328cd86b69a91274e0cb841059b428666140..779a5872a2c5fb5f9aa9b49af6f77391aefc2336 100644 (file)
@@ -127,10 +127,14 @@ static inline unsigned long *vcpu_spsr(const struct kvm_vcpu *vcpu)
 
 static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
 {
-       u32 mode = *vcpu_cpsr(vcpu) & PSR_MODE_MASK;
+       u32 mode;
 
-       if (vcpu_mode_is_32bit(vcpu))
+       if (vcpu_mode_is_32bit(vcpu)) {
+               mode = *vcpu_cpsr(vcpu) & COMPAT_PSR_MODE_MASK;
                return mode > COMPAT_PSR_MODE_USR;
+       }
+
+       mode = *vcpu_cpsr(vcpu) & PSR_MODE_MASK;
 
        return mode != PSR_MODE_EL0t;
 }
index bf464de33f52f77d2520db0a12e53b3749ced6cc..f5060867458024a5a61ccfd4a77330c728e13010 100644 (file)
 /*
  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
  *
- * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
+ * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
  *     (rounded up to PUD_SIZE).
  * VMALLOC_START: beginning of the kernel VA space
  * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
  *     fixed mappings and modules
  */
-#define VMEMMAP_SIZE           ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
+#define VMEMMAP_SIZE           ALIGN((1UL << (VA_BITS - PAGE_SHIFT - 1)) * sizeof(struct page), PUD_SIZE)
 
 #ifndef CONFIG_KASAN
 #define VMALLOC_START          (VA_START)
@@ -51,7 +51,8 @@
 
 #define VMALLOC_END            (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
-#define vmemmap                        ((struct page *)(VMALLOC_END + SZ_64K))
+#define VMEMMAP_START          (VMALLOC_END + SZ_64K)
+#define vmemmap                        ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
 
 #define FIRST_USER_ADDRESS     0UL
 
index 8aee3aeec3e687edde6f5be67233299e7a4f7d4f..c536c9e307b9a484dca6d03572f28cbf9f8c0667 100644 (file)
@@ -226,11 +226,28 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr)
        return retval;
 }
 
+static void send_user_sigtrap(int si_code)
+{
+       struct pt_regs *regs = current_pt_regs();
+       siginfo_t info = {
+               .si_signo       = SIGTRAP,
+               .si_errno       = 0,
+               .si_code        = si_code,
+               .si_addr        = (void __user *)instruction_pointer(regs),
+       };
+
+       if (WARN_ON(!user_mode(regs)))
+               return;
+
+       if (interrupts_enabled(regs))
+               local_irq_enable();
+
+       force_sig_info(SIGTRAP, &info, current);
+}
+
 static int single_step_handler(unsigned long addr, unsigned int esr,
                               struct pt_regs *regs)
 {
-       siginfo_t info;
-
        /*
         * If we are stepping a pending breakpoint, call the hw_breakpoint
         * handler first.
@@ -239,11 +256,7 @@ static int single_step_handler(unsigned long addr, unsigned int esr,
                return 0;
 
        if (user_mode(regs)) {
-               info.si_signo = SIGTRAP;
-               info.si_errno = 0;
-               info.si_code  = TRAP_HWBKPT;
-               info.si_addr  = (void __user *)instruction_pointer(regs);
-               force_sig_info(SIGTRAP, &info, current);
+               send_user_sigtrap(TRAP_HWBKPT);
 
                /*
                 * ptrace will disable single step unless explicitly
@@ -307,17 +320,8 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr)
 static int brk_handler(unsigned long addr, unsigned int esr,
                       struct pt_regs *regs)
 {
-       siginfo_t info;
-
        if (user_mode(regs)) {
-               info = (siginfo_t) {
-                       .si_signo = SIGTRAP,
-                       .si_errno = 0,
-                       .si_code  = TRAP_BRKPT,
-                       .si_addr  = (void __user *)instruction_pointer(regs),
-               };
-
-               force_sig_info(SIGTRAP, &info, current);
+               send_user_sigtrap(TRAP_BRKPT);
        } else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) {
                pr_warning("Unexpected kernel BRK exception at EL1\n");
                return -EFAULT;
@@ -328,7 +332,6 @@ static int brk_handler(unsigned long addr, unsigned int esr,
 
 int aarch32_break_handler(struct pt_regs *regs)
 {
-       siginfo_t info;
        u32 arm_instr;
        u16 thumb_instr;
        bool bp = false;
@@ -359,14 +362,7 @@ int aarch32_break_handler(struct pt_regs *regs)
        if (!bp)
                return -EFAULT;
 
-       info = (siginfo_t) {
-               .si_signo = SIGTRAP,
-               .si_errno = 0,
-               .si_code  = TRAP_BRKPT,
-               .si_addr  = pc,
-       };
-
-       force_sig_info(SIGTRAP, &info, current);
+       send_user_sigtrap(TRAP_BRKPT);
        return 0;
 }
 
index 999633bd7294aab399183bd3bcf33c64ce8a6e2c..352f7abd91c998f297b229d00e5cbb2f4882e81c 100644 (file)
@@ -89,6 +89,7 @@ __efistub_memcpy              = KALLSYMS_HIDE(__pi_memcpy);
 __efistub_memmove              = KALLSYMS_HIDE(__pi_memmove);
 __efistub_memset               = KALLSYMS_HIDE(__pi_memset);
 __efistub_strlen               = KALLSYMS_HIDE(__pi_strlen);
+__efistub_strnlen              = KALLSYMS_HIDE(__pi_strnlen);
 __efistub_strcmp               = KALLSYMS_HIDE(__pi_strcmp);
 __efistub_strncmp              = KALLSYMS_HIDE(__pi_strncmp);
 __efistub___flush_dcache_area  = KALLSYMS_HIDE(__pi___flush_dcache_area);
index 4fad9787ab46ed04bf36873e8f7f7eb724beb262..d9751a4769e758b220181d6a400bd5a238c2cedb 100644 (file)
@@ -44,14 +44,13 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
        unsigned long irq_stack_ptr;
 
        /*
-        * Use raw_smp_processor_id() to avoid false-positives from
-        * CONFIG_DEBUG_PREEMPT. get_wchan() calls unwind_frame() on sleeping
-        * task stacks, we can be pre-empted in this case, so
-        * {raw_,}smp_processor_id() may give us the wrong value. Sleeping
-        * tasks can't ever be on an interrupt stack, so regardless of cpu,
-        * the checks will always fail.
+        * Switching between stacks is valid when tracing current and in
+        * non-preemptible context.
         */
-       irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id());
+       if (tsk == current && !preemptible())
+               irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
+       else
+               irq_stack_ptr = 0;
 
        low  = frame->sp;
        /* irq stacks are not THREAD_SIZE aligned */
@@ -64,8 +63,8 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
                return -EINVAL;
 
        frame->sp = fp + 0x10;
-       frame->fp = *(unsigned long *)(fp);
-       frame->pc = *(unsigned long *)(fp + 8);
+       frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
+       frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8));
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        if (tsk && tsk->ret_stack &&
index cbedd724f48efcf487e443fa3fc21516d8d898a6..c5392081b49ba4ac4f48d9a0782442ac888ed222 100644 (file)
@@ -146,9 +146,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 {
        struct stackframe frame;
-       unsigned long irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
+       unsigned long irq_stack_ptr;
        int skip;
 
+       /*
+        * Switching between stacks is valid when tracing current and in
+        * non-preemptible context.
+        */
+       if (tsk == current && !preemptible())
+               irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id());
+       else
+               irq_stack_ptr = 0;
+
        pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
 
        if (!tsk)
index fcb778899a3804455f2e9ef5f3fad33456d2d96e..9e54ad7c240ac5d2239ba5140b04c6727b20377e 100644 (file)
@@ -194,7 +194,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
        u64 val;
 
        val = kvm_arm_timer_get_reg(vcpu, reg->id);
-       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
+       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
 /**
index 3e568dcd907b8c82806ee4c2bf4f355e64cf7d51..d073b5a216f72b1db65fbef79efd942b28df6f6e 100644 (file)
@@ -64,7 +64,7 @@ __do_hyp_init:
        mrs     x4, tcr_el1
        ldr     x5, =TCR_EL2_MASK
        and     x4, x4, x5
-       ldr     x5, =TCR_EL2_FLAGS
+       mov     x5, #TCR_EL2_RES1
        orr     x4, x4, x5
 
 #ifndef CONFIG_ARM64_VA_BITS_48
@@ -85,15 +85,17 @@ __do_hyp_init:
        ldr_l   x5, idmap_t0sz
        bfi     x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
 #endif
-       msr     tcr_el2, x4
-
-       ldr     x4, =VTCR_EL2_FLAGS
        /*
         * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in
-        * VTCR_EL2.
+        * TCR_EL2 and VTCR_EL2.
         */
        mrs     x5, ID_AA64MMFR0_EL1
        bfi     x4, x5, #16, #3
+
+       msr     tcr_el2, x4
+
+       ldr     x4, =VTCR_EL2_FLAGS
+       bfi     x4, x5, #16, #3
        /*
         * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS bit in
         * VTCR_EL2.
index ca8f5a5e2f965748fca28ced482c9c195270e5ab..f0e7bdfae134a727ec7c0ac76466020fdb65e0fb 100644 (file)
@@ -36,7 +36,11 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
        write_sysreg(val, hcr_el2);
        /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
        write_sysreg(1 << 15, hstr_el2);
-       write_sysreg(CPTR_EL2_TTA | CPTR_EL2_TFP, cptr_el2);
+
+       val = CPTR_EL2_DEFAULT;
+       val |= CPTR_EL2_TTA | CPTR_EL2_TFP;
+       write_sysreg(val, cptr_el2);
+
        write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
 }
 
@@ -45,7 +49,7 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
        write_sysreg(HCR_RW, hcr_el2);
        write_sysreg(0, hstr_el2);
        write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2);
-       write_sysreg(0, cptr_el2);
+       write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
 }
 
 static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
index 9142e082f5f3996df9428670f2e107cfc948d2e3..5dd2a26444ec116cd46d51f118c62ddcd78752ae 100644 (file)
@@ -147,16 +147,6 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        max_lr_idx = vtr_to_max_lr_idx(val);
        nr_pri_bits = vtr_to_nr_pri_bits(val);
 
-       switch (nr_pri_bits) {
-       case 7:
-                write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
-                write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
-       case 6:
-                write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
-       default:
-                write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
-       }                                          
-                                                  
        switch (nr_pri_bits) {
        case 7:
                 write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
@@ -167,6 +157,16 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
                 write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
        }
 
+       switch (nr_pri_bits) {
+       case 7:
+                write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
+                write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
+       case 6:
+                write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
+       default:
+                write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
+       }
+
        switch (max_lr_idx) {
        case 15:
                write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(15)], ICH_LR15_EL2);
index 648112e90ed546d2d052ccf7d9f66866d2390d06..4d1ac81870d27e6f272abde088e0f5e8290c80d1 100644 (file)
 
 #define PSTATE_FAULT_BITS_64   (PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | \
                                 PSR_I_BIT | PSR_D_BIT)
-#define EL1_EXCEPT_SYNC_OFFSET 0x200
+
+#define CURRENT_EL_SP_EL0_VECTOR       0x0
+#define CURRENT_EL_SP_ELx_VECTOR       0x200
+#define LOWER_EL_AArch64_VECTOR                0x400
+#define LOWER_EL_AArch32_VECTOR                0x600
 
 static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
 {
@@ -97,6 +101,34 @@ static void inject_abt32(struct kvm_vcpu *vcpu, bool is_pabt,
                *fsr = 0x14;
 }
 
+enum exception_type {
+       except_type_sync        = 0,
+       except_type_irq         = 0x80,
+       except_type_fiq         = 0x100,
+       except_type_serror      = 0x180,
+};
+
+static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
+{
+       u64 exc_offset;
+
+       switch (*vcpu_cpsr(vcpu) & (PSR_MODE_MASK | PSR_MODE32_BIT)) {
+       case PSR_MODE_EL1t:
+               exc_offset = CURRENT_EL_SP_EL0_VECTOR;
+               break;
+       case PSR_MODE_EL1h:
+               exc_offset = CURRENT_EL_SP_ELx_VECTOR;
+               break;
+       case PSR_MODE_EL0t:
+               exc_offset = LOWER_EL_AArch64_VECTOR;
+               break;
+       default:
+               exc_offset = LOWER_EL_AArch32_VECTOR;
+       }
+
+       return vcpu_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
+}
+
 static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
 {
        unsigned long cpsr = *vcpu_cpsr(vcpu);
@@ -108,8 +140,8 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
        *vcpu_spsr(vcpu) = cpsr;
        *vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
 
+       *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
        *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
-       *vcpu_pc(vcpu) = vcpu_sys_reg(vcpu, VBAR_EL1) + EL1_EXCEPT_SYNC_OFFSET;
 
        vcpu_sys_reg(vcpu, FAR_EL1) = addr;
 
@@ -143,8 +175,8 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
        *vcpu_spsr(vcpu) = cpsr;
        *vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
 
+       *vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
        *vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
-       *vcpu_pc(vcpu) = vcpu_sys_reg(vcpu, VBAR_EL1) + EL1_EXCEPT_SYNC_OFFSET;
 
        /*
         * Build an unknown exception, depending on the instruction
index eec3598b4184077b83b5a1f24321891cb110f5bb..2e90371cfb378b0e064667506a2b74c9275cacfb 100644 (file)
@@ -1007,10 +1007,9 @@ static int emulate_cp(struct kvm_vcpu *vcpu,
                if (likely(r->access(vcpu, params, r))) {
                        /* Skip instruction, since it was emulated */
                        kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+                       /* Handled */
+                       return 0;
                }
-
-               /* Handled */
-               return 0;
        }
 
        /* Not handled */
@@ -1043,7 +1042,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
 }
 
 /**
- * kvm_handle_cp_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * kvm_handle_cp_64 -- handles a mrrc/mcrr trap on a guest CP14/CP15 access
  * @vcpu: The VCPU pointer
  * @run:  The kvm_run struct
  */
@@ -1095,7 +1094,7 @@ out:
 }
 
 /**
- * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
+ * kvm_handle_cp_32 -- handles a mrc/mcr trap on a guest CP14/CP15 access
  * @vcpu: The VCPU pointer
  * @run:  The kvm_run struct
  */
index 2ca665711bf21e590b79f89578dbe4cbba0ca9b3..eae38da6e0bb3911a5cad1fb2f6da46b4bb0090a 100644 (file)
@@ -168,4 +168,4 @@ CPU_LE( lsr tmp2, tmp2, tmp4 )      /* Shift (tmp1 & 63).  */
 .Lhit_limit:
        mov     len, limit
        ret
-ENDPROC(strnlen)
+ENDPIPROC(strnlen)
index 331c4ca6205c4e7211d4bc7bc4832891d26080cc..a6e757cbab7785ed411e919b95c6d13caaf21726 100644 (file)
@@ -933,6 +933,10 @@ static int __init __iommu_dma_init(void)
                ret = register_iommu_dma_ops_notifier(&platform_bus_type);
        if (!ret)
                ret = register_iommu_dma_ops_notifier(&amba_bustype);
+
+       /* handle devices queued before this arch_initcall */
+       if (!ret)
+               __iommu_attach_notifier(NULL, BUS_NOTIFY_ADD_DEVICE, NULL);
        return ret;
 }
 arch_initcall(__iommu_dma_init);
index 92ddac1e8ca2f35b8f24028514bb761aed3591a4..abe2a9542b3a367c778a96051dcf3618881d6fa1 100644 (file)
@@ -371,6 +371,13 @@ static int __kprobes do_translation_fault(unsigned long addr,
        return 0;
 }
 
+static int do_alignment_fault(unsigned long addr, unsigned int esr,
+                             struct pt_regs *regs)
+{
+       do_bad_area(addr, esr, regs);
+       return 0;
+}
+
 /*
  * This abort handler always returns "fault".
  */
@@ -418,7 +425,7 @@ static struct fault_info {
        { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk)" },
        { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk)" },
        { do_bad,               SIGBUS,  0,             "unknown 32"                    },
-       { do_bad,               SIGBUS,  BUS_ADRALN,    "alignment fault"               },
+       { do_alignment_fault,   SIGBUS,  BUS_ADRALN,    "alignment fault"               },
        { do_bad,               SIGBUS,  0,             "unknown 34"                    },
        { do_bad,               SIGBUS,  0,             "unknown 35"                    },
        { do_bad,               SIGBUS,  0,             "unknown 36"                    },
index f3b061e67bfe0f4565d5df29322eeaef38a9bcc3..7802f216a67a588ab778b7d2b7649a2979e68b87 100644 (file)
@@ -319,8 +319,8 @@ void __init mem_init(void)
 #endif
                  MLG(VMALLOC_START, VMALLOC_END),
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-                 MLG((unsigned long)vmemmap,
-                     (unsigned long)vmemmap + VMEMMAP_SIZE),
+                 MLG(VMEMMAP_START,
+                     VMEMMAP_START + VMEMMAP_SIZE),
                  MLM((unsigned long)virt_to_page(PAGE_OFFSET),
                      (unsigned long)virt_to_page(high_memory)),
 #endif
index 4c893b5189ddd027537511c5daaca70f158577c4..232f787a088ae8e992c52cba450159a43a900174 100644 (file)
@@ -53,10 +53,10 @@ unsigned long arch_mmap_rnd(void)
 
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT))
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_compat_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
        else
 #endif
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
        return rnd << PAGE_SHIFT;
 }
 
index fc96e814188e57aa9dee8ed516c62200c543ad56..d1fc4796025edb8769ee01195e64b91821f3625a 100644 (file)
@@ -108,6 +108,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -266,6 +268,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -366,6 +374,7 @@ CONFIG_ARIADNE=y
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 CONFIG_HYDRA=y
 CONFIG_APNE=y
 CONFIG_ZORRO8390=y
index 05c904f08d9d496fb7455df0d1506fb8d8c9bc23..9bfe8be3658c18231ca4473d8c075a1fb2ac4d5e 100644 (file)
@@ -106,6 +106,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -264,6 +266,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -344,6 +352,7 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index d572b731c510fdb2dc60616ee1ff0ce7e10516ce..ebdcfae555801cd1c7367d4ca40974b3d39099cb 100644 (file)
@@ -106,6 +106,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -264,6 +266,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -353,6 +361,7 @@ CONFIG_ATARILANCE=y
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
index 11a30c65ad44cb52347929d51f80301c8aca648b..8acc65e54995388614666716febdab1dda706376 100644 (file)
@@ -104,6 +104,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -262,6 +264,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -343,6 +351,7 @@ CONFIG_BVME6000_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index 6630a5154b9d797ebea93cdbe70886bc673f60cd..0c6a3d52b26e2b2559f24963040d3ba65a91ed47 100644 (file)
@@ -106,6 +106,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -264,6 +266,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -345,6 +353,7 @@ CONFIG_HPLANCE=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index 1d90b71d09038da90cfad0cab267d60dae0fd752..12a8a6cb32f4914f06c1f5d4c8e5dd6ba31381ef 100644 (file)
@@ -105,6 +105,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -266,6 +268,12 @@ CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -362,6 +370,7 @@ CONFIG_MAC89x0=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_MACSONIC=y
+# CONFIG_NET_VENDOR_NETRONOME is not set
 CONFIG_MAC8390=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
index 1fd21c1ca87fd8da85ace8c64930cfeed4383370..64ff2dcb34c89a3e60e26f9c468d654ed943e97f 100644 (file)
@@ -115,6 +115,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -276,6 +278,12 @@ CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -404,6 +412,7 @@ CONFIG_MVME16x_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_MACSONIC=y
+# CONFIG_NET_VENDOR_NETRONOME is not set
 CONFIG_HYDRA=y
 CONFIG_MAC8390=y
 CONFIG_NE2000=y
index 74e10f79d7b1f9475574d422451314b7bcc1af64..07fc6abcfe0c50e4b656a63a9da36c728b13cec4 100644 (file)
@@ -103,6 +103,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -261,6 +263,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -343,6 +351,7 @@ CONFIG_MVME147_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index 7034e716f166be8f869f872b12f9cbf960054029..69903ded88f71d1d51ad4b430acbd2f745fdf867 100644 (file)
@@ -104,6 +104,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -262,6 +264,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -343,6 +351,7 @@ CONFIG_MVME16x_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index f7deb5f702a6484dda646577f48ade90b902bf18..bd8401686ddef143bf036159cb3f4ea650772f32 100644 (file)
@@ -104,6 +104,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -262,6 +264,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -352,6 +360,7 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
index 0ce79eb0d80503140d928c3c6c77061a2ead34d9..5f9fb3ab9636808d46b75f3696f477ab91e6dd79 100644 (file)
@@ -101,6 +101,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -259,6 +261,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -340,6 +348,7 @@ CONFIG_SUN3_82586=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index 4cb787e4991fcfd02646b1144999419b40454f83..5d1c674530e2ba73ca43ffc4940f139772962152 100644 (file)
@@ -101,6 +101,8 @@ CONFIG_NFT_NAT=m
 CONFIG_NFT_QUEUE=m
 CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -259,6 +261,12 @@ CONFIG_L2TP=m
 CONFIG_BRIDGE=m
 CONFIG_ATALK=m
 CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
@@ -341,6 +349,7 @@ CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
index f9d96bf869109c028e5a9f1f12ad3e9fe8b933ba..bafaff6dcd7bda8a28101f140159f9a7a76638db 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            376
+#define NR_syscalls            377
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index 36cf129de663a7ca22f1bf1bba5a6245b7b04c03..0ca729665f29e9d67851aed2c1c52be75bbd078b 100644 (file)
 #define __NR_userfaultfd       373
 #define __NR_membarrier                374
 #define __NR_mlock2            375
+#define __NR_copy_file_range   376
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 282cd903f4c469197738eb9e840eaa75c77ec11a..8bb94261ff97d953fcfbe7c305e6a7ecfce27a97 100644 (file)
@@ -396,3 +396,4 @@ ENTRY(sys_call_table)
        .long sys_userfaultfd
        .long sys_membarrier
        .long sys_mlock2                /* 375 */
+       .long sys_copy_file_range
index 57a945e832f43ff711fe04d1fa8a52fe1970f000..74a3db92da1b52edc15165ac06d3b1558b8b78c0 100644 (file)
@@ -2085,7 +2085,7 @@ config PAGE_SIZE_32KB
 
 config PAGE_SIZE_64KB
        bool "64kB"
-       depends on !CPU_R3000 && !CPU_TX39XX
+       depends on !CPU_R3000 && !CPU_TX39XX && !CPU_R6000
        help
          Using 64kB page size will result in higher performance kernel at
          the price of higher memory consumption.  This option is available on
index 459b9b252c3b73fe2c95362177655b3a6f154a6f..9d19236f53e7b9a33c2a2cc2ccfd593322b04074 100644 (file)
@@ -74,6 +74,7 @@
                timer: timer@10000040 {
                        compatible = "syscon";
                        reg = <0x10000040 0x2c>;
+                       native-endian;
                };
 
                reboot {
index 9c8d3fe28b3114e51aaf128a640bde630d31a65b..1f6b9b5cddb4c0890b02cb37edb5c0c3331ba8dd 100644 (file)
@@ -54,7 +54,7 @@
                periph_cntl: syscon@10000000 {
                        compatible = "syscon";
                        reg = <0x10000000 0x14>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot: syscon-reboot@10000008 {
index 4fc7ecee273c105027ff20cea02f2bd5cf86c9fe..3ae16053a0c98763d8b8239eff18630105c2239a 100644 (file)
@@ -98,6 +98,7 @@
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7125-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x60c>;
+                       native-endian;
                };
 
                reboot {
index a3039bb53477d40a426fec1d1318f3156ede8be3..be7991917d2950f0d48d0c04dfd9b478856fcc35 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7346-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
+                       native-endian;
                };
 
                reboot {
index 4274ff41ec2122ac0bfd52d814aee8432c26553e..060805be619a23ac8812576a59a47fead67c98aa 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7358-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
+                       native-endian;
                };
 
                reboot {
index 0dcc9163c27bdd0022e5b66f3ffd65da7fd6ce31..bcdb09bfe07ba3ed86369f9938ac50db678d250f 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7360-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
+                       native-endian;
                };
 
                reboot {
index 2f3f9fc2c478df36ef57c5990dd81f6757240e3a..d3b1b762e6c3e21c3e129aea6127f071d4417845 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7362-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
+                       native-endian;
                };
 
                reboot {
index bee221b3b56857c8d84dac3e2fa9bfe8b3c54a85..3302a1b8a5c9b841b46b931ab501327aa2099b30 100644 (file)
@@ -99,6 +99,7 @@
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7420-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x60c>;
+                       native-endian;
                };
 
                reboot {
index 571f30f52e3ff5780ec4fd72e18e72737e51537d..15b27aae15a9620e439de3e13162e16b2e8306b1 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
+                       native-endian;
                };
 
                reboot {
index 614ee211f71a89356dd1eb814a38ec3071885747..adb33e3550430de99adb3b2e2c211310fabc65a9 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
+                       native-endian;
                };
 
                reboot {
index cefb7a5968783094befa3ee5925b02ab1f972fac..e090fc388e02483faf1291e2f4844f823aec5bc2 100644 (file)
@@ -227,7 +227,7 @@ struct mips_elf_abiflags_v0 {
        int __res = 1;                                                  \
        struct elfhdr *__h = (hdr);                                     \
                                                                        \
-       if (__h->e_machine != EM_MIPS)                                  \
+       if (!mips_elf_check_machine(__h))                               \
                __res = 0;                                              \
        if (__h->e_ident[EI_CLASS] != ELFCLASS32)                       \
                __res = 0;                                              \
@@ -258,7 +258,7 @@ struct mips_elf_abiflags_v0 {
        int __res = 1;                                                  \
        struct elfhdr *__h = (hdr);                                     \
                                                                        \
-       if (__h->e_machine != EM_MIPS)                                  \
+       if (!mips_elf_check_machine(__h))                               \
                __res = 0;                                              \
        if (__h->e_ident[EI_CLASS] != ELFCLASS64)                       \
                __res = 0;                                              \
@@ -285,6 +285,11 @@ struct mips_elf_abiflags_v0 {
 
 #endif /* !defined(ELF_ARCH) */
 
+#define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS)
+
+#define vmcore_elf32_check_arch mips_elf_check_machine
+#define vmcore_elf64_check_arch mips_elf_check_machine
+
 struct mips_abi;
 
 extern struct mips_abi mips_abi;
index 9cbf383b8834c7551820930b0dc98a66895012fa..f06f97bd62df906bf4160594119dec4d52b028eb 100644 (file)
@@ -179,6 +179,10 @@ static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
                if (save)
                        _save_fp(tsk);
                __disable_fpu();
+       } else {
+               /* FPU should not have been left enabled with no owner */
+               WARN(read_c0_status() & ST0_CU1,
+                    "Orphaned FPU left enabled");
        }
        KSTK_STATUS(tsk) &= ~ST0_CU1;
        clear_tsk_thread_flag(tsk, TIF_USEDFPU);
index 8ebd3f579b848ea5c1a1f6c3cb4d79a2bafbcfac..3ed10a8d78651373a55e4f99c722767cbbc26810 100644 (file)
@@ -128,7 +128,8 @@ static inline int octeon_has_feature(enum octeon_feature feature)
        case OCTEON_FEATURE_PCIE:
                return OCTEON_IS_MODEL(OCTEON_CN56XX)
                        || OCTEON_IS_MODEL(OCTEON_CN52XX)
-                       || OCTEON_IS_MODEL(OCTEON_CN6XXX);
+                       || OCTEON_IS_MODEL(OCTEON_CN6XXX)
+                       || OCTEON_IS_MODEL(OCTEON_CN7XXX);
 
        case OCTEON_FEATURE_SRIO:
                return OCTEON_IS_MODEL(OCTEON_CN63XX)
index 3f832c3dd8f5f1cad76461b47ee00a0b7f85722d..041153f5cf93432ea1140c10cd53c3d48e91ab76 100644 (file)
@@ -45,7 +45,7 @@ extern unsigned int vced_count, vcei_count;
  * User space process size: 2GB. This is hardcoded into a few places,
  * so don't change it unless you know what you are doing.
  */
-#define TASK_SIZE      0x7fff8000UL
+#define TASK_SIZE      0x80000000UL
 #endif
 
 #define STACK_TOP_MAX  TASK_SIZE
index a71da576883c8f4b1a3d60279ebfaefb95798031..eebf3954960644daf75dd5ae0d6e7eca1c50f34a 100644 (file)
                .set    reorder
                .set    noat
                mfc0    a0, CP0_STATUS
-               li      v1, 0xff00
+               li      v1, ST0_CU1 | ST0_IM
                ori     a0, STATMASK
                xori    a0, STATMASK
                mtc0    a0, CP0_STATUS
                ori     a0, STATMASK
                xori    a0, STATMASK
                mtc0    a0, CP0_STATUS
-               li      v1, 0xff00
+               li      v1, ST0_CU1 | ST0_FR | ST0_IM
                and     a0, v1
                LONG_L  v0, PT_STATUS(sp)
                nor     v1, $0, v1
index 6499d93ae68d7096d63416a349d9afcdcc0cb3ae..47bc45a67e9ba187fb709b97e755900e9bcb4caf 100644 (file)
@@ -101,10 +101,8 @@ static inline void syscall_get_arguments(struct task_struct *task,
        /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
        if ((config_enabled(CONFIG_32BIT) ||
            test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
-           (regs->regs[2] == __NR_syscall)) {
+           (regs->regs[2] == __NR_syscall))
                i++;
-               n++;
-       }
 
        while (n--)
                ret |= mips_get_syscall_arg(args++, task, regs, i++);
index 90f03a7da6654da7000108042dcf00944d322406..3129795de940b0c370c3eb6926ade8b11f878f91 100644 (file)
 #define __NR_userfaultfd               (__NR_Linux + 357)
 #define __NR_membarrier                        (__NR_Linux + 358)
 #define __NR_mlock2                    (__NR_Linux + 359)
+#define __NR_copy_file_range           (__NR_Linux + 360)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            359
+#define __NR_Linux_syscalls            360
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                359
+#define __NR_O32_Linux_syscalls                360
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_userfaultfd               (__NR_Linux + 317)
 #define __NR_membarrier                        (__NR_Linux + 318)
 #define __NR_mlock2                    (__NR_Linux + 319)
+#define __NR_copy_file_range           (__NR_Linux + 320)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            319
+#define __NR_Linux_syscalls            320
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         319
+#define __NR_64_Linux_syscalls         320
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_userfaultfd               (__NR_Linux + 321)
 #define __NR_membarrier                        (__NR_Linux + 322)
 #define __NR_mlock2                    (__NR_Linux + 323)
+#define __NR_copy_file_range           (__NR_Linux + 324)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            323
+#define __NR_Linux_syscalls            324
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                323
+#define __NR_N32_Linux_syscalls                324
 
 #endif /* _UAPI_ASM_UNISTD_H */
index 8c6d76c9b2d69bf6603e32598e3b8d74cba15bf6..d9907e57e9b986f4d296c829c4cf0d5d8c995d38 100644 (file)
@@ -270,7 +270,7 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
 }
 EXPORT_SYMBOL(jz_gpio_port_get_value);
 
-#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f)
+#define IRQ_TO_BIT(irq) BIT((irq - JZ4740_IRQ_GPIO(0)) & 0x1f)
 
 static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq)
 {
index 1188e00bb120a2637c53f3916f28b1f990a9515e..1b992c6e3d8e212420673fbb697edeff0b6314e3 100644 (file)
@@ -35,7 +35,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
        int __res = 1;                                                  \
        struct elfhdr *__h = (hdr);                                     \
                                                                        \
-       if (__h->e_machine != EM_MIPS)                                  \
+       if (!mips_elf_check_machine(__h))                               \
                __res = 0;                                              \
        if (__h->e_ident[EI_CLASS] != ELFCLASS32)                       \
                __res = 0;                                              \
index 928767858b867b65cce4aa92f965f96064a1f429..abd3affe5fb3bd71367b908f9439b54ddea7a61c 100644 (file)
@@ -47,7 +47,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
        int __res = 1;                                                  \
        struct elfhdr *__h = (hdr);                                     \
                                                                        \
-       if (__h->e_machine != EM_MIPS)                                  \
+       if (!mips_elf_check_machine(__h))                               \
                __res = 0;                                              \
        if (__h->e_ident[EI_CLASS] != ELFCLASS32)                       \
                __res = 0;                                              \
index f2975d4d1e449cc948d84dacac736451a3144cf9..eddd5fd6fdfa2ee20f50886b8fbbad9045fd496d 100644 (file)
@@ -65,12 +65,10 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
        status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
        status |= KU_USER;
        regs->cp0_status = status;
+       lose_fpu(0);
+       clear_thread_flag(TIF_MSA_CTX_LIVE);
        clear_used_math();
-       clear_fpu_owner();
        init_dsp();
-       clear_thread_flag(TIF_USEDMSA);
-       clear_thread_flag(TIF_MSA_CTX_LIVE);
-       disable_msa();
        regs->cp0_epc = pc;
        regs->regs[29] = sp;
 }
index 5ce3b746cedc0bdea6e305cc72ef2121f0026053..b4ac6374a38f28e182b2558934ff979b88b33bb2 100644 (file)
@@ -125,7 +125,7 @@ LEAF(_restore_fp_context)
        END(_restore_fp_context)
        .set    reorder
 
-       .type   fault@function
+       .type   fault@function
        .ent    fault
 fault: li      v0, -EFAULT
        jr      ra
index f09546ee2cdc907dc02e4c391c103ba381e35a5e..17732f876eff1ad7e7e868f960304420e380db93 100644 (file)
@@ -358,7 +358,7 @@ LEAF(_restore_msa_all_upper)
 
        .set    reorder
 
-       .type   fault@function
+       .type   fault@function
        .ent    fault
 fault: li      v0, -EFAULT                             # failure
        jr      ra
index 2d23c834ba96cd328a87d016e328176fc9a6876e..a56317444bdad94c73325eb1f72d75ff46af1b82 100644 (file)
@@ -595,3 +595,4 @@ EXPORT(sys_call_table)
        PTR     sys_userfaultfd
        PTR     sys_membarrier
        PTR     sys_mlock2
+       PTR     sys_copy_file_range             /* 4360 */
index deac63315d0ed4123d1e0f09b617e9250d68c885..2b2dc14610d02b58dc704ee63de6520d45ee5156 100644 (file)
@@ -433,4 +433,5 @@ EXPORT(sys_call_table)
        PTR     sys_userfaultfd
        PTR     sys_membarrier
        PTR     sys_mlock2
+       PTR     sys_copy_file_range             /* 5320 */
        .size   sys_call_table,.-sys_call_table
index 5a69eb48d0a8cef87c33c3184f4ddc3236f01d2d..2bf5c8593d91daad1a9ee5ffea26eb59318854d9 100644 (file)
@@ -423,4 +423,5 @@ EXPORT(sysn32_call_table)
        PTR     sys_userfaultfd
        PTR     sys_membarrier
        PTR     sys_mlock2
+       PTR     sys_copy_file_range
        .size   sysn32_call_table,.-sysn32_call_table
index e4b6d7c9782263e7c6dfca1b7eb4e6818ca78a6e..c5b759e584c758a9d56acf44d7677ff74dc7ecf8 100644 (file)
@@ -578,4 +578,5 @@ EXPORT(sys32_call_table)
        PTR     sys_userfaultfd
        PTR     sys_membarrier
        PTR     sys_mlock2
+       PTR     sys_copy_file_range             /* 4360 */
        .size   sys32_call_table,.-sys32_call_table
index 569a7d5242ddda902e7ab1a03430ab14c712e5cd..5fdaf8bdcd2ebeed8e31eb7825edd958bfc1c251 100644 (file)
@@ -782,6 +782,7 @@ static inline void prefill_possible_map(void) {}
 void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
+       mips_cm_probe();
        prom_init();
 
        setup_early_fdc_console();
index bafcb7ad5c854d5109010485dd190f12486c363e..bf14da9f3e33b74473d2a23c3b3b388456c4bdc5 100644 (file)
@@ -663,7 +663,7 @@ static int simulate_rdhwr_normal(struct pt_regs *regs, unsigned int opcode)
        return -1;
 }
 
-static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned short opcode)
+static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned int opcode)
 {
        if ((opcode & MM_POOL32A_FUNC) == MM_RDHWR) {
                int rd = (opcode & MM_RS) >> 16;
@@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
 asmlinkage void do_ov(struct pt_regs *regs)
 {
        enum ctx_state prev_state;
-       siginfo_t info;
+       siginfo_t info = {
+               .si_signo = SIGFPE,
+               .si_code = FPE_INTOVF,
+               .si_addr = (void __user *)regs->cp0_epc,
+       };
 
        prev_state = exception_enter();
        die_if_kernel("Integer overflow", regs);
 
-       info.si_code = FPE_INTOVF;
-       info.si_signo = SIGFPE;
-       info.si_errno = 0;
-       info.si_addr = (void __user *) regs->cp0_epc;
        force_sig_info(SIGFPE, &info, current);
        exception_exit(prev_state);
 }
@@ -874,7 +874,7 @@ out:
 void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
        const char *str)
 {
-       siginfo_t info;
+       siginfo_t info = { 0 };
        char b[40];
 
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
@@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
                else
                        info.si_code = FPE_INTOVF;
                info.si_signo = SIGFPE;
-               info.si_errno = 0;
                info.si_addr = (void __user *) regs->cp0_epc;
                force_sig_info(SIGFPE, &info, current);
                break;
@@ -1119,11 +1118,12 @@ no_r2_instr:
        if (get_isa16_mode(regs->cp0_epc)) {
                unsigned short mmop[2] = { 0 };
 
-               if (unlikely(get_user(mmop[0], epc) < 0))
+               if (unlikely(get_user(mmop[0], (u16 __user *)epc + 0) < 0))
                        status = SIGSEGV;
-               if (unlikely(get_user(mmop[1], epc) < 0))
+               if (unlikely(get_user(mmop[1], (u16 __user *)epc + 1) < 0))
                        status = SIGSEGV;
-               opcode = (mmop[0] << 16) | mmop[1];
+               opcode = mmop[0];
+               opcode = (opcode << 16) | mmop[1];
 
                if (status < 0)
                        status = simulate_rdhwr_mm(regs, opcode);
@@ -1369,26 +1369,12 @@ asmlinkage void do_cpu(struct pt_regs *regs)
                if (unlikely(compute_return_epc(regs) < 0))
                        break;
 
-               if (get_isa16_mode(regs->cp0_epc)) {
-                       unsigned short mmop[2] = { 0 };
-
-                       if (unlikely(get_user(mmop[0], epc) < 0))
-                               status = SIGSEGV;
-                       if (unlikely(get_user(mmop[1], epc) < 0))
-                               status = SIGSEGV;
-                       opcode = (mmop[0] << 16) | mmop[1];
-
-                       if (status < 0)
-                               status = simulate_rdhwr_mm(regs, opcode);
-               } else {
+               if (!get_isa16_mode(regs->cp0_epc)) {
                        if (unlikely(get_user(opcode, epc) < 0))
                                status = SIGSEGV;
 
                        if (!cpu_has_llsc && status < 0)
                                status = simulate_llsc(regs, opcode);
-
-                       if (status < 0)
-                               status = simulate_rdhwr_normal(regs, opcode);
                }
 
                if (status < 0)
index 8bc3977576e6af5f7b5c1a17f306da0f21b26937..3110447ab1e9bffc37fa8572f5ce62d44d4a5fd9 100644 (file)
@@ -702,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
        } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
                void __user *uaddr = (void __user *)(long)reg->addr;
 
-               return copy_to_user(uaddr, vs, 16);
+               return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0;
        } else {
                return -EINVAL;
        }
@@ -732,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
        } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
                void __user *uaddr = (void __user *)(long)reg->addr;
 
-               return copy_from_user(vs, uaddr, 16);
+               return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0;
        } else {
                return -EINVAL;
        }
index 5c81fdd032c3b1269549f27e27348e9606eb5424..353037699512ca5515b11ce8fb2c808eb6386c78 100644 (file)
@@ -146,7 +146,7 @@ unsigned long arch_mmap_rnd(void)
 {
        unsigned long rnd;
 
-       rnd = (unsigned long)get_random_int();
+       rnd = get_random_long();
        rnd <<= PAGE_SHIFT;
        if (TASK_IS_32BIT_ADDR)
                rnd &= 0xfffffful;
@@ -174,7 +174,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 static inline unsigned long brk_rnd(void)
 {
-       unsigned long rnd = get_random_int();
+       unsigned long rnd = get_random_long();
 
        rnd = rnd << PAGE_SHIFT;
        /* 8MB for 32bit, 256MB for 64bit */
index 3bd0597d9c3da3a56ea6ba083ca05c67bd71c5e7..91dec32c77b722a838ce9ca352d89ca3939fba2b 100644 (file)
@@ -164,11 +164,13 @@ static int __init mips_sc_probe_cm3(void)
 
        sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
        sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
-       c->scache.sets = 64 << sets;
+       if (sets)
+               c->scache.sets = 64 << sets;
 
        line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
        line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
-       c->scache.linesz = 2 << line_sz;
+       if (line_sz)
+               c->scache.linesz = 2 << line_sz;
 
        assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
        assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
@@ -176,13 +178,12 @@ static int __init mips_sc_probe_cm3(void)
        c->scache.waysize = c->scache.sets * c->scache.linesz;
        c->scache.waybit = __ffs(c->scache.waysize);
 
-       c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+       if (c->scache.linesz) {
+               c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+               return 1;
+       }
 
-       return 1;
-}
-
-void __weak platform_early_l2_init(void)
-{
+       return 0;
 }
 
 static inline int __init mips_sc_probe(void)
@@ -194,12 +195,6 @@ static inline int __init mips_sc_probe(void)
        /* Mark as not present until probe completed */
        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
-       /*
-        * Do we need some platform specific probing before
-        * we configure L2?
-        */
-       platform_early_l2_init();
-
        if (mips_cm_revision() >= CM_REV_CM3)
                return mips_sc_probe_cm3();
 
index 571148c5fd0baa5ce8656e87574144d90b58e346..dc2c5214809d38703a7048babe7a16f83d77f28a 100644 (file)
@@ -293,7 +293,6 @@ mips_pci_controller:
        console_config();
 #endif
        /* Early detection of CMP support */
-       mips_cm_probe();
        mips_cpc_probe();
 
        if (!register_cps_smp_ops())
@@ -304,10 +303,3 @@ mips_pci_controller:
                return;
        register_up_smp_ops();
 }
-
-void platform_early_l2_init(void)
-{
-       /* L2 configuration lives in the CM3 */
-       if (mips_cm_revision() >= CM_REV_CM3)
-               mips_cm_probe();
-}
index a009ee4589343fab6442f902f2412d1236c6a4d1..1ae932c2d78b364b6c93b142d075c6a42bb1c7b6 100644 (file)
@@ -297,12 +297,12 @@ static int mt7620_pci_probe(struct platform_device *pdev)
                return PTR_ERR(rstpcie0);
 
        bridge_base = devm_ioremap_resource(&pdev->dev, bridge_res);
-       if (!bridge_base)
-               return -ENOMEM;
+       if (IS_ERR(bridge_base))
+               return PTR_ERR(bridge_base);
 
        pcie_base = devm_ioremap_resource(&pdev->dev, pcie_res);
-       if (!pcie_base)
-               return -ENOMEM;
+       if (IS_ERR(pcie_base))
+               return PTR_ERR(pcie_base);
 
        iomem_resource.start = 0;
        iomem_resource.end = ~0;
index f84ff12574b7375f0d08396047aca4f7fc22854f..6d8276cd25cad289b838bf20df02b6bcd8a06bb8 100644 (file)
@@ -33,7 +33,7 @@
  * floppy accesses go through the track buffer.
  */
 #define _CROSS_64KB(a,s,vdma) \
-(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
+(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
 
 #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
 
index 35bdccbb203622e116f288741ac4a9bc173034b0..b75039f9211645becb970599deeaafe257b86001 100644 (file)
 #define __NR_membarrier                (__NR_Linux + 343)
 #define __NR_userfaultfd       (__NR_Linux + 344)
 #define __NR_mlock2            (__NR_Linux + 345)
+#define __NR_copy_file_range   (__NR_Linux + 346)
 
-#define __NR_Linux_syscalls    (__NR_mlock2 + 1)
+#define __NR_Linux_syscalls    (__NR_copy_file_range + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 9585c81f755fc667370ed850cba16ee1ff91024c..ce0b2b4075c704f9ee2006c263b1ba1cf3e9afd1 100644 (file)
@@ -269,14 +269,19 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       long ret = 0;
-
        /* Do the secure computing check first. */
        secure_computing_strict(regs->gr[20]);
 
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-           tracehook_report_syscall_entry(regs))
-               ret = -1L;
+           tracehook_report_syscall_entry(regs)) {
+               /*
+                * Tracing decided this syscall should not happen or the
+                * debugger stored an invalid system call number. Skip
+                * the system call and the system call restart handling.
+                */
+               regs->gr[20] = -1UL;
+               goto out;
+       }
 
 #ifdef CONFIG_64BIT
        if (!is_compat_task())
@@ -290,7 +295,8 @@ long do_syscall_trace_enter(struct pt_regs *regs)
                        regs->gr[24] & 0xffffffff,
                        regs->gr[23] & 0xffffffff);
 
-       return ret ? : regs->gr[20];
+out:
+       return regs->gr[20];
 }
 
 void do_syscall_trace_exit(struct pt_regs *regs)
index 3fbd7252a4b27efd106250f5b21e98910f8af8bd..fbafa0d0e2bf865db726d15f9c4beb4817afe86c 100644 (file)
@@ -343,7 +343,7 @@ tracesys_next:
 #endif
 
        comiclr,>>=     __NR_Linux_syscalls, %r20, %r0
-       b,n     .Lsyscall_nosys
+       b,n     .Ltracesys_nosys
 
        LDREGX  %r20(%r19), %r19
 
@@ -359,6 +359,9 @@ tracesys_next:
        be      0(%sr7,%r19)
        ldo     R%tracesys_exit(%r2),%r2
 
+.Ltracesys_nosys:
+       ldo     -ENOSYS(%r0),%r28               /* set errno */
+
        /* Do *not* call this function on the gateway page, because it
        makes a direct call to syscall_trace. */
        
index d4ffcfbc98851e7c3f0707ec9d82470d918bed2e..585d50fc75c0f9776cf2bca74651387790ab6c22 100644 (file)
        ENTRY_SAME(membarrier)
        ENTRY_SAME(userfaultfd)
        ENTRY_SAME(mlock2)              /* 345 */
+       ENTRY_SAME(copy_file_range)
 
 
 .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
index e4824fd04bb7449d262c1a7697b5f539b03f6bab..9faa18c4f3f702adceb4f555b05b72bc8437cf6c 100644 (file)
@@ -557,7 +557,7 @@ choice
 
 config PPC_4K_PAGES
        bool "4k page size"
-       select HAVE_ARCH_SOFT_DIRTY if CHECKPOINT_RESTORE && PPC_BOOK3S
+       select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64
 
 config PPC_16K_PAGES
        bool "16k page size"
@@ -566,7 +566,7 @@ config PPC_16K_PAGES
 config PPC_64K_PAGES
        bool "64k page size"
        depends on !PPC_FSL_BOOK3E && (44x || PPC_STD_MMU_64 || PPC_BOOK3E_64)
-       select HAVE_ARCH_SOFT_DIRTY if CHECKPOINT_RESTORE && PPC_BOOK3S
+       select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64
 
 config PPC_256K_PAGES
        bool "256k page size"
index 8d1c41d283184ed56b750f438a8fe201d87dbc4d..ac07a30a7934265ed98706efb9f2c82ac8db85ce 100644 (file)
@@ -281,6 +281,10 @@ extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
 extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                            pmd_t *pmdp);
 
+#define __HAVE_ARCH_PMDP_HUGE_SPLIT_PREPARE
+extern void pmdp_huge_split_prepare(struct vm_area_struct *vma,
+                                   unsigned long address, pmd_t *pmdp);
+
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
 static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
index c5eb86f3d452fbe66d44ae1cce9bbfff91a8b14d..867c39b45df6ce4c1bd5a342ca314a888bb185bf 100644 (file)
@@ -81,6 +81,7 @@ struct pci_dn;
 #define EEH_PE_KEEP            (1 << 8)        /* Keep PE on hotplug   */
 #define EEH_PE_CFG_RESTRICTED  (1 << 9)        /* Block config on error */
 #define EEH_PE_REMOVED         (1 << 10)       /* Removed permanently  */
+#define EEH_PE_PRI_BUS         (1 << 11)       /* Cached primary bus   */
 
 struct eeh_pe {
        int type;                       /* PE type: PHB/Bus/Device      */
index 8e86b48d03699047dda0f493a3955c8c05e34909..32e36b16773fd876a7b246ddb9e23c28193c3570 100644 (file)
@@ -57,12 +57,14 @@ DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_exit,
 extern void hcall_tracepoint_regfunc(void);
 extern void hcall_tracepoint_unregfunc(void);
 
-TRACE_EVENT_FN(hcall_entry,
+TRACE_EVENT_FN_COND(hcall_entry,
 
        TP_PROTO(unsigned long opcode, unsigned long *args),
 
        TP_ARGS(opcode, args),
 
+       TP_CONDITION(cpu_online(raw_smp_processor_id())),
+
        TP_STRUCT__entry(
                __field(unsigned long, opcode)
        ),
@@ -76,13 +78,15 @@ TRACE_EVENT_FN(hcall_entry,
        hcall_tracepoint_regfunc, hcall_tracepoint_unregfunc
 );
 
-TRACE_EVENT_FN(hcall_exit,
+TRACE_EVENT_FN_COND(hcall_exit,
 
        TP_PROTO(unsigned long opcode, unsigned long retval,
                unsigned long *retbuf),
 
        TP_ARGS(opcode, retval, retbuf),
 
+       TP_CONDITION(cpu_online(raw_smp_processor_id())),
+
        TP_STRUCT__entry(
                __field(unsigned long, opcode)
                __field(unsigned long, retval)
index 938742135ee08fc8dd058df690cfba7eacdabc0b..650cfb31ea3d9b3cee0301948bd85e54400cb951 100644 (file)
@@ -418,8 +418,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
                eeh_pcid_put(dev);
                if (driver->err_handler &&
                    driver->err_handler->error_detected &&
-                   driver->err_handler->slot_reset &&
-                   driver->err_handler->resume)
+                   driver->err_handler->slot_reset)
                        return NULL;
        }
 
@@ -564,6 +563,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
         */
        eeh_pe_state_mark(pe, EEH_PE_KEEP);
        if (bus) {
+               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
                pci_lock_rescan_remove();
                pcibios_remove_pci_devices(bus);
                pci_unlock_rescan_remove();
@@ -803,6 +803,7 @@ perm_error:
         * the their PCI config any more.
         */
        if (frozen_bus) {
+               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
                eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
 
                pci_lock_rescan_remove();
@@ -886,6 +887,7 @@ static void eeh_handle_special_event(void)
                                        continue;
 
                                /* Notify all devices to be down */
+                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
                                bus = eeh_pe_bus_get(phb_pe);
                                eeh_pe_dev_traverse(pe,
                                        eeh_report_failure, NULL);
index ca9e5371930ea7ca272913b931e0a5c6ffc8b656..98f81800e00c1030b69c80d79eb8d43edbda9728 100644 (file)
@@ -928,7 +928,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
                bus = pe->phb->bus;
        } else if (pe->type & EEH_PE_BUS ||
                   pe->type & EEH_PE_DEVICE) {
-               if (pe->bus) {
+               if (pe->state & EEH_PE_PRI_BUS) {
                        bus = pe->bus;
                        goto out;
                }
index 05e804cdecaa975dc6546ba251bbb61772f72219..aec9a1b1d25bc5a1d998b2a4f099176f9c48934d 100644 (file)
@@ -109,8 +109,9 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp)
         * If the breakpoint is unregistered between a hw_breakpoint_handler()
         * and the single_step_dabr_instruction(), then cleanup the breakpoint
         * restoration variables to prevent dangling pointers.
+        * FIXME, this should not be using bp->ctx at all! Sayeth peterz.
         */
-       if (bp->ctx && bp->ctx->task)
+       if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L))
                bp->ctx->task->thread.last_hit_ubp = NULL;
 }
 
index ac64ffdb52c848d170fa34ef9ffe50d8db4d19c0..08b7a40de5f85ab1c6f7e5ed205ca52edd5ab12c 100644 (file)
@@ -340,7 +340,7 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
                        if (name[0] == '.') {
                                if (strcmp(name+1, "TOC.") == 0)
                                        syms[i].st_shndx = SHN_ABS;
-                               memmove(name, name+1, strlen(name));
+                               syms[i].st_name++;
                        }
                }
        }
index dccc87e8fee5e6544de0d8fc732a97aa14f45907..3c5736e52a14b7d42dd0c28425e709b0a7147c3c 100644 (file)
@@ -1768,9 +1768,9 @@ static inline unsigned long brk_rnd(void)
 
        /* 8MB for 32bit, 1GB for 64bit */
        if (is_32bit_task())
-               rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
+               rnd = (get_random_long() % (1UL<<(23-PAGE_SHIFT)));
        else
-               rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
+               rnd = (get_random_long() % (1UL<<(30-PAGE_SHIFT)));
 
        return rnd << PAGE_SHIFT;
 }
index 0762c1e08c88644f35cc8a3df5ba50c52c1801a2..edb09912f0c9b5ca316216bf3d912c7efe8d920a 100644 (file)
@@ -111,7 +111,13 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
         */
        if (!(old_pte & _PAGE_COMBO)) {
                flush_hash_page(vpn, rpte, MMU_PAGE_64K, ssize, flags);
-               old_pte &= ~_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND;
+               /*
+                * clear the old slot details from the old and new pte.
+                * On hash insert failure we use old pte value and we don't
+                * want slot information there if we have a insert failure.
+                */
+               old_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND);
+               new_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND);
                goto htab_insert_hpte;
        }
        /*
index 49b152b0f926289e1dcaa595988932a036df5325..eb2accdd76fd8bb70a762c4a57df8bc2c425ffad 100644 (file)
@@ -78,9 +78,19 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
                 * base page size. This is because demote_segment won't flush
                 * hash page table entries.
                 */
-               if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO))
+               if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) {
                        flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K,
                                            ssize, flags);
+                       /*
+                        * With THP, we also clear the slot information with
+                        * respect to all the 64K hash pte mapping the 16MB
+                        * page. They are all invalid now. This make sure we
+                        * don't find the slot valid when we fault with 4k
+                        * base page size.
+                        *
+                        */
+                       memset(hpte_slot_array, 0, PTE_FRAG_SIZE);
+               }
        }
 
        valid = hpte_valid(hpte_slot_array, index);
index 7e6d0880813fe9e363a7e9edd2f5278ef10e4a9e..83a8be791e0646778ddf805d83b5a761bf0d62b1 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 
+#include <asm/mmu.h>
+
 #ifdef CONFIG_PPC_FSL_BOOK3E
 #ifdef CONFIG_PPC64
 static inline int tlb1_next(void)
@@ -60,6 +62,14 @@ static inline void book3e_tlb_lock(void)
        unsigned long tmp;
        int token = smp_processor_id() + 1;
 
+       /*
+        * Besides being unnecessary in the absence of SMT, this
+        * check prevents trying to do lbarx/stbcx. on e5500 which
+        * doesn't implement either feature.
+        */
+       if (!cpu_has_feature(CPU_FTR_SMT))
+               return;
+
        asm volatile("1: lbarx %0, 0, %1;"
                     "cmpwi %0, 0;"
                     "bne 2f;"
@@ -80,6 +90,9 @@ static inline void book3e_tlb_unlock(void)
 {
        struct paca_struct *paca = get_paca();
 
+       if (!cpu_has_feature(CPU_FTR_SMT))
+               return;
+
        isync();
        paca->tcd_ptr->lock = 0;
 }
index 0f0502e12f6c4c8accbe7fc28eb4db08158decfb..4087705ba90f34241200e2f30765794ea6b74b55 100644 (file)
@@ -59,9 +59,9 @@ unsigned long arch_mmap_rnd(void)
 
        /* 8MB for 32bit, 1GB for 64bit */
        if (is_32bit_task())
-               rnd = (unsigned long)get_random_int() % (1<<(23-PAGE_SHIFT));
+               rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
        else
-               rnd = (unsigned long)get_random_int() % (1<<(30-PAGE_SHIFT));
+               rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
 
        return rnd << PAGE_SHIFT;
 }
index 3124a20d0fab7a66b3a170356037da0d18c9da85..cdf2123d46db4813a4e87f30d29f8da359c313d9 100644 (file)
@@ -646,6 +646,28 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
        return pgtable;
 }
 
+void pmdp_huge_split_prepare(struct vm_area_struct *vma,
+                            unsigned long address, pmd_t *pmdp)
+{
+       VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+       VM_BUG_ON(REGION_ID(address) != USER_REGION_ID);
+
+       /*
+        * We can't mark the pmd none here, because that will cause a race
+        * against exit_mmap. We need to continue mark pmd TRANS HUGE, while
+        * we spilt, but at the same time we wan't rest of the ppc64 code
+        * not to insert hash pte on this, because we will be modifying
+        * the deposited pgtable in the caller of this function. Hence
+        * clear the _PAGE_USER so that we move the fault handling to
+        * higher level function and that will serialize against ptl.
+        * We need to flush existing hash pte entries here even though,
+        * the translation is still valid, because we will withdraw
+        * pgtable_t after this.
+        */
+       pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_USER, 0);
+}
+
+
 /*
  * set a new huge pmd. We should not be called for updating
  * an existing pmd entry. That should go via pmd_hugepage_update.
@@ -663,10 +685,20 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
        return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
 }
 
+/*
+ * We use this to invalidate a pmdp entry before switching from a
+ * hugepte to regular pmd entry.
+ */
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
        pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
+
+       /*
+        * This ensures that generic code that rely on IRQ disabling
+        * to prevent a parallel THP split work as expected.
+        */
+       kick_all_cpus_sync();
 }
 
 /*
index 5f152b95ca0c8493536d787a51d741ae628adb8a..87f47e55aab65ac234df1d67c926ca17b1517f06 100644 (file)
@@ -444,9 +444,12 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)
         * PCI devices of the PE are expected to be removed prior
         * to PE reset.
         */
-       if (!edev->pe->bus)
+       if (!(edev->pe->state & EEH_PE_PRI_BUS)) {
                edev->pe->bus = pci_find_bus(hose->global_number,
                                             pdn->busno);
+               if (edev->pe->bus)
+                       edev->pe->state |= EEH_PE_PRI_BUS;
+       }
 
        /*
         * Enable EEH explicitly so that we will do EEH check
index 573ae1994097fb91e15e3f7f6351fe1e73b35c59..f90dc04395bf47bcc0e662a7a1c17526220ccda2 100644 (file)
@@ -3180,6 +3180,7 @@ static void pnv_pci_ioda_shutdown(struct pci_controller *hose)
 
 static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
        .dma_dev_setup = pnv_pci_dma_dev_setup,
+       .dma_bus_setup = pnv_pci_dma_bus_setup,
 #ifdef CONFIG_PCI_MSI
        .setup_msi_irqs = pnv_setup_msi_irqs,
        .teardown_msi_irqs = pnv_teardown_msi_irqs,
index 2f55c86df703554bfd9541a44f8ba26bec072729..b1ef84a6c9d13cff03c2d4a5234e57265ef5bc75 100644 (file)
@@ -599,6 +599,9 @@ int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
        u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
        long i;
 
+       if (proto_tce & TCE_PCI_WRITE)
+               proto_tce |= TCE_PCI_READ;
+
        for (i = 0; i < npages; i++) {
                unsigned long newtce = proto_tce |
                        ((rpn + i) << tbl->it_page_shift);
@@ -620,6 +623,9 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index,
 
        BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl));
 
+       if (newtce & TCE_PCI_WRITE)
+               newtce |= TCE_PCI_READ;
+
        oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce));
        *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE);
        *direction = iommu_tce_direction(oldtce);
@@ -760,6 +766,26 @@ void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
                phb->dma_dev_setup(phb, pdev);
 }
 
+void pnv_pci_dma_bus_setup(struct pci_bus *bus)
+{
+       struct pci_controller *hose = bus->sysdata;
+       struct pnv_phb *phb = hose->private_data;
+       struct pnv_ioda_pe *pe;
+
+       list_for_each_entry(pe, &phb->ioda.pe_list, list) {
+               if (!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)))
+                       continue;
+
+               if (!pe->pbus)
+                       continue;
+
+               if (bus->number == ((pe->rid >> 8) & 0xFF)) {
+                       pe->pbus = bus;
+                       break;
+               }
+       }
+}
+
 void pnv_pci_shutdown(void)
 {
        struct pci_controller *hose;
index 7f56313e8d7223dfd9f22b927c807b20516cf941..00691a9b99af67b09967c73b39b652b973392f06 100644 (file)
@@ -242,6 +242,7 @@ extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
 extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
 
 extern void pnv_pci_dma_dev_setup(struct pci_dev *pdev);
+extern void pnv_pci_dma_bus_setup(struct pci_bus *bus);
 extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
 extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);
 
index ea91ddfe54ebb901007bb625f833f7457eff0253..629c90865a073174f61fcc47268d3311db4f3a9e 100644 (file)
@@ -40,6 +40,7 @@ static inline void convert_fp_to_vx(__vector128 *vxrs, freg_t *fprs)
 static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
 {
        fpregs->pad = 0;
+       fpregs->fpc = fpu->fpc;
        if (MACHINE_HAS_VX)
                convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
        else
@@ -49,6 +50,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
 
 static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
 {
+       fpu->fpc = fpregs->fpc;
        if (MACHINE_HAS_VX)
                convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
        else
index 7aa799134a11754b09ad523a00e54c92a6e1c7a9..a52b6cca873d380adc9bec726cc31816dba5cd6b 100644 (file)
@@ -37,7 +37,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
        regs->psw.addr = ip;
 }
 #else
-#error Live patching support is disabled; check CONFIG_LIVEPATCH
+#error Include linux/livepatch.h, not asm/livepatch.h
 #endif
 
 #endif
index 66c94417c0ba09a471244a629c78d2457f38b17d..4af60374eba01fba89dc8b170a41428b094160b5 100644 (file)
@@ -271,7 +271,7 @@ static int restore_sigregs_ext32(struct pt_regs *regs,
 
        /* Restore high gprs from signal stack */
        if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
-                            sizeof(&sregs_ext->gprs_high)))
+                            sizeof(sregs_ext->gprs_high)))
                return -EFAULT;
        for (i = 0; i < NUM_GPRS; i++)
                *(__u32 *)&regs->gprs[i] = gprs_high[i];
index cfcba2dd9bb51d30b105990e1257543e8b9c39fd..0943b11a2f6e22c088dc13d3b8a0de9b4e6ef92c 100644 (file)
@@ -260,12 +260,13 @@ static unsigned long __store_trace(struct perf_callchain_entry *entry,
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
                           struct pt_regs *regs)
 {
-       unsigned long head;
+       unsigned long head, frame_size;
        struct stack_frame *head_sf;
 
        if (user_mode(regs))
                return;
 
+       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
        head = regs->gprs[15];
        head_sf = (struct stack_frame *) head;
 
@@ -273,8 +274,9 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
                return;
 
        head = head_sf->back_chain;
-       head = __store_trace(entry, head, S390_lowcore.async_stack - ASYNC_SIZE,
-                            S390_lowcore.async_stack);
+       head = __store_trace(entry, head,
+                            S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
+                            S390_lowcore.async_stack + frame_size);
 
        __store_trace(entry, head, S390_lowcore.thread_info,
                      S390_lowcore.thread_info + THREAD_SIZE);
index 5acba3cb7220ea8c779d9606268a17f9b0a9a928..8f64ebd63767c7a1a3e434b994b65110e890f741 100644 (file)
@@ -59,26 +59,32 @@ static unsigned long save_context_stack(struct stack_trace *trace,
        }
 }
 
-void save_stack_trace(struct stack_trace *trace)
+static void __save_stack_trace(struct stack_trace *trace, unsigned long sp)
 {
-       register unsigned long sp asm ("15");
-       unsigned long orig_sp, new_sp;
+       unsigned long new_sp, frame_size;
 
-       orig_sp = sp;
-       new_sp = save_context_stack(trace, orig_sp,
-                                   S390_lowcore.panic_stack - PAGE_SIZE,
-                                   S390_lowcore.panic_stack, 1);
-       if (new_sp != orig_sp)
-               return;
+       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
+       new_sp = save_context_stack(trace, sp,
+                       S390_lowcore.panic_stack + frame_size - PAGE_SIZE,
+                       S390_lowcore.panic_stack + frame_size, 1);
        new_sp = save_context_stack(trace, new_sp,
-                                   S390_lowcore.async_stack - ASYNC_SIZE,
-                                   S390_lowcore.async_stack, 1);
-       if (new_sp != orig_sp)
-               return;
+                       S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
+                       S390_lowcore.async_stack + frame_size, 1);
        save_context_stack(trace, new_sp,
                           S390_lowcore.thread_info,
                           S390_lowcore.thread_info + THREAD_SIZE, 1);
 }
+
+void save_stack_trace(struct stack_trace *trace)
+{
+       register unsigned long r15 asm ("15");
+       unsigned long sp;
+
+       sp = r15;
+       __save_stack_trace(trace, sp);
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
 EXPORT_SYMBOL_GPL(save_stack_trace);
 
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
@@ -86,6 +92,10 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
        unsigned long sp, low, high;
 
        sp = tsk->thread.ksp;
+       if (tsk == current) {
+               /* Get current stack pointer. */
+               asm volatile("la %0,0(15)" : "=a" (sp));
+       }
        low = (unsigned long) task_stack_page(tsk);
        high = (unsigned long) task_pt_regs(tsk);
        save_context_stack(trace, sp, low, high, 0);
@@ -93,3 +103,14 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
+
+void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
+{
+       unsigned long sp;
+
+       sp = kernel_stack_pointer(regs);
+       __save_stack_trace(trace, sp);
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+EXPORT_SYMBOL_GPL(save_stack_trace_regs);
index 21a5df99552bce6e4f84c872acdda43e6c5732c3..dde7654f5c68e5d117d3493d9c0f130f2e24e830 100644 (file)
@@ -18,6 +18,9 @@ void trace_s390_diagnose_norecursion(int diag_nr)
        unsigned long flags;
        unsigned int *depth;
 
+       /* Avoid lockdep recursion. */
+       if (IS_ENABLED(CONFIG_LOCKDEP))
+               return;
        local_irq_save(flags);
        depth = this_cpu_ptr(&diagnose_trace_depth);
        if (*depth == 0) {
index fec59c067d0dddf8ecb4a550124691d0838cda46..792f9c63fbca5b97e03d1251bfff1facc987f9c4 100644 (file)
@@ -93,15 +93,19 @@ static int __memcpy_real(void *dest, void *src, size_t count)
  */
 int memcpy_real(void *dest, void *src, size_t count)
 {
+       int irqs_disabled, rc;
        unsigned long flags;
-       int rc;
 
        if (!count)
                return 0;
-       local_irq_save(flags);
-       __arch_local_irq_stnsm(0xfbUL);
+       flags = __arch_local_irq_stnsm(0xf8UL);
+       irqs_disabled = arch_irqs_disabled_flags(flags);
+       if (!irqs_disabled)
+               trace_hardirqs_off();
        rc = __memcpy_real(dest, src, count);
-       local_irq_restore(flags);
+       if (!irqs_disabled)
+               trace_hardirqs_on();
+       __arch_local_irq_ssm(flags);
        return rc;
 }
 
index fe0bfe370c4534a1ab5ceac19d54372390e19289..1884e17595294bbfafdcaf8e183fd80e40d8ea48 100644 (file)
@@ -54,12 +54,13 @@ __show_trace(unsigned int *depth, unsigned long sp,
 
 void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
-       unsigned long head;
+       unsigned long head, frame_size;
        struct stack_frame* head_sf;
 
        if (user_mode(regs))
                return;
 
+       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
        head = regs->gprs[15];
        head_sf = (struct stack_frame*)head;
 
@@ -68,8 +69,9 @@ void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
 
        head = head_sf->back_chain;
 
-       head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE,
-                           S390_lowcore.async_stack);
+       head = __show_trace(&depth, head,
+                           S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
+                           S390_lowcore.async_stack + frame_size);
 
        __show_trace(&depth, head, S390_lowcore.thread_info,
                     S390_lowcore.thread_info + THREAD_SIZE);
index eaee14637d93ec5db5f95931b52cc31d5a8c2108..8496a074bd0eb74548ce1e38709b8a8dfe7dfb31 100644 (file)
@@ -24,7 +24,13 @@ LDFLAGS        := -m elf32_sparc
 export BITS    := 32
 UTS_MACHINE    := sparc
 
+# We are adding -Wa,-Av8 to KBUILD_CFLAGS to deal with a specs bug in some
+# versions of gcc.  Some gcc versions won't pass -Av8 to binutils when you
+# give -mcpu=v8.  This silently worked with older bintutils versions but
+# does not any more.
 KBUILD_CFLAGS  += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_CFLAGS  += -Wa,-Av8
+
 KBUILD_AFLAGS  += -m32 -Wa,-Av8
 
 else
index 1c26d440d288dfb8d28579fda55e2a76ccf4c139..b6de8b10a55b8b8f09eedb2c90d86906d5445686 100644 (file)
 #define __NR_listen            354
 #define __NR_setsockopt                355
 #define __NR_mlock2            356
+#define __NR_copy_file_range   357
 
-#define NR_syscalls            357
+#define NR_syscalls            358
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
index 33c02b15f47859a8262677d08635fcfdbb8872cb..a83707c83be803b78b3019cac6dde9dba2cfabd6 100644 (file)
@@ -948,7 +948,24 @@ linux_syscall_trace:
        cmp     %o0, 0
        bne     3f
         mov    -ENOSYS, %o0
+
+       /* Syscall tracing can modify the registers.  */
+       ld      [%sp + STACKFRAME_SZ + PT_G1], %g1
+       sethi   %hi(sys_call_table), %l7
+       ld      [%sp + STACKFRAME_SZ + PT_I0], %i0
+       or      %l7, %lo(sys_call_table), %l7
+       ld      [%sp + STACKFRAME_SZ + PT_I1], %i1
+       ld      [%sp + STACKFRAME_SZ + PT_I2], %i2
+       ld      [%sp + STACKFRAME_SZ + PT_I3], %i3
+       ld      [%sp + STACKFRAME_SZ + PT_I4], %i4
+       ld      [%sp + STACKFRAME_SZ + PT_I5], %i5
+       cmp     %g1, NR_syscalls
+       bgeu    3f
+        mov    -ENOSYS, %o0
+
+       sll     %g1, 2, %l4
        mov     %i0, %o0
+       ld      [%l7 + %l4], %l7
        mov     %i1, %o1
        mov     %i2, %o2
        mov     %i3, %o3
index afbaba52d2f16cb30daf092f5cd3986e7ca9c299..d127130bf4246032d39cf923248fce7eebf92867 100644 (file)
@@ -338,8 +338,9 @@ ENTRY(sun4v_mach_set_watchdog)
        mov     %o1, %o4
        mov     HV_FAST_MACH_SET_WATCHDOG, %o5
        ta      HV_FAST_TRAP
+       brnz,a,pn %o4, 0f
        stx     %o1, [%o4]
-       retl
+0:     retl
         nop
 ENDPROC(sun4v_mach_set_watchdog)
 
index d88beff47bab3eb74fece39e282f7c701ab84868..39aaec173f66ebce88fe7953c99b412f5b07cc3d 100644 (file)
@@ -52,7 +52,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
        unsigned char fenab;
        int err;
 
-       flush_user_windows();
+       synchronize_user_stack();
        if (get_thread_wsaved()                                 ||
            (((unsigned long)ucp) & (sizeof(unsigned long)-1))  ||
            (!__access_ok(ucp, sizeof(*ucp))))
index a92d5d2c46a3a6553bf13a57f95f65c6d61c334c..9e034f29dcc52208ca98a648e028f955f7c8f882 100644 (file)
@@ -37,6 +37,7 @@ EXPORT_SYMBOL(sun4v_niagara_getperf);
 EXPORT_SYMBOL(sun4v_niagara_setperf);
 EXPORT_SYMBOL(sun4v_niagara2_getperf);
 EXPORT_SYMBOL(sun4v_niagara2_setperf);
+EXPORT_SYMBOL(sun4v_mach_set_watchdog);
 
 /* from hweight.S */
 EXPORT_SYMBOL(__arch_hweight8);
index c690c8e16a96ef2758fca4e9af8080ec7af6c17a..b489e9759518182b6a3884935e5a1c22b1af3524 100644 (file)
@@ -264,7 +264,7 @@ static unsigned long mmap_rnd(void)
        unsigned long rnd = 0UL;
 
        if (current->flags & PF_RANDOMIZE) {
-               unsigned long val = get_random_int();
+               unsigned long val = get_random_long();
                if (test_thread_flag(TIF_32BIT))
                        rnd = (val % (1UL << (23UL-PAGE_SHIFT)));
                else
index bb0008927598b1f7bbeeccdf30c6fa154219a4ce..c4a1b5c40e4efc7ed17bcc0d67d1f058ea4f09f8 100644 (file)
@@ -158,7 +158,25 @@ linux_syscall_trace32:
         add    %sp, PTREGS_OFF, %o0
        brnz,pn %o0, 3f
         mov    -ENOSYS, %o0
+
+       /* Syscall tracing can modify the registers.  */
+       ldx     [%sp + PTREGS_OFF + PT_V9_G1], %g1
+       sethi   %hi(sys_call_table32), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I0], %i0
+       or      %l7, %lo(sys_call_table32), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I1], %i1
+       ldx     [%sp + PTREGS_OFF + PT_V9_I2], %i2
+       ldx     [%sp + PTREGS_OFF + PT_V9_I3], %i3
+       ldx     [%sp + PTREGS_OFF + PT_V9_I4], %i4
+       ldx     [%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+       cmp     %g1, NR_syscalls
+       bgeu,pn %xcc, 3f
+        mov    -ENOSYS, %o0
+
+       sll     %g1, 2, %l4
        srl     %i0, 0, %o0
+       lduw    [%l7 + %l4], %l7
        srl     %i4, 0, %o4
        srl     %i1, 0, %o1
        srl     %i2, 0, %o2
@@ -170,7 +188,25 @@ linux_syscall_trace:
         add    %sp, PTREGS_OFF, %o0
        brnz,pn %o0, 3f
         mov    -ENOSYS, %o0
+
+       /* Syscall tracing can modify the registers.  */
+       ldx     [%sp + PTREGS_OFF + PT_V9_G1], %g1
+       sethi   %hi(sys_call_table64), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I0], %i0
+       or      %l7, %lo(sys_call_table64), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I1], %i1
+       ldx     [%sp + PTREGS_OFF + PT_V9_I2], %i2
+       ldx     [%sp + PTREGS_OFF + PT_V9_I3], %i3
+       ldx     [%sp + PTREGS_OFF + PT_V9_I4], %i4
+       ldx     [%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+       cmp     %g1, NR_syscalls
+       bgeu,pn %xcc, 3f
+        mov    -ENOSYS, %o0
+
+       sll     %g1, 2, %l4
        mov     %i0, %o0
+       lduw    [%l7 + %l4], %l7
        mov     %i1, %o1
        mov     %i2, %o2
        mov     %i3, %o3
index e663b6c78de2e6498a5a458f1129504cae3ab2a8..6c3dd6c52f8bd09135e81f1d56704602d10c4f4e 100644 (file)
@@ -88,4 +88,4 @@ sys_call_table:
 /*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
 /*345*/        .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 /*350*/        .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
-/*355*/        .long sys_setsockopt, sys_mlock2
+/*355*/        .long sys_setsockopt, sys_mlock2, sys_copy_file_range
index 1557121f4cdce8a6ae21c31fb33e9aa2d7cbc443..12b524cfcfa0120caabdf7aa5b8606ecc3978c96 100644 (file)
@@ -89,7 +89,7 @@ sys_call_table32:
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
        .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 /*350*/        .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
-       .word compat_sys_setsockopt, sys_mlock2
+       .word compat_sys_setsockopt, sys_mlock2, sys_copy_file_range
 
 #endif /* CONFIG_COMPAT */
 
@@ -170,4 +170,4 @@ sys_call_table:
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
        .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 /*350*/        .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
-       .word sys_setsockopt, sys_mlock2
+       .word sys_setsockopt, sys_mlock2, sys_copy_file_range
index 9bdf67a092a53bc9b9f68939abce7cc872e2a8b6..b60a9f8cda7550729a571c1eb6433eb83dcbd858 100644 (file)
@@ -12,6 +12,7 @@
 #include <skas.h>
 
 void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
 
 static void kill_off_processes(void)
 {
index fc8be0e3a4ff879a2cf9fddc8e017dfa974ffc95..57acbd67d85dbd4051cd3c534ceff2a300ce9906 100644 (file)
@@ -69,7 +69,7 @@ void do_signal(struct pt_regs *regs)
        struct ksignal ksig;
        int handled_sig = 0;
 
-       if (get_signal(&ksig)) {
+       while (get_signal(&ksig)) {
                handled_sig = 1;
                /* Whee!  Actually deliver the signal.  */
                handle_signal(&ksig, regs);
index 9af2e63384005002bc99c762f8a61fdd1bbbb3ca..c46662f64c392050d1c45b722e3de7c01f87e250 100644 (file)
@@ -475,6 +475,7 @@ config X86_UV
        depends on X86_64
        depends on X86_EXTENDED_PLATFORM
        depends on NUMA
+       depends on EFI
        depends on X86_X2APIC
        depends on PCI
        ---help---
@@ -777,8 +778,8 @@ config HPET_TIMER
          HPET is the next generation timer replacing legacy 8254s.
          The HPET provides a stable time base on SMP
          systems, unlike the TSC, but it is more expensive to access,
-         as it is off-chip.  You can find the HPET spec at
-         <http://www.intel.com/hardwaredesign/hpetspec_1.pdf>.
+         as it is off-chip.  The interface used is documented
+         in the HPET spec, revision 1.
 
          You can safely choose Y here.  However, HPET will only be
          activated if the platform and the BIOS support this feature.
index 77d8c5112900e0edb73741af9c7cc4a60b0bb8f5..bb3e376d0f33c8dda5a9cf7b4e2b3f2d39f6389a 100644 (file)
@@ -294,6 +294,7 @@ sysenter_past_esp:
        pushl   $__USER_DS              /* pt_regs->ss */
        pushl   %ebp                    /* pt_regs->sp (stashed in bp) */
        pushfl                          /* pt_regs->flags (except IF = 0) */
+       ASM_CLAC                        /* Clear AC after saving FLAGS */
        orl     $X86_EFLAGS_IF, (%esp)  /* Fix IF */
        pushl   $__USER_CS              /* pt_regs->cs */
        pushl   $0                      /* pt_regs->ip = 0 (placeholder) */
index ff1c6d61f332d22e6f95f54a782b150b39bf75dc..3c990eeee40bd6e83b4d830654fdf966250bb0e1 100644 (file)
@@ -261,6 +261,7 @@ ENTRY(entry_INT80_compat)
         * Interrupts are off on entry.
         */
        PARAVIRT_ADJUST_EXCEPTION_FRAME
+       ASM_CLAC                        /* Do this early to minimize exposure */
        SWAPGS
 
        /*
index 19c099afa8613ead6565917f5787deb3df12c9e7..e795f5274217a47cf1713063399675a175d5a4ea 100644 (file)
@@ -41,7 +41,7 @@ static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
        regs->ip = ip;
 }
 #else
-#error Live patching support is disabled; check CONFIG_LIVEPATCH
+#error Include linux/livepatch.h, not asm/livepatch.h
 #endif
 
 #endif /* _ASM_X86_LIVEPATCH_H */
index 46873fbd44e1b522b5d40ad5ebf963714df566a1..d08eacd298c2f4b2436b9841203dd5c90f295697 100644 (file)
@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
+extern bool mp_should_keep_irq(struct device *dev);
+
 struct pci_raw_ops {
        int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
                                                int reg, int len, u32 *val);
index 2d5a50cb61a2d6ad5c68d5563636edcc112ff4f9..20c11d1aa4ccce11b0709c3fe56092a5505151cf 100644 (file)
@@ -766,7 +766,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
  * Return saved PC of a blocked thread.
  * What is this good for? it will be always the scheduler or ret_from_fork.
  */
-#define thread_saved_pc(t)     (*(unsigned long *)((t)->thread.sp - 8))
+#define thread_saved_pc(t)     READ_ONCE_NOCHECK(*(unsigned long *)((t)->thread.sp - 8))
 
 #define task_pt_regs(tsk)      ((struct pt_regs *)(tsk)->thread.sp0 - 1)
 extern unsigned long KSTK_ESP(struct task_struct *task);
index f5dcb5204dcd5b27e8b8e9a1b87612a28cda10c6..3fe0eac59462b39fc12ce28a6e22d6e347b8719a 100644 (file)
@@ -48,20 +48,28 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
                switch (n) {
                case 1:
+                       __uaccess_begin();
                        __put_user_size(*(u8 *)from, (u8 __user *)to,
                                        1, ret, 1);
+                       __uaccess_end();
                        return ret;
                case 2:
+                       __uaccess_begin();
                        __put_user_size(*(u16 *)from, (u16 __user *)to,
                                        2, ret, 2);
+                       __uaccess_end();
                        return ret;
                case 4:
+                       __uaccess_begin();
                        __put_user_size(*(u32 *)from, (u32 __user *)to,
                                        4, ret, 4);
+                       __uaccess_end();
                        return ret;
                case 8:
+                       __uaccess_begin();
                        __put_user_size(*(u64 *)from, (u64 __user *)to,
                                        8, ret, 8);
+                       __uaccess_end();
                        return ret;
                }
        }
@@ -103,13 +111,19 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
                switch (n) {
                case 1:
+                       __uaccess_begin();
                        __get_user_size(*(u8 *)to, from, 1, ret, 1);
+                       __uaccess_end();
                        return ret;
                case 2:
+                       __uaccess_begin();
                        __get_user_size(*(u16 *)to, from, 2, ret, 2);
+                       __uaccess_end();
                        return ret;
                case 4:
+                       __uaccess_begin();
                        __get_user_size(*(u32 *)to, from, 4, ret, 4);
+                       __uaccess_end();
                        return ret;
                }
        }
@@ -148,13 +162,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
                switch (n) {
                case 1:
+                       __uaccess_begin();
                        __get_user_size(*(u8 *)to, from, 1, ret, 1);
+                       __uaccess_end();
                        return ret;
                case 2:
+                       __uaccess_begin();
                        __get_user_size(*(u16 *)to, from, 2, ret, 2);
+                       __uaccess_end();
                        return ret;
                case 4:
+                       __uaccess_begin();
                        __get_user_size(*(u32 *)to, from, 4, ret, 4);
+                       __uaccess_end();
                        return ret;
                }
        }
@@ -170,13 +190,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
                switch (n) {
                case 1:
+                       __uaccess_begin();
                        __get_user_size(*(u8 *)to, from, 1, ret, 1);
+                       __uaccess_end();
                        return ret;
                case 2:
+                       __uaccess_begin();
                        __get_user_size(*(u16 *)to, from, 2, ret, 2);
+                       __uaccess_end();
                        return ret;
                case 4:
+                       __uaccess_begin();
                        __get_user_size(*(u32 *)to, from, 4, ret, 4);
+                       __uaccess_end();
                        return ret;
                }
        }
index 968d57dd54c9d19ed0a93cb3be6633d3328dc4e7..f320ee32d5a139a522c1b26f75e1076c9606f563 100644 (file)
@@ -57,7 +57,7 @@ static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev,
 {
        if (xen_pci_frontend && xen_pci_frontend->enable_msi)
                return xen_pci_frontend->enable_msi(dev, vectors);
-       return -ENODEV;
+       return -ENOSYS;
 }
 static inline void xen_pci_frontend_disable_msi(struct pci_dev *dev)
 {
@@ -69,7 +69,7 @@ static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev,
 {
        if (xen_pci_frontend && xen_pci_frontend->enable_msix)
                return xen_pci_frontend->enable_msix(dev, vectors, nvec);
-       return -ENODEV;
+       return -ENOSYS;
 }
 static inline void xen_pci_frontend_disable_msix(struct pci_dev *dev)
 {
index d1daead5fcddd57ab4cd0675315420bf52608584..adb3eaf8fe2a5e038c2444bd8f75b55716faf607 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/realmode.h>
 
+#include <linux/ftrace.h>
 #include "../../realmode/rm/wakeup.h"
 #include "sleep.h"
 
@@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void)
        saved_magic = 0x123456789abcdef0L;
 #endif /* CONFIG_64BIT */
 
+       /*
+        * Pause/unpause graph tracing around do_suspend_lowlevel as it has
+        * inconsistent call/return info after it jumps to the wakeup vector.
+        */
+       pause_graph_tracing();
        do_suspend_lowlevel();
+       unpause_graph_tracing();
        return 0;
 }
 
index 49742746a6c963c4a86c08c773430087225fec53..8836fc9fa84b08de4e35ddd60ac7b0f828fec231 100644 (file)
@@ -323,6 +323,8 @@ static int amd_uncore_cpu_up_prepare(unsigned int cpu)
        return 0;
 
 fail:
+       if (amd_uncore_nb)
+               *per_cpu_ptr(amd_uncore_nb, cpu) = NULL;
        kfree(uncore_nb);
        return -ENOMEM;
 }
index 1505587d06e97826703b21aba540ea8403bd8f2c..b9b09fec173bf2fedb0b9ee122b3c4668eb6e471 100644 (file)
@@ -650,10 +650,10 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
        u16 sel;
 
        la = seg_base(ctxt, addr.seg) + addr.ea;
-       *linear = la;
        *max_size = 0;
        switch (mode) {
        case X86EMUL_MODE_PROT64:
+               *linear = la;
                if (is_noncanonical_address(la))
                        goto bad;
 
@@ -662,6 +662,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
                        goto bad;
                break;
        default:
+               *linear = la = (u32)la;
                usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL,
                                                addr.seg);
                if (!usable)
@@ -689,7 +690,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
                        if (size > *max_size)
                                goto bad;
                }
-               la &= (u32)-1;
                break;
        }
        if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
index 6c9fed957cce1c897f0a490ec74c3f4e4f76d4dc..2ce4f05e81d3804cef4ded542a105a5a917b8bed 100644 (file)
@@ -249,7 +249,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                        return ret;
 
                kvm_vcpu_mark_page_dirty(vcpu, table_gfn);
-               walker->ptes[level] = pte;
+               walker->ptes[level - 1] = pte;
        }
        return 0;
 }
index e2951b6edbbce4deb5bad4fb38b8858c8093f8d5..0ff453749a909b9f0140b5de5d5d2dbb133e99d9 100644 (file)
@@ -596,6 +596,8 @@ struct vcpu_vmx {
        /* Support for PML */
 #define PML_ENTITY_NUM         512
        struct page *pml_pg;
+
+       u64 current_tsc_ratio;
 };
 
 enum segment_cache_field {
@@ -2127,14 +2129,16 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
                vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
 
-               /* Setup TSC multiplier */
-               if (cpu_has_vmx_tsc_scaling())
-                       vmcs_write64(TSC_MULTIPLIER,
-                                    vcpu->arch.tsc_scaling_ratio);
-
                vmx->loaded_vmcs->cpu = cpu;
        }
 
+       /* Setup TSC multiplier */
+       if (kvm_has_tsc_control &&
+           vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio) {
+               vmx->current_tsc_ratio = vcpu->arch.tsc_scaling_ratio;
+               vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
+       }
+
        vmx_vcpu_pi_load(vcpu, cpu);
 }
 
index 4244c2baf57da55aa5dd266b63781642dcc8af12..eaf6ee8c28b8f1619e7404bfd7efbf78beecc574 100644 (file)
@@ -6618,12 +6618,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
         * KVM_DEBUGREG_WONT_EXIT again.
         */
        if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
-               int i;
-
                WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
                kvm_x86_ops->sync_dirty_debug_regs(vcpu);
-               for (i = 0; i < KVM_NR_DB_REGS; i++)
-                       vcpu->arch.eff_db[i] = vcpu->arch.db[i];
+               kvm_update_dr0123(vcpu);
+               kvm_update_dr6(vcpu);
+               kvm_update_dr7(vcpu);
+               vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
        }
 
        /*
index 982ce34f4a9bf66011fc2652b45466d9c2b276f9..27f89c79a44b7da6fc6aef54e3961426e542e7ed 100644 (file)
@@ -232,17 +232,31 @@ ENDPROC(copy_user_enhanced_fast_string)
 
 /*
  * copy_user_nocache - Uncached memory copy with exception handling
- * This will force destination/source out of cache for more performance.
+ * This will force destination out of cache for more performance.
+ *
+ * Note: Cached memory copy is used when destination or size is not
+ * naturally aligned. That is:
+ *  - Require 8-byte alignment when size is 8 bytes or larger.
+ *  - Require 4-byte alignment when size is 4 bytes.
  */
 ENTRY(__copy_user_nocache)
        ASM_STAC
+
+       /* If size is less than 8 bytes, go to 4-byte copy */
        cmpl $8,%edx
-       jb 20f          /* less then 8 bytes, go to byte copy loop */
+       jb .L_4b_nocache_copy_entry
+
+       /* If destination is not 8-byte aligned, "cache" copy to align it */
        ALIGN_DESTINATION
+
+       /* Set 4x8-byte copy count and remainder */
        movl %edx,%ecx
        andl $63,%edx
        shrl $6,%ecx
-       jz 17f
+       jz .L_8b_nocache_copy_entry     /* jump if count is 0 */
+
+       /* Perform 4x8-byte nocache loop-copy */
+.L_4x8b_nocache_copy_loop:
 1:     movq (%rsi),%r8
 2:     movq 1*8(%rsi),%r9
 3:     movq 2*8(%rsi),%r10
@@ -262,60 +276,106 @@ ENTRY(__copy_user_nocache)
        leaq 64(%rsi),%rsi
        leaq 64(%rdi),%rdi
        decl %ecx
-       jnz 1b
-17:    movl %edx,%ecx
+       jnz .L_4x8b_nocache_copy_loop
+
+       /* Set 8-byte copy count and remainder */
+.L_8b_nocache_copy_entry:
+       movl %edx,%ecx
        andl $7,%edx
        shrl $3,%ecx
-       jz 20f
-18:    movq (%rsi),%r8
-19:    movnti %r8,(%rdi)
+       jz .L_4b_nocache_copy_entry     /* jump if count is 0 */
+
+       /* Perform 8-byte nocache loop-copy */
+.L_8b_nocache_copy_loop:
+20:    movq (%rsi),%r8
+21:    movnti %r8,(%rdi)
        leaq 8(%rsi),%rsi
        leaq 8(%rdi),%rdi
        decl %ecx
-       jnz 18b
-20:    andl %edx,%edx
-       jz 23f
+       jnz .L_8b_nocache_copy_loop
+
+       /* If no byte left, we're done */
+.L_4b_nocache_copy_entry:
+       andl %edx,%edx
+       jz .L_finish_copy
+
+       /* If destination is not 4-byte aligned, go to byte copy: */
+       movl %edi,%ecx
+       andl $3,%ecx
+       jnz .L_1b_cache_copy_entry
+
+       /* Set 4-byte copy count (1 or 0) and remainder */
        movl %edx,%ecx
-21:    movb (%rsi),%al
-22:    movb %al,(%rdi)
+       andl $3,%edx
+       shrl $2,%ecx
+       jz .L_1b_cache_copy_entry       /* jump if count is 0 */
+
+       /* Perform 4-byte nocache copy: */
+30:    movl (%rsi),%r8d
+31:    movnti %r8d,(%rdi)
+       leaq 4(%rsi),%rsi
+       leaq 4(%rdi),%rdi
+
+       /* If no bytes left, we're done: */
+       andl %edx,%edx
+       jz .L_finish_copy
+
+       /* Perform byte "cache" loop-copy for the remainder */
+.L_1b_cache_copy_entry:
+       movl %edx,%ecx
+.L_1b_cache_copy_loop:
+40:    movb (%rsi),%al
+41:    movb %al,(%rdi)
        incq %rsi
        incq %rdi
        decl %ecx
-       jnz 21b
-23:    xorl %eax,%eax
+       jnz .L_1b_cache_copy_loop
+
+       /* Finished copying; fence the prior stores */
+.L_finish_copy:
+       xorl %eax,%eax
        ASM_CLAC
        sfence
        ret
 
        .section .fixup,"ax"
-30:    shll $6,%ecx
+.L_fixup_4x8b_copy:
+       shll $6,%ecx
        addl %ecx,%edx
-       jmp 60f
-40:    lea (%rdx,%rcx,8),%rdx
-       jmp 60f
-50:    movl %ecx,%edx
-60:    sfence
+       jmp .L_fixup_handle_tail
+.L_fixup_8b_copy:
+       lea (%rdx,%rcx,8),%rdx
+       jmp .L_fixup_handle_tail
+.L_fixup_4b_copy:
+       lea (%rdx,%rcx,4),%rdx
+       jmp .L_fixup_handle_tail
+.L_fixup_1b_copy:
+       movl %ecx,%edx
+.L_fixup_handle_tail:
+       sfence
        jmp copy_user_handle_tail
        .previous
 
-       _ASM_EXTABLE(1b,30b)
-       _ASM_EXTABLE(2b,30b)
-       _ASM_EXTABLE(3b,30b)
-       _ASM_EXTABLE(4b,30b)
-       _ASM_EXTABLE(5b,30b)
-       _ASM_EXTABLE(6b,30b)
-       _ASM_EXTABLE(7b,30b)
-       _ASM_EXTABLE(8b,30b)
-       _ASM_EXTABLE(9b,30b)
-       _ASM_EXTABLE(10b,30b)
-       _ASM_EXTABLE(11b,30b)
-       _ASM_EXTABLE(12b,30b)
-       _ASM_EXTABLE(13b,30b)
-       _ASM_EXTABLE(14b,30b)
-       _ASM_EXTABLE(15b,30b)
-       _ASM_EXTABLE(16b,30b)
-       _ASM_EXTABLE(18b,40b)
-       _ASM_EXTABLE(19b,40b)
-       _ASM_EXTABLE(21b,50b)
-       _ASM_EXTABLE(22b,50b)
+       _ASM_EXTABLE(1b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(2b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(3b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(4b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(5b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(6b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(7b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(8b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(9b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(10b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(11b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(12b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(13b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(14b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(15b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(16b,.L_fixup_4x8b_copy)
+       _ASM_EXTABLE(20b,.L_fixup_8b_copy)
+       _ASM_EXTABLE(21b,.L_fixup_8b_copy)
+       _ASM_EXTABLE(30b,.L_fixup_4b_copy)
+       _ASM_EXTABLE(31b,.L_fixup_4b_copy)
+       _ASM_EXTABLE(40b,.L_fixup_1b_copy)
+       _ASM_EXTABLE(41b,.L_fixup_1b_copy)
 ENDPROC(__copy_user_nocache)
index eef44d9a3f77e2acc88baa424683388f67985e24..e830c71a13232f4305adf9ef1eb8ce6ffe201d5b 100644 (file)
@@ -287,6 +287,9 @@ static noinline int vmalloc_fault(unsigned long address)
        if (!pmd_k)
                return -1;
 
+       if (pmd_huge(*pmd_k))
+               return 0;
+
        pte_k = pte_offset_kernel(pmd_k, address);
        if (!pte_present(*pte_k))
                return -1;
@@ -360,8 +363,6 @@ void vmalloc_sync_all(void)
  * 64-bit:
  *
  *   Handle a fault on the vmalloc area
- *
- * This assumes no large pages in there.
  */
 static noinline int vmalloc_fault(unsigned long address)
 {
@@ -403,17 +404,23 @@ static noinline int vmalloc_fault(unsigned long address)
        if (pud_none(*pud_ref))
                return -1;
 
-       if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
+       if (pud_none(*pud) || pud_pfn(*pud) != pud_pfn(*pud_ref))
                BUG();
 
+       if (pud_huge(*pud))
+               return 0;
+
        pmd = pmd_offset(pud, address);
        pmd_ref = pmd_offset(pud_ref, address);
        if (pmd_none(*pmd_ref))
                return -1;
 
-       if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
+       if (pmd_none(*pmd) || pmd_pfn(*pmd) != pmd_pfn(*pmd_ref))
                BUG();
 
+       if (pmd_huge(*pmd))
+               return 0;
+
        pte_ref = pte_offset_kernel(pmd_ref, address);
        if (!pte_present(*pte_ref))
                return -1;
index 6d5eb59003721b79213a7661994be1a339bc5590..d8a798d8bf50ac037fa2ac4854085bd78759c249 100644 (file)
@@ -102,7 +102,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                        return 0;
                }
 
-               page = pte_page(pte);
                if (pte_devmap(pte)) {
                        pgmap = get_dev_pagemap(pte_pfn(pte), pgmap);
                        if (unlikely(!pgmap)) {
@@ -115,6 +114,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                        return 0;
                }
                VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+               page = pte_page(pte);
                get_page(page);
                put_dev_pagemap(pgmap);
                SetPageReferenced(page);
index 96bd1e2bffafb3b8ffbc28906a2998ad992d50e8..72bb52f93c3d619d0dc6c0355b7ab293a24c3199 100644 (file)
@@ -71,12 +71,12 @@ unsigned long arch_mmap_rnd(void)
 
        if (mmap_is_ia32())
 #ifdef CONFIG_COMPAT
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_compat_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
 #else
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
 #endif
        else
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
 
        return rnd << PAGE_SHIFT;
 }
index b2fd67da1701433d9168ebf1d0a908330544bd7d..ef05755a190063cdf79210f7ac164aef1a0f4ec5 100644 (file)
@@ -123,7 +123,7 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
                break;
        }
 
-       if (regno > nr_registers) {
+       if (regno >= nr_registers) {
                WARN_ONCE(1, "decoded an instruction with an invalid register");
                return -EINVAL;
        }
index c3b3f653ed0c6c9112297164c5cf535494f19461..d04f8094bc2323bbaa76095ab09efa2e8357cc7e 100644 (file)
@@ -469,7 +469,7 @@ static void __init numa_clear_kernel_node_hotplug(void)
 {
        int i, nid;
        nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
-       unsigned long start, end;
+       phys_addr_t start, end;
        struct memblock_region *r;
 
        /*
index 2440814b00699e33809ce061d6f86a48437f7a10..9cf96d82147a8da38ce4f57413d75075003cb244 100644 (file)
@@ -419,24 +419,30 @@ pmd_t *lookup_pmd_address(unsigned long address)
 phys_addr_t slow_virt_to_phys(void *__virt_addr)
 {
        unsigned long virt_addr = (unsigned long)__virt_addr;
-       unsigned long phys_addr, offset;
+       phys_addr_t phys_addr;
+       unsigned long offset;
        enum pg_level level;
        pte_t *pte;
 
        pte = lookup_address(virt_addr, &level);
        BUG_ON(!pte);
 
+       /*
+        * pXX_pfn() returns unsigned long, which must be cast to phys_addr_t
+        * before being left-shifted PAGE_SHIFT bits -- this trick is to
+        * make 32-PAE kernel work correctly.
+        */
        switch (level) {
        case PG_LEVEL_1G:
-               phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
+               phys_addr = (phys_addr_t)pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
                offset = virt_addr & ~PUD_PAGE_MASK;
                break;
        case PG_LEVEL_2M:
-               phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
+               phys_addr = (phys_addr_t)pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
                offset = virt_addr & ~PMD_PAGE_MASK;
                break;
        default:
-               phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
+               phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
                offset = virt_addr & ~PAGE_MASK;
        }
 
index 2879efc73a967bca70606547014decd3703c84bf..d34b5118b4e8e7a30c55d722733d03b00bade013 100644 (file)
@@ -711,28 +711,22 @@ int pcibios_add_device(struct pci_dev *dev)
        return 0;
 }
 
-int pcibios_alloc_irq(struct pci_dev *dev)
+int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-       /*
-        * If the PCI device was already claimed by core code and has
-        * MSI enabled, probing of the pcibios IRQ will overwrite
-        * dev->irq.  So bail out if MSI is already enabled.
-        */
-       if (pci_dev_msi_enabled(dev))
-               return -EBUSY;
+       int err;
 
-       return pcibios_enable_irq(dev);
-}
+       if ((err = pci_enable_resources(dev, mask)) < 0)
+               return err;
 
-void pcibios_free_irq(struct pci_dev *dev)
-{
-       if (pcibios_disable_irq)
-               pcibios_disable_irq(dev);
+       if (!pci_dev_msi_enabled(dev))
+               return pcibios_enable_irq(dev);
+       return 0;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+void pcibios_disable_device (struct pci_dev *dev)
 {
-       return pci_enable_resources(dev, mask);
+       if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+               pcibios_disable_irq(dev);
 }
 
 int pci_ext_cfg_avail(void)
index 0d24e7c101454057f432dd976ea7e3d537e0a38c..8b93e634af84c4698e6f7c6ab718a018e2cdc9db 100644 (file)
@@ -215,7 +215,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
        int polarity;
        int ret;
 
-       if (pci_has_managed_irq(dev))
+       if (dev->irq_managed && dev->irq > 0)
                return 0;
 
        switch (intel_mid_identify_cpu()) {
@@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-       if (pci_has_managed_irq(dev)) {
+       if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
+           dev->irq > 0) {
                mp_unmap_irq(dev->irq);
                dev->irq_managed = 0;
-               /*
-                * Don't reset dev->irq here, otherwise
-                * intel_mid_pci_irq_enable() will fail on next call.
-                */
        }
 }
 
index 32e70343e6fdd0e58ab80644284dd01000dccd82..9bd115484745703791c6515b289938546d2478ab 100644 (file)
@@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        struct pci_dev *temp_dev;
                        int irq;
 
-                       if (pci_has_managed_irq(dev))
+                       if (dev->irq_managed && dev->irq > 0)
                                return 0;
 
                        irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
@@ -1230,7 +1230,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        }
                        dev = temp_dev;
                        if (irq >= 0) {
-                               pci_set_managed_irq(dev, irq);
+                               dev->irq_managed = 1;
+                               dev->irq = irq;
                                dev_info(&dev->dev, "PCI->APIC IRQ transform: "
                                         "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
                                return 0;
@@ -1256,10 +1257,24 @@ static int pirq_enable_irq(struct pci_dev *dev)
        return 0;
 }
 
+bool mp_should_keep_irq(struct device *dev)
+{
+       if (dev->power.is_prepared)
+               return true;
+#ifdef CONFIG_PM
+       if (dev->power.runtime_status == RPM_SUSPENDING)
+               return true;
+#endif
+
+       return false;
+}
+
 static void pirq_disable_irq(struct pci_dev *dev)
 {
-       if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
+       if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
+           dev->irq_managed && dev->irq) {
                mp_unmap_irq(dev->irq);
-               pci_reset_managed_irq(dev);
+               dev->irq = 0;
+               dev->irq_managed = 0;
        }
 }
index ff31ab464213fc49f21d0dde5bdcb14cc0763020..beac4dfdade6c05c02591e924fd913d5db53abcd 100644 (file)
@@ -196,7 +196,10 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        return 0;
 
 error:
-       dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
+       if (ret == -ENOSYS)
+               dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
+       else if (ret)
+               dev_err(&dev->dev, "Xen PCI frontend error: %d!\n", ret);
 free:
        kfree(v);
        return ret;
index c61b6c332e971929fd4d639b9754e8707f513930..bfadcd0f4944276e39999cd00b86d6c786d1a085 100644 (file)
@@ -592,14 +592,14 @@ static void __init imr_fixup_memmap(struct imr_device *idev)
        end = (unsigned long)__end_rodata - 1;
 
        /*
-        * Setup a locked IMR around the physical extent of the kernel
+        * Setup an unlocked IMR around the physical extent of the kernel
         * from the beginning of the .text secton to the end of the
         * .rodata section as one physically contiguous block.
         *
         * We don't round up @size since it is already PAGE_SIZE aligned.
         * See vmlinux.lds.S for details.
         */
-       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, true);
+       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
        if (ret < 0) {
                pr_err("unable to setup IMR for kernel: %zu KiB (%lx - %lx)\n",
                        size / 1024, start, end);
index 8502ad30e61bcfc49a9e28c975d356b4b628a62c..5adb6a2fd117df01c232156e2091bfc3d190eac7 100644 (file)
@@ -109,7 +109,7 @@ unsigned long os_get_top_address(void)
                exit(1);
        }
 
-       printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
+       printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
        printf("Locating the top of the address space ... ");
        fflush(stdout);
 
@@ -134,7 +134,7 @@ out:
                exit(1);
        }
        top <<= UM_KERN_PAGE_SHIFT;
-       printf("0x%x\n", top);
+       printf("0x%lx\n", top);
 
        return top;
 }
index 161491d0a879ed11ce2276a1923a60bc1d92479e..0363cd731320d8d9d93cdcd8e3fb5351682e6464 100644 (file)
@@ -88,6 +88,19 @@ config BLK_DEV_INTEGRITY
        T10/SCSI Data Integrity Field or the T13/ATA External Path
        Protection.  If in doubt, say N.
 
+config BLK_DEV_DAX
+       bool "Block device DAX support"
+       depends on FS_DAX
+       depends on BROKEN
+       help
+         When DAX support is available (CONFIG_FS_DAX) raw block
+         devices can also support direct userspace access to the
+         storage capacity via MMAP(2) similar to a file on a
+         DAX-enabled filesystem.  However, the DAX I/O-path disables
+         some standard I/O-statistics, and the MMAP(2) path has some
+         operational differences due to bypassing the page
+         cache.  If in doubt, say N.
+
 config BLK_DEV_THROTTLING
        bool "Block layer bio throttling support"
        depends on BLK_CGROUP=y
index dbabd48b1934739bba125827e2019414cf34adee..cf7591551b1716b74fa3765cb1c271a554e8ef56 100644 (file)
@@ -874,7 +874,7 @@ int submit_bio_wait(int rw, struct bio *bio)
        bio->bi_private = &ret;
        bio->bi_end_io = submit_bio_wait_endio;
        submit_bio(rw, bio);
-       wait_for_completion(&ret.event);
+       wait_for_completion_io(&ret.event);
 
        return ret.error;
 }
@@ -1090,9 +1090,12 @@ int bio_uncopy_user(struct bio *bio)
        if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
                /*
                 * if we're in a workqueue, the request is orphaned, so
-                * don't copy into a random user address space, just free.
+                * don't copy into a random user address space, just free
+                * and return -EINTR so user space doesn't expect any data.
                 */
-               if (current->mm && bio_data_dir(bio) == READ)
+               if (!current->mm)
+                       ret = -EINTR;
+               else if (bio_data_dir(bio) == READ)
                        ret = bio_copy_to_iter(bio, bmd->iter);
                if (bmd->is_our_pages)
                        bio_free_pages(bio);
index 5a37188b559fba8feb1da48b00d5290c3a6a09b6..66e6f1aae02eeb14de30ada1e6696622082729c1 100644 (file)
@@ -788,6 +788,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
 {
        struct gendisk *disk;
        struct blkcg_gq *blkg;
+       struct module *owner;
        unsigned int major, minor;
        int key_len, part, ret;
        char *body;
@@ -804,7 +805,9 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
        if (!disk)
                return -ENODEV;
        if (part) {
+               owner = disk->fops->owner;
                put_disk(disk);
+               module_put(owner);
                return -ENODEV;
        }
 
@@ -820,7 +823,9 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
                ret = PTR_ERR(blkg);
                rcu_read_unlock();
                spin_unlock_irq(disk->queue->queue_lock);
+               owner = disk->fops->owner;
                put_disk(disk);
+               module_put(owner);
                /*
                 * If queue was bypassing, we should retry.  Do so after a
                 * short msleep().  It isn't strictly necessary but queue
@@ -851,9 +856,13 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep);
 void blkg_conf_finish(struct blkg_conf_ctx *ctx)
        __releases(ctx->disk->queue->queue_lock) __releases(rcu)
 {
+       struct module *owner;
+
        spin_unlock_irq(ctx->disk->queue->queue_lock);
        rcu_read_unlock();
+       owner = ctx->disk->fops->owner;
        put_disk(ctx->disk);
+       module_put(owner);
 }
 EXPORT_SYMBOL_GPL(blkg_conf_finish);
 
index ab51685988c253616f751615ba06206732149de4..b83d29755b5a04509edd3ebfe70f89f354a09932 100644 (file)
@@ -2455,14 +2455,16 @@ struct request *blk_peek_request(struct request_queue *q)
 
                        rq = NULL;
                        break;
-               } else if (ret == BLKPREP_KILL) {
+               } else if (ret == BLKPREP_KILL || ret == BLKPREP_INVALID) {
+                       int err = (ret == BLKPREP_INVALID) ? -EREMOTEIO : -EIO;
+
                        rq->cmd_flags |= REQ_QUIET;
                        /*
                         * Mark this request as started so we don't trigger
                         * any debug logic in the end I/O path.
                         */
                        blk_start_request(rq);
-                       __blk_end_request_all(rq, -EIO);
+                       __blk_end_request_all(rq, err);
                } else {
                        printk(KERN_ERR "%s: bad return=%d\n", __func__, ret);
                        break;
index f565e11f465aa145120973bce58ef7ecc192f349..a54f0543b956e5ccf5f20206e7983fe66ce2698d 100644 (file)
@@ -57,6 +57,49 @@ static int __blk_rq_unmap_user(struct bio *bio)
        return ret;
 }
 
+static int __blk_rq_map_user_iov(struct request *rq,
+               struct rq_map_data *map_data, struct iov_iter *iter,
+               gfp_t gfp_mask, bool copy)
+{
+       struct request_queue *q = rq->q;
+       struct bio *bio, *orig_bio;
+       int ret;
+
+       if (copy)
+               bio = bio_copy_user_iov(q, map_data, iter, gfp_mask);
+       else
+               bio = bio_map_user_iov(q, iter, gfp_mask);
+
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
+
+       if (map_data && map_data->null_mapped)
+               bio_set_flag(bio, BIO_NULL_MAPPED);
+
+       iov_iter_advance(iter, bio->bi_iter.bi_size);
+       if (map_data)
+               map_data->offset += bio->bi_iter.bi_size;
+
+       orig_bio = bio;
+       blk_queue_bounce(q, &bio);
+
+       /*
+        * We link the bounce buffer in and could have to traverse it
+        * later so we have to get a ref to prevent it from being freed
+        */
+       bio_get(bio);
+
+       ret = blk_rq_append_bio(q, rq, bio);
+       if (ret) {
+               bio_endio(bio);
+               __blk_rq_unmap_user(orig_bio);
+               bio_put(bio);
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage
  * @q:         request queue where request should be inserted
@@ -82,10 +125,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                        struct rq_map_data *map_data,
                        const struct iov_iter *iter, gfp_t gfp_mask)
 {
-       struct bio *bio;
-       int unaligned = 0;
-       struct iov_iter i;
        struct iovec iov, prv = {.iov_base = NULL, .iov_len = 0};
+       bool copy = (q->dma_pad_mask & iter->count) || map_data;
+       struct bio *bio = NULL;
+       struct iov_iter i;
+       int ret;
 
        if (!iter || !iter->count)
                return -EINVAL;
@@ -101,42 +145,29 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                 */
                if ((uaddr & queue_dma_alignment(q)) ||
                    iovec_gap_to_prv(q, &prv, &iov))
-                       unaligned = 1;
+                       copy = true;
 
                prv.iov_base = iov.iov_base;
                prv.iov_len = iov.iov_len;
        }
 
-       if (unaligned || (q->dma_pad_mask & iter->count) || map_data)
-               bio = bio_copy_user_iov(q, map_data, iter, gfp_mask);
-       else
-               bio = bio_map_user_iov(q, iter, gfp_mask);
-
-       if (IS_ERR(bio))
-               return PTR_ERR(bio);
-
-       if (map_data && map_data->null_mapped)
-               bio_set_flag(bio, BIO_NULL_MAPPED);
-
-       if (bio->bi_iter.bi_size != iter->count) {
-               /*
-                * Grab an extra reference to this bio, as bio_unmap_user()
-                * expects to be able to drop it twice as it happens on the
-                * normal IO completion path
-                */
-               bio_get(bio);
-               bio_endio(bio);
-               __blk_rq_unmap_user(bio);
-               return -EINVAL;
-       }
+       i = *iter;
+       do {
+               ret =__blk_rq_map_user_iov(rq, map_data, &i, gfp_mask, copy);
+               if (ret)
+                       goto unmap_rq;
+               if (!bio)
+                       bio = rq->bio;
+       } while (iov_iter_count(&i));
 
        if (!bio_flagged(bio, BIO_USER_MAPPED))
                rq->cmd_flags |= REQ_COPY_USER;
-
-       blk_queue_bounce(q, &bio);
-       bio_get(bio);
-       blk_rq_bio_prep(q, rq, bio);
        return 0;
+
+unmap_rq:
+       __blk_rq_unmap_user(bio);
+       rq->bio = NULL;
+       return -EINVAL;
 }
 EXPORT_SYMBOL(blk_rq_map_user_iov);
 
index 888a7fec81f715199c3050576516e55b692f2b9b..261353166dcf33a042ea4466ecae044388dddc98 100644 (file)
@@ -304,7 +304,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
        struct bio_vec end_bv = { NULL }, nxt_bv;
-       struct bvec_iter iter;
 
        if (!blk_queue_cluster(q))
                return 0;
@@ -316,11 +315,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
        if (!bio_has_data(bio))
                return 1;
 
-       bio_for_each_segment(end_bv, bio, iter)
-               if (end_bv.bv_len == iter.bi_size)
-                       break;
-
-       nxt_bv = bio_iovec(nxt);
+       bio_get_last_bvec(bio, &end_bv);
+       bio_get_first_bvec(nxt, &nxt_bv);
 
        if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv))
                return 0;
index 4c0622fae41383d0f5577ea9b8b127d93df33bb6..56c0a726b619374ec9f8cf4b60649a14919f0625 100644 (file)
@@ -599,8 +599,10 @@ static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
                 * If a request wasn't started before the queue was
                 * marked dying, kill it here or it'll go unnoticed.
                 */
-               if (unlikely(blk_queue_dying(rq->q)))
-                       blk_mq_complete_request(rq, -EIO);
+               if (unlikely(blk_queue_dying(rq->q))) {
+                       rq->errors = -EIO;
+                       blk_mq_end_request(rq, rq->errors);
+               }
                return;
        }
 
index dd49735839789167d427dc8b64da71c6b21f08f5..c7bb666aafd100a329c67b97e616c9f9037c508e 100644 (file)
@@ -91,8 +91,8 @@ void blk_set_default_limits(struct queue_limits *lim)
        lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
        lim->virt_boundary_mask = 0;
        lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
-       lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors =
-               BLK_SAFE_MAX_SECTORS;
+       lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
+       lim->max_dev_sectors = 0;
        lim->chunk_sectors = 0;
        lim->max_write_same_sectors = 0;
        lim->max_discard_sectors = 0;
index e140cc487ce11349ff1917e4e866eccf0a18106c..dd93763057ce0187dcc1b81602b75a43310d451d 100644 (file)
@@ -147,10 +147,9 @@ static ssize_t queue_discard_granularity_show(struct request_queue *q, char *pag
 
 static ssize_t queue_discard_max_hw_show(struct request_queue *q, char *page)
 {
-       unsigned long long val;
 
-       val = q->limits.max_hw_discard_sectors << 9;
-       return sprintf(page, "%llu\n", val);
+       return sprintf(page, "%llu\n",
+               (unsigned long long)q->limits.max_hw_discard_sectors << 9);
 }
 
 static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
index a753df2b3fc29324a850442966b15199bc932508..d0dd7882d8c7fa7ffe80ea2e9a6ad3c0f5e97a68 100644 (file)
@@ -39,7 +39,6 @@ struct deadline_data {
         */
        struct request *next_rq[2];
        unsigned int batching;          /* number of sequential requests made */
-       sector_t last_sector;           /* head position */
        unsigned int starved;           /* times reads have starved writes */
 
        /*
@@ -210,8 +209,6 @@ deadline_move_request(struct deadline_data *dd, struct request *rq)
        dd->next_rq[WRITE] = NULL;
        dd->next_rq[data_dir] = deadline_latter_request(rq);
 
-       dd->last_sector = rq_end_sector(rq);
-
        /*
         * take it off the sort and fifo list, move
         * to dispatch queue
index 38c1aa89d3a0a7c4448bcd094ca1f268b9156a2d..28556fce42671e2f182d5239d3dc6468e5b1d970 100644 (file)
@@ -65,18 +65,10 @@ struct skcipher_async_req {
        struct skcipher_async_rsgl first_sgl;
        struct list_head list;
        struct scatterlist *tsg;
-       char iv[];
+       atomic_t *inflight;
+       struct skcipher_request req;
 };
 
-#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
-       crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
-
-#define GET_REQ_SIZE(ctx) \
-       crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
-
-#define GET_IV_SIZE(ctx) \
-       crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
-
 #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
                      sizeof(struct scatterlist) - 1)
 
@@ -102,15 +94,12 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq)
 
 static void skcipher_async_cb(struct crypto_async_request *req, int err)
 {
-       struct sock *sk = req->data;
-       struct alg_sock *ask = alg_sk(sk);
-       struct skcipher_ctx *ctx = ask->private;
-       struct skcipher_async_req *sreq = GET_SREQ(req, ctx);
+       struct skcipher_async_req *sreq = req->data;
        struct kiocb *iocb = sreq->iocb;
 
-       atomic_dec(&ctx->inflight);
+       atomic_dec(sreq->inflight);
        skcipher_free_async_sgls(sreq);
-       kfree(req);
+       kzfree(sreq);
        iocb->ki_complete(iocb, err, err);
 }
 
@@ -306,8 +295,11 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
 {
        struct sock *sk = sock->sk;
        struct alg_sock *ask = alg_sk(sk);
+       struct sock *psk = ask->parent;
+       struct alg_sock *pask = alg_sk(psk);
        struct skcipher_ctx *ctx = ask->private;
-       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
+       struct skcipher_tfm *skc = pask->private;
+       struct crypto_skcipher *tfm = skc->skcipher;
        unsigned ivsize = crypto_skcipher_ivsize(tfm);
        struct skcipher_sg_list *sgl;
        struct af_alg_control con = {};
@@ -509,37 +501,43 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
 {
        struct sock *sk = sock->sk;
        struct alg_sock *ask = alg_sk(sk);
+       struct sock *psk = ask->parent;
+       struct alg_sock *pask = alg_sk(psk);
        struct skcipher_ctx *ctx = ask->private;
+       struct skcipher_tfm *skc = pask->private;
+       struct crypto_skcipher *tfm = skc->skcipher;
        struct skcipher_sg_list *sgl;
        struct scatterlist *sg;
        struct skcipher_async_req *sreq;
        struct skcipher_request *req;
        struct skcipher_async_rsgl *last_rsgl = NULL;
-       unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
-       unsigned int reqlen = sizeof(struct skcipher_async_req) +
-                               GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx);
+       unsigned int txbufs = 0, len = 0, tx_nents;
+       unsigned int reqsize = crypto_skcipher_reqsize(tfm);
+       unsigned int ivsize = crypto_skcipher_ivsize(tfm);
        int err = -ENOMEM;
        bool mark = false;
+       char *iv;
 
-       lock_sock(sk);
-       req = kmalloc(reqlen, GFP_KERNEL);
-       if (unlikely(!req))
-               goto unlock;
+       sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
+       if (unlikely(!sreq))
+               goto out;
 
-       sreq = GET_SREQ(req, ctx);
+       req = &sreq->req;
+       iv = (char *)(req + 1) + reqsize;
        sreq->iocb = msg->msg_iocb;
-       memset(&sreq->first_sgl, '\0', sizeof(struct skcipher_async_rsgl));
        INIT_LIST_HEAD(&sreq->list);
+       sreq->inflight = &ctx->inflight;
+
+       lock_sock(sk);
+       tx_nents = skcipher_all_sg_nents(ctx);
        sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
-       if (unlikely(!sreq->tsg)) {
-               kfree(req);
+       if (unlikely(!sreq->tsg))
                goto unlock;
-       }
        sg_init_table(sreq->tsg, tx_nents);
-       memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
-       skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
-       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                     skcipher_async_cb, sk);
+       memcpy(iv, ctx->iv, ivsize);
+       skcipher_request_set_tfm(req, tfm);
+       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
+                                     skcipher_async_cb, sreq);
 
        while (iov_iter_count(&msg->msg_iter)) {
                struct skcipher_async_rsgl *rsgl;
@@ -615,20 +613,22 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
                sg_mark_end(sreq->tsg + txbufs - 1);
 
        skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
-                                  len, sreq->iv);
+                                  len, iv);
        err = ctx->enc ? crypto_skcipher_encrypt(req) :
                         crypto_skcipher_decrypt(req);
        if (err == -EINPROGRESS) {
                atomic_inc(&ctx->inflight);
                err = -EIOCBQUEUED;
+               sreq = NULL;
                goto unlock;
        }
 free:
        skcipher_free_async_sgls(sreq);
-       kfree(req);
 unlock:
        skcipher_wmem_wakeup(sk);
        release_sock(sk);
+       kzfree(sreq);
+out:
        return err;
 }
 
@@ -637,9 +637,12 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
 {
        struct sock *sk = sock->sk;
        struct alg_sock *ask = alg_sk(sk);
+       struct sock *psk = ask->parent;
+       struct alg_sock *pask = alg_sk(psk);
        struct skcipher_ctx *ctx = ask->private;
-       unsigned bs = crypto_skcipher_blocksize(crypto_skcipher_reqtfm(
-               &ctx->req));
+       struct skcipher_tfm *skc = pask->private;
+       struct crypto_skcipher *tfm = skc->skcipher;
+       unsigned bs = crypto_skcipher_blocksize(tfm);
        struct skcipher_sg_list *sgl;
        struct scatterlist *sg;
        int err = -EAGAIN;
@@ -947,7 +950,8 @@ static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
        ask->private = ctx;
 
        skcipher_request_set_tfm(&ctx->req, skcipher);
-       skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+       skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
+                                                CRYPTO_TFM_REQ_MAY_BACKLOG,
                                      af_alg_complete, &ctx->completion);
 
        sk->sk_destruct = skcipher_sock_destruct;
index 237f3795cfaaa1f988fadf5b07eefe3c44609091..43fe85f20d577b4f3d1bbd6576b6d752bc578531 100644 (file)
@@ -499,6 +499,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (link->dump == NULL)
                        return -EINVAL;
 
+               down_read(&crypto_alg_sem);
                list_for_each_entry(alg, &crypto_alg_list, cra_list)
                        dump_alloc += CRYPTO_REPORT_MAXSIZE;
 
@@ -508,8 +509,11 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                .done = link->done,
                                .min_dump_alloc = dump_alloc,
                        };
-                       return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
+                       err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
                }
+               up_read(&crypto_alg_sem);
+
+               return err;
        }
 
        err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
index ad6d8c6b777e7c83885cc3f854396808153653f3..35947ac8764459ab0cea484d66bb3f7e7589dc82 100644 (file)
@@ -469,37 +469,16 @@ static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc,
        nfit_mem->bdw = NULL;
 }
 
-static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
+static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc,
                struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa)
 {
        u16 dcr = __to_nfit_memdev(nfit_mem)->region_index;
        struct nfit_memdev *nfit_memdev;
        struct nfit_flush *nfit_flush;
-       struct nfit_dcr *nfit_dcr;
        struct nfit_bdw *nfit_bdw;
        struct nfit_idt *nfit_idt;
        u16 idt_idx, range_index;
 
-       list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
-               if (nfit_dcr->dcr->region_index != dcr)
-                       continue;
-               nfit_mem->dcr = nfit_dcr->dcr;
-               break;
-       }
-
-       if (!nfit_mem->dcr) {
-               dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n",
-                               spa->range_index, __to_nfit_memdev(nfit_mem)
-                               ? "" : " MEMDEV", nfit_mem->dcr ? "" : " DCR");
-               return -ENODEV;
-       }
-
-       /*
-        * We've found enough to create an nvdimm, optionally
-        * find an associated BDW
-        */
-       list_add(&nfit_mem->list, &acpi_desc->dimms);
-
        list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) {
                if (nfit_bdw->bdw->region_index != dcr)
                        continue;
@@ -508,12 +487,12 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
        }
 
        if (!nfit_mem->bdw)
-               return 0;
+               return;
 
        nfit_mem_find_spa_bdw(acpi_desc, nfit_mem);
 
        if (!nfit_mem->spa_bdw)
-               return 0;
+               return;
 
        range_index = nfit_mem->spa_bdw->range_index;
        list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
@@ -538,8 +517,6 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
                }
                break;
        }
-
-       return 0;
 }
 
 static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
@@ -548,7 +525,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
        struct nfit_mem *nfit_mem, *found;
        struct nfit_memdev *nfit_memdev;
        int type = nfit_spa_type(spa);
-       u16 dcr;
 
        switch (type) {
        case NFIT_SPA_DCR:
@@ -559,14 +535,18 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
        }
 
        list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
-               int rc;
+               struct nfit_dcr *nfit_dcr;
+               u32 device_handle;
+               u16 dcr;
 
                if (nfit_memdev->memdev->range_index != spa->range_index)
                        continue;
                found = NULL;
                dcr = nfit_memdev->memdev->region_index;
+               device_handle = nfit_memdev->memdev->device_handle;
                list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
-                       if (__to_nfit_memdev(nfit_mem)->region_index == dcr) {
+                       if (__to_nfit_memdev(nfit_mem)->device_handle
+                                       == device_handle) {
                                found = nfit_mem;
                                break;
                        }
@@ -579,6 +559,31 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
                        if (!nfit_mem)
                                return -ENOMEM;
                        INIT_LIST_HEAD(&nfit_mem->list);
+                       list_add(&nfit_mem->list, &acpi_desc->dimms);
+               }
+
+               list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
+                       if (nfit_dcr->dcr->region_index != dcr)
+                               continue;
+                       /*
+                        * Record the control region for the dimm.  For
+                        * the ACPI 6.1 case, where there are separate
+                        * control regions for the pmem vs blk
+                        * interfaces, be sure to record the extended
+                        * blk details.
+                        */
+                       if (!nfit_mem->dcr)
+                               nfit_mem->dcr = nfit_dcr->dcr;
+                       else if (nfit_mem->dcr->windows == 0
+                                       && nfit_dcr->dcr->windows)
+                               nfit_mem->dcr = nfit_dcr->dcr;
+                       break;
+               }
+
+               if (dcr && !nfit_mem->dcr) {
+                       dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n",
+                                       spa->range_index, dcr);
+                       return -ENODEV;
                }
 
                if (type == NFIT_SPA_DCR) {
@@ -595,6 +600,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
                                nfit_mem->idt_dcr = nfit_idt->idt;
                                break;
                        }
+                       nfit_mem_init_bdw(acpi_desc, nfit_mem, spa);
                } else {
                        /*
                         * A single dimm may belong to multiple SPA-PM
@@ -603,13 +609,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
                         */
                        nfit_mem->memdev_pmem = nfit_memdev->memdev;
                }
-
-               if (found)
-                       continue;
-
-               rc = nfit_mem_add(acpi_desc, nfit_mem, spa);
-               if (rc)
-                       return rc;
        }
 
        return 0;
@@ -1504,9 +1503,7 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
                case 1:
                        /* ARS unsupported, but we should never get here */
                        return 0;
-               case 2:
-                       return -EINVAL;
-               case 3:
+               case 6:
                        /* ARS is in progress */
                        msleep(1000);
                        break;
@@ -1517,13 +1514,13 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
 }
 
 static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc,
-               struct nd_cmd_ars_status *cmd)
+               struct nd_cmd_ars_status *cmd, u32 size)
 {
        int rc;
 
        while (1) {
                rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd,
-                       sizeof(*cmd));
+                       size);
                if (rc || cmd->status & 0xffff)
                        return -ENXIO;
 
@@ -1538,6 +1535,8 @@ static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc,
                case 2:
                        /* No ARS performed for the current boot */
                        return 0;
+               case 3:
+                       /* TODO: error list overflow support */
                default:
                        return -ENXIO;
                }
@@ -1581,6 +1580,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
        struct nd_cmd_ars_start *ars_start = NULL;
        struct nd_cmd_ars_cap *ars_cap = NULL;
        u64 start, len, cur, remaining;
+       u32 ars_status_size;
        int rc;
 
        ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL);
@@ -1590,14 +1590,21 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
        start = ndr_desc->res->start;
        len = ndr_desc->res->end - ndr_desc->res->start + 1;
 
+       /*
+        * If ARS is unimplemented, unsupported, or if the 'Persistent Memory
+        * Scrub' flag in extended status is not set, skip this but continue
+        * initialization
+        */
        rc = ars_get_cap(nd_desc, ars_cap, start, len);
+       if (rc == -ENOTTY) {
+               dev_dbg(acpi_desc->dev,
+                       "Address Range Scrub is not implemented, won't create an error list\n");
+               rc = 0;
+               goto out;
+       }
        if (rc)
                goto out;
 
-       /*
-        * If ARS is unsupported, or if the 'Persistent Memory Scrub' flag in
-        * extended status is not set, skip this but continue initialization
-        */
        if ((ars_cap->status & 0xffff) ||
                !(ars_cap->status >> 16 & ND_ARS_PERSISTENT)) {
                dev_warn(acpi_desc->dev,
@@ -1610,14 +1617,14 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
         * Check if a full-range ARS has been run. If so, use those results
         * without having to start a new ARS.
         */
-       ars_status = kzalloc(ars_cap->max_ars_out + sizeof(*ars_status),
-                       GFP_KERNEL);
+       ars_status_size = ars_cap->max_ars_out;
+       ars_status = kzalloc(ars_status_size, GFP_KERNEL);
        if (!ars_status) {
                rc = -ENOMEM;
                goto out;
        }
 
-       rc = ars_get_status(nd_desc, ars_status);
+       rc = ars_get_status(nd_desc, ars_status, ars_status_size);
        if (rc)
                goto out;
 
@@ -1647,7 +1654,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
                if (rc)
                        goto out;
 
-               rc = ars_get_status(nd_desc, ars_status);
+               rc = ars_get_status(nd_desc, ars_status, ars_status_size);
                if (rc)
                        goto out;
 
index d30184c7f3bcb851c62fe410906160b6e802a631..c8e169e46673ae253882872cda7a94249540c3a5 100644 (file)
@@ -406,7 +406,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                return 0;
        }
 
-       if (pci_has_managed_irq(dev))
+       if (dev->irq_managed && dev->irq > 0)
                return 0;
 
        entry = acpi_pci_irq_lookup(dev, pin);
@@ -451,7 +451,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                kfree(entry);
                return rc;
        }
-       pci_set_managed_irq(dev, rc);
+       dev->irq = rc;
+       dev->irq_managed = 1;
 
        if (link)
                snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -474,9 +475,17 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        u8 pin;
 
        pin = dev->pin;
-       if (!pin || !pci_has_managed_irq(dev))
+       if (!pin || !dev->irq_managed || dev->irq <= 0)
                return;
 
+       /* Keep IOAPIC pin configuration when suspending */
+       if (dev->dev.power.is_prepared)
+               return;
+#ifdef CONFIG_PM
+       if (dev->dev.power.runtime_status == RPM_SUSPENDING)
+               return;
+#endif
+
        entry = acpi_pci_irq_lookup(dev, pin);
        if (!entry)
                return;
@@ -496,6 +505,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
        if (gsi >= 0) {
                acpi_unregister_gsi(gsi);
-               pci_reset_managed_irq(dev);
+               dev->irq_managed = 0;
        }
 }
index fa2863567eed3c944c884245118c0d55d5ec5fdd..ededa909df2fc02eb2b77fb495e43f8e850c5469 100644 (file)
@@ -4,7 +4,6 @@
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
- *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -438,6 +437,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
+#define ACPI_MAX_IRQS          256
 #define ACPI_MAX_ISA_IRQ       16
 
 #define PIRQ_PENALTY_PCI_AVAILABLE     (0)
@@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 #define PIRQ_PENALTY_ISA_USED          (16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS                (16*16*16*16*16*16)
 
-static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ0 timer */
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ1 keyboard */
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ2 cascade */
@@ -464,68 +464,9 @@ static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
        PIRQ_PENALTY_ISA_USED,          /* IRQ13 fpe, sometimes */
        PIRQ_PENALTY_ISA_USED,          /* IRQ14 ide0 */
        PIRQ_PENALTY_ISA_USED,          /* IRQ15 ide1 */
+       /* >IRQ15 */
 };
 
-struct irq_penalty_info {
-       int irq;
-       int penalty;
-       struct list_head node;
-};
-
-static LIST_HEAD(acpi_irq_penalty_list);
-
-static int acpi_irq_get_penalty(int irq)
-{
-       struct irq_penalty_info *irq_info;
-
-       if (irq < ACPI_MAX_ISA_IRQ)
-               return acpi_irq_isa_penalty[irq];
-
-       list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
-               if (irq_info->irq == irq)
-                       return irq_info->penalty;
-       }
-
-       return 0;
-}
-
-static int acpi_irq_set_penalty(int irq, int new_penalty)
-{
-       struct irq_penalty_info *irq_info;
-
-       /* see if this is a ISA IRQ */
-       if (irq < ACPI_MAX_ISA_IRQ) {
-               acpi_irq_isa_penalty[irq] = new_penalty;
-               return 0;
-       }
-
-       /* next, try to locate from the dynamic list */
-       list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
-               if (irq_info->irq == irq) {
-                       irq_info->penalty  = new_penalty;
-                       return 0;
-               }
-       }
-
-       /* nope, let's allocate a slot for this IRQ */
-       irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL);
-       if (!irq_info)
-               return -ENOMEM;
-
-       irq_info->irq = irq;
-       irq_info->penalty = new_penalty;
-       list_add_tail(&irq_info->node, &acpi_irq_penalty_list);
-
-       return 0;
-}
-
-static void acpi_irq_add_penalty(int irq, int penalty)
-{
-       int curpen = acpi_irq_get_penalty(irq);
-
-       acpi_irq_set_penalty(irq, curpen + penalty);
-}
-
 int __init acpi_irq_penalty_init(void)
 {
        struct acpi_pci_link *link;
@@ -546,16 +487,15 @@ int __init acpi_irq_penalty_init(void)
                            link->irq.possible_count;
 
                        for (i = 0; i < link->irq.possible_count; i++) {
-                               if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) {
-                                       int irqpos = link->irq.possible[i];
-
-                                       acpi_irq_add_penalty(irqpos, penalty);
-                               }
+                               if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
+                                       acpi_irq_penalty[link->irq.
+                                                        possible[i]] +=
+                                           penalty;
                        }
 
                } else if (link->irq.active) {
-                       acpi_irq_add_penalty(link->irq.active,
-                                            PIRQ_PENALTY_PCI_POSSIBLE);
+                       acpi_irq_penalty[link->irq.active] +=
+                           PIRQ_PENALTY_PCI_POSSIBLE;
                }
        }
 
@@ -607,12 +547,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                 * the use of IRQs 9, 10, 11, and >15.
                 */
                for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_get_penalty(irq) >
-                           acpi_irq_get_penalty(link->irq.possible[i]))
+                       if (acpi_irq_penalty[irq] >
+                           acpi_irq_penalty[link->irq.possible[i]])
                                irq = link->irq.possible[i];
                }
        }
-       if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
+       if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
                printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
                            "Try pci=noacpi or acpi=off\n",
                            acpi_device_name(link->device),
@@ -628,8 +568,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                            acpi_device_bid(link->device));
                return -ENODEV;
        } else {
-               acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING);
-
+               acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
                printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
                       acpi_device_name(link->device),
                       acpi_device_bid(link->device), link->irq.active);
@@ -839,7 +778,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
 }
 
 /*
- * modify penalty from cmdline
+ * modify acpi_irq_penalty[] from cmdline
  */
 static int __init acpi_irq_penalty_update(char *str, int used)
 {
@@ -857,10 +796,13 @@ static int __init acpi_irq_penalty_update(char *str, int used)
                if (irq < 0)
                        continue;
 
+               if (irq >= ARRAY_SIZE(acpi_irq_penalty))
+                       continue;
+
                if (used)
-                       acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED);
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
                else
-                       acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE);
+                       acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
 
                if (retval != 2)        /* no next number */
                        break;
@@ -877,15 +819,18 @@ static int __init acpi_irq_penalty_update(char *str, int used)
  */
 void acpi_penalize_isa_irq(int irq, int active)
 {
-       if (irq >= 0)
-               acpi_irq_add_penalty(irq, active ?
-                       PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
+       if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
+               if (active)
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
+               else
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
+       }
 }
 
 bool acpi_isa_irq_available(int irq)
 {
-       return irq >= 0 &&
-               (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
+       return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
+                           acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
 }
 
 /*
@@ -895,18 +840,13 @@ bool acpi_isa_irq_available(int irq)
  */
 void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
 {
-       int penalty;
-
-       if (irq < 0)
-               return;
-
-       if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
-           polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
-               penalty = PIRQ_PENALTY_ISA_ALWAYS;
-       else
-               penalty = PIRQ_PENALTY_PCI_USING;
-
-       acpi_irq_add_penalty(irq, penalty);
+       if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
+               if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
+                   polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
+               else
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
+       }
 }
 
 /*
index a39e85f9efa98854768f39b01502274401673957..7d00b7a015ead0182feaace6231a8d7fad719b64 100644 (file)
@@ -2074,7 +2074,7 @@ static int binder_thread_write(struct binder_proc *proc,
                        if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
 
-                       ptr += sizeof(void *);
+                       ptr += sizeof(cookie);
                        list_for_each_entry(w, &proc->delivered_death, entry) {
                                struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
 
index 594fcabd22cd16bfcc09626338a3da33481497cc..146dc0b8ec61752c03278cf5121061aaaf4c27ce 100644 (file)
@@ -264,6 +264,26 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
+       { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
        { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
        { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
        { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
@@ -347,15 +367,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
        { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
        { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
        { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -1305,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 {}
 #endif
 
+#ifdef CONFIG_ARM64
+/*
+ * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
+ * Workaround is to make sure all pending IRQs are served before leaving
+ * handler.
+ */
+static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
+{
+       struct ata_host *host = dev_instance;
+       struct ahci_host_priv *hpriv;
+       unsigned int rc = 0;
+       void __iomem *mmio;
+       u32 irq_stat, irq_masked;
+       unsigned int handled = 1;
+
+       VPRINTK("ENTER\n");
+       hpriv = host->private_data;
+       mmio = hpriv->mmio;
+       irq_stat = readl(mmio + HOST_IRQ_STAT);
+       if (!irq_stat)
+               return IRQ_NONE;
+
+       do {
+               irq_masked = irq_stat & hpriv->port_map;
+               spin_lock(&host->lock);
+               rc = ahci_handle_port_intr(host, irq_masked);
+               if (!rc)
+                       handled = 0;
+               writel(irq_stat, mmio + HOST_IRQ_STAT);
+               irq_stat = readl(mmio + HOST_IRQ_STAT);
+               spin_unlock(&host->lock);
+       } while (irq_stat);
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(handled);
+}
+#endif
+
 /*
  * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
  * to single msi.
@@ -1540,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ahci_broken_devslp(pdev))
                hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
 
+#ifdef CONFIG_ARM64
+       if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
+               hpriv->irq_handler = ahci_thunderx_irq_handler;
+#endif
+
        /* save initial config */
        ahci_pci_save_initial_config(pdev, hpriv);
 
index a4faa438889c075070084fb1f1cd943d61082a88..167ba7e3b92e8fcec115ddcbd1988326e7c67ba5 100644 (file)
@@ -240,8 +240,7 @@ enum {
                                                        error-handling stage) */
        AHCI_HFLAG_NO_DEVSLP            = (1 << 17), /* no device sleep */
        AHCI_HFLAG_NO_FBS               = (1 << 18), /* no FBS */
-       AHCI_HFLAG_EDGE_IRQ             = (1 << 19), /* HOST_IRQ_STAT behaves as
-                                                       Edge Triggered */
+
 #ifdef CONFIG_PCI_MSI
        AHCI_HFLAG_MULTI_MSI            = (1 << 20), /* multiple PCI MSIs */
        AHCI_HFLAG_MULTI_MSIX           = (1 << 21), /* per-port MSI-X */
@@ -250,6 +249,7 @@ enum {
        AHCI_HFLAG_MULTI_MSI            = 0,
        AHCI_HFLAG_MULTI_MSIX           = 0,
 #endif
+       AHCI_HFLAG_WAKE_BEFORE_STOP     = (1 << 22), /* wake before DMA stop */
 
        /* ap->flags bits */
 
@@ -360,6 +360,7 @@ struct ahci_host_priv {
         * be overridden anytime before the host is activated.
         */
        void                    (*start_engine)(struct ata_port *ap);
+       irqreturn_t             (*irq_handler)(int irq, void *dev_instance);
 };
 
 #ifdef CONFIG_PCI_MSI
@@ -423,6 +424,7 @@ int ahci_reset_em(struct ata_host *host);
 void ahci_print_info(struct ata_host *host, const char *scc_s);
 int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
 void ahci_error_handler(struct ata_port *ap);
+u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
 
 static inline void __iomem *__ahci_port_base(struct ata_host *host,
                                             unsigned int port_no)
index b36cae2fd04b2b2969cfefcfe54f63beadef48e2..e87bcec0fd7c31d9623e54cf84fa6c62b41f2f39 100644 (file)
@@ -317,6 +317,7 @@ static int brcm_ahci_probe(struct platform_device *pdev)
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
        hpriv->plat_data = priv;
+       hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;
 
        brcm_sata_alpm_init(hpriv);
 
index e2c6d9e0c5ac5ce5ce389b0ae1b0597ae979ee8b..8e3f7faf00d383f8eea284fe122e90a44ee7ce40 100644 (file)
@@ -548,6 +548,88 @@ softreset_retry:
        return rc;
 }
 
+/**
+ * xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
+ * @ata_host: Host that recieved the irq
+ * @irq_masked: HOST_IRQ_STAT value
+ *
+ * For hardware with broken edge trigger latch
+ * the HOST_IRQ_STAT register misses the edge interrupt
+ * when clearing of HOST_IRQ_STAT register and hardware
+ * reporting the PORT_IRQ_STAT register at the
+ * same clock cycle.
+ * As such, the algorithm below outlines the workaround.
+ *
+ * 1. Read HOST_IRQ_STAT register and save the state.
+ * 2. Clear the HOST_IRQ_STAT register.
+ * 3. Read back the HOST_IRQ_STAT register.
+ * 4. If HOST_IRQ_STAT register equals to zero, then
+ *    traverse the rest of port's PORT_IRQ_STAT register
+ *    to check if an interrupt is triggered at that point else
+ *    go to step 6.
+ * 5. If PORT_IRQ_STAT register of rest ports is not equal to zero
+ *    then update the state of HOST_IRQ_STAT saved in step 1.
+ * 6. Handle port interrupts.
+ * 7. Exit
+ */
+static int xgene_ahci_handle_broken_edge_irq(struct ata_host *host,
+                                            u32 irq_masked)
+{
+       struct ahci_host_priv *hpriv = host->private_data;
+       void __iomem *port_mmio;
+       int i;
+
+       if (!readl(hpriv->mmio + HOST_IRQ_STAT)) {
+               for (i = 0; i < host->n_ports; i++) {
+                       if (irq_masked & (1 << i))
+                               continue;
+
+                       port_mmio = ahci_port_base(host->ports[i]);
+                       if (readl(port_mmio + PORT_IRQ_STAT))
+                               irq_masked |= (1 << i);
+               }
+       }
+
+       return ahci_handle_port_intr(host, irq_masked);
+}
+
+static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance)
+{
+       struct ata_host *host = dev_instance;
+       struct ahci_host_priv *hpriv;
+       unsigned int rc = 0;
+       void __iomem *mmio;
+       u32 irq_stat, irq_masked;
+
+       VPRINTK("ENTER\n");
+
+       hpriv = host->private_data;
+       mmio = hpriv->mmio;
+
+       /* sigh.  0xffffffff is a valid return from h/w */
+       irq_stat = readl(mmio + HOST_IRQ_STAT);
+       if (!irq_stat)
+               return IRQ_NONE;
+
+       irq_masked = irq_stat & hpriv->port_map;
+
+       spin_lock(&host->lock);
+
+       /*
+        * HOST_IRQ_STAT behaves as edge triggered latch meaning that
+        * it should be cleared before all the port events are cleared.
+        */
+       writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+       rc = xgene_ahci_handle_broken_edge_irq(host, irq_masked);
+
+       spin_unlock(&host->lock);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(rc);
+}
+
 static struct ata_port_operations xgene_ahci_v1_ops = {
        .inherits = &ahci_ops,
        .host_stop = xgene_ahci_host_stop,
@@ -779,7 +861,8 @@ skip_clk_phy:
                hpriv->flags = AHCI_HFLAG_NO_NCQ;
                break;
        case XGENE_AHCI_V2:
-               hpriv->flags |= AHCI_HFLAG_YES_FBS | AHCI_HFLAG_EDGE_IRQ;
+               hpriv->flags |= AHCI_HFLAG_YES_FBS;
+               hpriv->irq_handler = xgene_ahci_irq_intr;
                break;
        default:
                break;
index d61740e78d6dc93a1b17d9e3c9d9425067190a21..85ea5142a09518acc9e5c781fffbbf737f262f31 100644 (file)
@@ -113,6 +113,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
                                    const char *buf, size_t size);
 static ssize_t ahci_show_em_supported(struct device *dev,
                                      struct device_attribute *attr, char *buf);
+static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance);
 
 static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
@@ -496,8 +497,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
                }
        }
 
-       /* fabricate port_map from cap.nr_ports */
-       if (!port_map) {
+       /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
+       if (!port_map && vers < 0x10300) {
                port_map = (1 << ahci_nr_ports(cap)) - 1;
                dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
 
@@ -512,6 +513,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 
        if (!hpriv->start_engine)
                hpriv->start_engine = ahci_start_engine;
+
+       if (!hpriv->irq_handler)
+               hpriv->irq_handler = ahci_single_level_irq_intr;
 }
 EXPORT_SYMBOL_GPL(ahci_save_initial_config);
 
@@ -593,8 +597,22 @@ EXPORT_SYMBOL_GPL(ahci_start_engine);
 int ahci_stop_engine(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        u32 tmp;
 
+       /*
+        * On some controllers, stopping a port's DMA engine while the port
+        * is in ALPM state (partial or slumber) results in failures on
+        * subsequent DMA engine starts.  For those controllers, put the
+        * port back in active state before stopping its DMA engine.
+        */
+       if ((hpriv->flags & AHCI_HFLAG_WAKE_BEFORE_STOP) &&
+           (ap->link.lpm_policy > ATA_LPM_MAX_POWER) &&
+           ahci_set_lpm(&ap->link, ATA_LPM_MAX_POWER, ATA_LPM_WAKE_ONLY)) {
+               dev_err(ap->host->dev, "Failed to wake up port before engine stop\n");
+               return -EIO;
+       }
+
        tmp = readl(port_mmio + PORT_CMD);
 
        /* check if the HBA is idle */
@@ -689,6 +707,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
        void __iomem *port_mmio = ahci_port_base(ap);
 
        if (policy != ATA_LPM_MAX_POWER) {
+               /* wakeup flag only applies to the max power policy */
+               hints &= ~ATA_LPM_WAKE_ONLY;
+
                /*
                 * Disable interrupts on Phy Ready. This keeps us from
                 * getting woken up due to spurious phy ready
@@ -704,7 +725,8 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
                u32 cmd = readl(port_mmio + PORT_CMD);
 
                if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
-                       cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
+                       if (!(hints & ATA_LPM_WAKE_ONLY))
+                               cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
                        cmd |= PORT_CMD_ICC_ACTIVE;
 
                        writel(cmd, port_mmio + PORT_CMD);
@@ -712,6 +734,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 
                        /* wait 10ms to be sure we've come out of LPM state */
                        ata_msleep(ap, 10);
+
+                       if (hints & ATA_LPM_WAKE_ONLY)
+                               return 0;
                } else {
                        cmd |= PORT_CMD_ALPE;
                        if (policy == ATA_LPM_MIN_POWER)
@@ -1143,8 +1168,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
 
        /* mark esata ports */
        tmp = readl(port_mmio + PORT_CMD);
-       if ((tmp & PORT_CMD_HPCP) ||
-           ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
+       if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))
                ap->pflags |= ATA_PFLAG_EXTERNAL;
 }
 
@@ -1825,7 +1849,7 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
-static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
+u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
 {
        unsigned int i, handled = 0;
 
@@ -1851,43 +1875,7 @@ static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
 
        return handled;
 }
-
-static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance)
-{
-       struct ata_host *host = dev_instance;
-       struct ahci_host_priv *hpriv;
-       unsigned int rc = 0;
-       void __iomem *mmio;
-       u32 irq_stat, irq_masked;
-
-       VPRINTK("ENTER\n");
-
-       hpriv = host->private_data;
-       mmio = hpriv->mmio;
-
-       /* sigh.  0xffffffff is a valid return from h/w */
-       irq_stat = readl(mmio + HOST_IRQ_STAT);
-       if (!irq_stat)
-               return IRQ_NONE;
-
-       irq_masked = irq_stat & hpriv->port_map;
-
-       spin_lock(&host->lock);
-
-       /*
-        * HOST_IRQ_STAT behaves as edge triggered latch meaning that
-        * it should be cleared before all the port events are cleared.
-        */
-       writel(irq_stat, mmio + HOST_IRQ_STAT);
-
-       rc = ahci_handle_port_intr(host, irq_masked);
-
-       spin_unlock(&host->lock);
-
-       VPRINTK("EXIT\n");
-
-       return IRQ_RETVAL(rc);
-}
+EXPORT_SYMBOL_GPL(ahci_handle_port_intr);
 
 static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance)
 {
@@ -2514,14 +2502,18 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht)
        int irq = hpriv->irq;
        int rc;
 
-       if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX))
+       if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) {
+               if (hpriv->irq_handler)
+                       dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \
+                                and custom irq handler implemented\n");
+
                rc = ahci_host_activate_multi_irqs(host, sht);
-       else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ)
-               rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr,
-                                      IRQF_SHARED, sht);
-       else
-               rc = ata_host_activate(host, irq, ahci_single_level_irq_intr,
+       } else {
+               rc = ata_host_activate(host, irq, hpriv->irq_handler,
                                       IRQF_SHARED, sht);
+       }
+
+
        return rc;
 }
 EXPORT_SYMBOL_GPL(ahci_host_activate);
index cbb74719d2c1b80d61590ddf3fb2f9c71a31ce06..55e257c268ddde37677cf4ff85472f65e9a63c97 100644 (file)
@@ -4125,6 +4125,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "SAMSUNG CD-ROM SN-124", "N001",      ATA_HORKAGE_NODMA },
        { "Seagate STT20000A", NULL,            ATA_HORKAGE_NODMA },
        { " 2GB ATA Flash Disk", "ADMA428M",    ATA_HORKAGE_NODMA },
+       { "VRFDFC22048UCHC-TE*", NULL,          ATA_HORKAGE_NODMA },
        /* Odd clown on sil3726/4726 PMPs */
        { "Config  Disk",       NULL,           ATA_HORKAGE_DISABLE },
 
index 7e959f90c0203f9b94124ab73867e4a72bd11188..e417e1a1d02c568595fa465682ade483a9d0645a 100644 (file)
@@ -675,19 +675,18 @@ static int ata_ioc32(struct ata_port *ap)
 int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
                     int cmd, void __user *arg)
 {
-       int val = -EINVAL, rc = -EINVAL;
+       unsigned long val;
+       int rc = -EINVAL;
        unsigned long flags;
 
        switch (cmd) {
-       case ATA_IOC_GET_IO32:
+       case HDIO_GET_32BIT:
                spin_lock_irqsave(ap->lock, flags);
                val = ata_ioc32(ap);
                spin_unlock_irqrestore(ap->lock, flags);
-               if (copy_to_user(arg, &val, 1))
-                       return -EFAULT;
-               return 0;
+               return put_user(val, (unsigned long __user *)arg);
 
-       case ATA_IOC_SET_IO32:
+       case HDIO_SET_32BIT:
                val = (unsigned long) arg;
                rc = 0;
                spin_lock_irqsave(ap->lock, flags);
index cdf6215a9a22beb93ede75a702797e12c5ad4870..051b6158d1b7f45b7116b9debc98376a9d4d240f 100644 (file)
@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap,
 static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
 {
        struct ata_port *ap = qc->ap;
-       unsigned long flags;
 
        if (ap->ops->error_handler) {
                if (in_wq) {
-                       spin_lock_irqsave(ap->lock, flags);
-
                        /* EH might have kicked in while host lock is
                         * released.
                         */
@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
                                } else
                                        ata_port_freeze(ap);
                        }
-
-                       spin_unlock_irqrestore(ap->lock, flags);
                } else {
                        if (likely(!(qc->err_mask & AC_ERR_HSM)))
                                ata_qc_complete(qc);
@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
                }
        } else {
                if (in_wq) {
-                       spin_lock_irqsave(ap->lock, flags);
                        ata_sff_irq_on(ap);
                        ata_qc_complete(qc);
-                       spin_unlock_irqrestore(ap->lock, flags);
                } else
                        ata_qc_complete(qc);
        }
@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
 {
        struct ata_link *link = qc->dev->link;
        struct ata_eh_info *ehi = &link->eh_info;
-       unsigned long flags = 0;
        int poll_next;
 
+       lockdep_assert_held(ap->lock);
+
        WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
 
        /* Make sure ata_sff_qc_issue() does not throw things
@@ -1112,14 +1106,6 @@ fsm_start:
                        }
                }
 
-               /* Send the CDB (atapi) or the first data block (ata pio out).
-                * During the state transition, interrupt handler shouldn't
-                * be invoked before the data transfer is complete and
-                * hsm_task_state is changed. Hence, the following locking.
-                */
-               if (in_wq)
-                       spin_lock_irqsave(ap->lock, flags);
-
                if (qc->tf.protocol == ATA_PROT_PIO) {
                        /* PIO data out protocol.
                         * send first data block.
@@ -1135,9 +1121,6 @@ fsm_start:
                        /* send CDB */
                        atapi_send_cdb(ap, qc);
 
-               if (in_wq)
-                       spin_unlock_irqrestore(ap->lock, flags);
-
                /* if polling, ata_sff_pio_task() handles the rest.
                 * otherwise, interrupt handler takes over from here.
                 */
@@ -1296,7 +1279,8 @@ fsm_start:
                break;
        default:
                poll_next = 0;
-               BUG();
+               WARN(true, "ata%d: SFF host state machine in invalid state %d",
+                    ap->print_id, ap->hsm_task_state);
        }
 
        return poll_next;
@@ -1361,12 +1345,14 @@ static void ata_sff_pio_task(struct work_struct *work)
        u8 status;
        int poll_next;
 
+       spin_lock_irq(ap->lock);
+
        BUG_ON(ap->sff_pio_task_link == NULL);
        /* qc can be NULL if timeout occurred */
        qc = ata_qc_from_tag(ap, link->active_tag);
        if (!qc) {
                ap->sff_pio_task_link = NULL;
-               return;
+               goto out_unlock;
        }
 
 fsm_start:
@@ -1381,11 +1367,14 @@ fsm_start:
         */
        status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
        if (status & ATA_BUSY) {
+               spin_unlock_irq(ap->lock);
                ata_msleep(ap, 2);
+               spin_lock_irq(ap->lock);
+
                status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
                if (status & ATA_BUSY) {
                        ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
-                       return;
+                       goto out_unlock;
                }
        }
 
@@ -1402,6 +1391,8 @@ fsm_start:
         */
        if (poll_next)
                goto fsm_start;
+out_unlock:
+       spin_unlock_irq(ap->lock);
 }
 
 /**
index 12fe0f3bb7e9b0bf8120af19badf4ddf72903565..c8b6a780a29050775f66ec60bc89773d71677683 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
 
+#include <asm/mach-rc32434/rb.h>
+
 #define DRV_NAME       "pata-rb532-cf"
 #define DRV_VERSION    "0.1.0"
 #define DRV_DESC       "PATA driver for RouterBOARD 532 Compact Flash"
@@ -107,6 +109,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
        int gpio;
        struct resource *res;
        struct ata_host *ah;
+       struct cf_device *pdata;
        struct rb532_cf_info *info;
        int ret;
 
@@ -122,7 +125,13 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
                return -ENOENT;
        }
 
-       gpio = irq_to_gpio(irq);
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data specified\n");
+               return -EINVAL;
+       }
+
+       gpio = pdata->gpio_pin;
        if (gpio < 0) {
                dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
                return -ENOENT;
index 89f5cf68d80a143198c2c253d6d21c0d9fb38388..04a1582e80bb83d00fa80c3fb95d325bb165b261 100644 (file)
@@ -206,6 +206,8 @@ static void component_match_release(struct device *master,
                if (mc->release)
                        mc->release(master, mc->data);
        }
+
+       kfree(match->compare);
 }
 
 static void devm_component_match_release(struct device *dev, void *res)
@@ -221,14 +223,14 @@ static int component_match_realloc(struct device *dev,
        if (match->alloc == num)
                return 0;
 
-       new = devm_kmalloc_array(dev, num, sizeof(*new), GFP_KERNEL);
+       new = kmalloc_array(num, sizeof(*new), GFP_KERNEL);
        if (!new)
                return -ENOMEM;
 
        if (match->compare) {
                memcpy(new, match->compare, sizeof(*new) *
                                            min(match->num, num));
-               devm_kfree(dev, match->compare);
+               kfree(match->compare);
        }
        match->compare = new;
        match->alloc = num;
@@ -283,6 +285,24 @@ void component_match_add_release(struct device *master,
 }
 EXPORT_SYMBOL(component_match_add_release);
 
+static void free_master(struct master *master)
+{
+       struct component_match *match = master->match;
+       int i;
+
+       list_del(&master->node);
+
+       if (match) {
+               for (i = 0; i < match->num; i++) {
+                       struct component *c = match->compare[i].component;
+                       if (c)
+                               c->master = NULL;
+               }
+       }
+
+       kfree(master);
+}
+
 int component_master_add_with_match(struct device *dev,
        const struct component_master_ops *ops,
        struct component_match *match)
@@ -309,11 +329,9 @@ int component_master_add_with_match(struct device *dev,
 
        ret = try_to_bring_up_master(master, NULL);
 
-       if (ret < 0) {
-               /* Delete off the list if we weren't successful */
-               list_del(&master->node);
-               kfree(master);
-       }
+       if (ret < 0)
+               free_master(master);
+
        mutex_unlock(&component_mutex);
 
        return ret < 0 ? ret : 0;
@@ -324,25 +342,12 @@ void component_master_del(struct device *dev,
        const struct component_master_ops *ops)
 {
        struct master *master;
-       int i;
 
        mutex_lock(&component_mutex);
        master = __master_find(dev, ops);
        if (master) {
-               struct component_match *match = master->match;
-
                take_down_master(master);
-
-               list_del(&master->node);
-
-               if (match) {
-                       for (i = 0; i < match->num; i++) {
-                               struct component *c = match->compare[i].component;
-                               if (c)
-                                       c->master = NULL;
-                       }
-               }
-               kfree(master);
+               free_master(master);
        }
        mutex_unlock(&component_mutex);
 }
@@ -486,6 +491,8 @@ int component_add(struct device *dev, const struct component_ops *ops)
 
        ret = try_to_bring_up_masters(component);
        if (ret < 0) {
+               if (component->master)
+                       remove_component(component->master, component);
                list_del(&component->node);
 
                kfree(component);
index 348be3a354108eb2533587dabed9495e9c324b5a..cccceb599b025b5e8b6a6fb8dac4f672d29ccecb 100644 (file)
@@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map)
        int i, j;
        int ret;
        int count;
-       unsigned int val;
+       unsigned int reg, val;
        void *tmp_buf;
 
        if (!map->num_reg_defaults_raw)
@@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map)
                ret = regmap_raw_read(map, 0, tmp_buf,
                                      map->num_reg_defaults_raw);
                map->cache_bypass = cache_bypass;
-               if (ret < 0)
-                       goto err_cache_free;
-
-               map->reg_defaults_raw = tmp_buf;
-               map->cache_free = 1;
+               if (ret == 0) {
+                       map->reg_defaults_raw = tmp_buf;
+                       map->cache_free = 1;
+               } else {
+                       kfree(tmp_buf);
+               }
        }
 
        /* fill the reg_defaults */
        for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
-               if (regmap_volatile(map, i * map->reg_stride))
+               reg = i * map->reg_stride;
+
+               if (!regmap_readable(map, reg))
                        continue;
-               val = regcache_get_val(map, map->reg_defaults_raw, i);
-               map->reg_defaults[j].reg = i * map->reg_stride;
+
+               if (regmap_volatile(map, reg))
+                       continue;
+
+               if (map->reg_defaults_raw) {
+                       val = regcache_get_val(map, map->reg_defaults_raw, i);
+               } else {
+                       bool cache_bypass = map->cache_bypass;
+
+                       map->cache_bypass = true;
+                       ret = regmap_read(map, reg, &val);
+                       map->cache_bypass = cache_bypass;
+                       if (ret != 0) {
+                               dev_err(map->dev, "Failed to read %d: %d\n",
+                                       reg, ret);
+                               goto err_free;
+                       }
+               }
+
+               map->reg_defaults[j].reg = reg;
                map->reg_defaults[j].def = val;
                j++;
        }
 
        return 0;
 
-err_cache_free:
-       kfree(tmp_buf);
 err_free:
        kfree(map->reg_defaults);
 
index 8812bfb9e3b89256f4a5d1468cf45484b18e4cd1..7526906ca080f81dcff1499b7e57c2ff0b79569e 100644 (file)
 
 struct regmap_mmio_context {
        void __iomem *regs;
-       unsigned reg_bytes;
        unsigned val_bytes;
-       unsigned pad_bytes;
        struct clk *clk;
-};
 
-static inline void regmap_mmio_regsize_check(size_t reg_size)
-{
-       switch (reg_size) {
-       case 1:
-       case 2:
-       case 4:
-#ifdef CONFIG_64BIT
-       case 8:
-#endif
-               break;
-       default:
-               BUG();
-       }
-}
+       void (*reg_write)(struct regmap_mmio_context *ctx,
+                         unsigned int reg, unsigned int val);
+       unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
+                                unsigned int reg);
+};
 
 static int regmap_mmio_regbits_check(size_t reg_bits)
 {
@@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits)
        return min_stride;
 }
 
-static inline void regmap_mmio_count_check(size_t count, u32 offset)
+static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
+                               unsigned int reg,
+                               unsigned int val)
+{
+       writeb(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
 {
-       BUG_ON(count <= offset);
+       writew(val, ctx->regs + reg);
 }
 
-static inline unsigned int
-regmap_mmio_get_offset(const void *reg, size_t reg_size)
+static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
 {
-       switch (reg_size) {
-       case 1:
-               return *(u8 *)reg;
-       case 2:
-               return *(u16 *)reg;
-       case 4:
-               return *(u32 *)reg;
+       iowrite16be(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
+{
+       writel(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
+{
+       iowrite32be(val, ctx->regs + reg);
+}
+
 #ifdef CONFIG_64BIT
-       case 8:
-               return *(u64 *)reg;
-#endif
-       default:
-               BUG();
-       }
+static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
+{
+       writeq(val, ctx->regs + reg);
 }
+#endif
 
-static int regmap_mmio_gather_write(void *context,
-                                   const void *reg, size_t reg_size,
-                                   const void *val, size_t val_size)
+static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
 {
        struct regmap_mmio_context *ctx = context;
-       unsigned int offset;
        int ret;
 
-       regmap_mmio_regsize_check(reg_size);
-
        if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
        }
 
-       offset = regmap_mmio_get_offset(reg, reg_size);
-
-       while (val_size) {
-               switch (ctx->val_bytes) {
-               case 1:
-                       __raw_writeb(*(u8 *)val, ctx->regs + offset);
-                       break;
-               case 2:
-                       __raw_writew(*(u16 *)val, ctx->regs + offset);
-                       break;
-               case 4:
-                       __raw_writel(*(u32 *)val, ctx->regs + offset);
-                       break;
-#ifdef CONFIG_64BIT
-               case 8:
-                       __raw_writeq(*(u64 *)val, ctx->regs + offset);
-                       break;
-#endif
-               default:
-                       /* Should be caught by regmap_mmio_check_config */
-                       BUG();
-               }
-               val_size -= ctx->val_bytes;
-               val += ctx->val_bytes;
-               offset += ctx->val_bytes;
-       }
+       ctx->reg_write(ctx, reg, val);
 
        if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
@@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context,
        return 0;
 }
 
-static int regmap_mmio_write(void *context, const void *data, size_t count)
+static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
+                                     unsigned int reg)
 {
-       struct regmap_mmio_context *ctx = context;
-       unsigned int offset = ctx->reg_bytes + ctx->pad_bytes;
+       return readb(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return readw(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return ioread16be(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return readl(ctx->regs + reg);
+}
 
-       regmap_mmio_count_check(count, offset);
+static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return ioread32be(ctx->regs + reg);
+}
 
-       return regmap_mmio_gather_write(context, data, ctx->reg_bytes,
-                                       data + offset, count - offset);
+#ifdef CONFIG_64BIT
+static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return readq(ctx->regs + reg);
 }
+#endif
 
-static int regmap_mmio_read(void *context,
-                           const void *reg, size_t reg_size,
-                           void *val, size_t val_size)
+static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
 {
        struct regmap_mmio_context *ctx = context;
-       unsigned int offset;
        int ret;
 
-       regmap_mmio_regsize_check(reg_size);
-
        if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
        }
 
-       offset = regmap_mmio_get_offset(reg, reg_size);
-
-       while (val_size) {
-               switch (ctx->val_bytes) {
-               case 1:
-                       *(u8 *)val = __raw_readb(ctx->regs + offset);
-                       break;
-               case 2:
-                       *(u16 *)val = __raw_readw(ctx->regs + offset);
-                       break;
-               case 4:
-                       *(u32 *)val = __raw_readl(ctx->regs + offset);
-                       break;
-#ifdef CONFIG_64BIT
-               case 8:
-                       *(u64 *)val = __raw_readq(ctx->regs + offset);
-                       break;
-#endif
-               default:
-                       /* Should be caught by regmap_mmio_check_config */
-                       BUG();
-               }
-               val_size -= ctx->val_bytes;
-               val += ctx->val_bytes;
-               offset += ctx->val_bytes;
-       }
+       *val = ctx->reg_read(ctx, reg);
 
        if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
@@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context)
        kfree(context);
 }
 
-static struct regmap_bus regmap_mmio = {
+static const struct regmap_bus regmap_mmio = {
        .fast_io = true,
-       .write = regmap_mmio_write,
-       .gather_write = regmap_mmio_gather_write,
-       .read = regmap_mmio_read,
+       .reg_write = regmap_mmio_write,
+       .reg_read = regmap_mmio_read,
        .free_context = regmap_mmio_free_context,
-       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-       .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
 };
 
 static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
@@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
        if (config->reg_stride < min_stride)
                return ERR_PTR(-EINVAL);
 
-       switch (config->reg_format_endian) {
-       case REGMAP_ENDIAN_DEFAULT:
-       case REGMAP_ENDIAN_NATIVE:
-               break;
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
        ctx->regs = regs;
        ctx->val_bytes = config->val_bits / 8;
-       ctx->reg_bytes = config->reg_bits / 8;
-       ctx->pad_bytes = config->pad_bits / 8;
        ctx->clk = ERR_PTR(-ENODEV);
 
+       switch (config->reg_format_endian) {
+       case REGMAP_ENDIAN_DEFAULT:
+       case REGMAP_ENDIAN_LITTLE:
+#ifdef __LITTLE_ENDIAN
+       case REGMAP_ENDIAN_NATIVE:
+#endif
+               switch (config->val_bits) {
+               case 8:
+                       ctx->reg_read = regmap_mmio_read8;
+                       ctx->reg_write = regmap_mmio_write8;
+                       break;
+               case 16:
+                       ctx->reg_read = regmap_mmio_read16le;
+                       ctx->reg_write = regmap_mmio_write16le;
+                       break;
+               case 32:
+                       ctx->reg_read = regmap_mmio_read32le;
+                       ctx->reg_write = regmap_mmio_write32le;
+                       break;
+#ifdef CONFIG_64BIT
+               case 64:
+                       ctx->reg_read = regmap_mmio_read64le;
+                       ctx->reg_write = regmap_mmio_write64le;
+                       break;
+#endif
+               default:
+                       ret = -EINVAL;
+                       goto err_free;
+               }
+               break;
+       case REGMAP_ENDIAN_BIG:
+#ifdef __BIG_ENDIAN
+       case REGMAP_ENDIAN_NATIVE:
+#endif
+               switch (config->val_bits) {
+               case 8:
+                       ctx->reg_read = regmap_mmio_read8;
+                       ctx->reg_write = regmap_mmio_write8;
+                       break;
+               case 16:
+                       ctx->reg_read = regmap_mmio_read16be;
+                       ctx->reg_write = regmap_mmio_write16be;
+                       break;
+               case 32:
+                       ctx->reg_read = regmap_mmio_read32be;
+                       ctx->reg_write = regmap_mmio_write32be;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto err_free;
+               }
+               break;
+       default:
+               ret = -EINVAL;
+               goto err_free;
+       }
+
        if (clk_id == NULL)
                return ctx;
 
index ee54e841de4ad69c96ecb7897ddc04e889e8c702..e2f68807d970f6bce49124d4eaf39ec3c0e57ec7 100644 (file)
@@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
                        endian = REGMAP_ENDIAN_BIG;
                else if (of_property_read_bool(np, "little-endian"))
                        endian = REGMAP_ENDIAN_LITTLE;
+               else if (of_property_read_bool(np, "native-endian"))
+                       endian = REGMAP_ENDIAN_NATIVE;
 
                /* If the endianness was specified in DT, use that */
                if (endian != REGMAP_ENDIAN_DEFAULT)
@@ -2253,6 +2255,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 
        WARN_ON(!map->bus);
 
+       if (!map->bus || !map->bus->read)
+               return -EINVAL;
+
        range = _regmap_range_lookup(map, reg);
        if (range) {
                ret = _regmap_select_page(map, &reg, range,
index 9e251201dd48ef2a850b8069edf7ffc05be98a4e..84708a5f8c520cb86db4ad62a4b845a5ec83b88f 100644 (file)
@@ -866,7 +866,7 @@ static void set_fdc(int drive)
 }
 
 /* locks the driver */
-static int lock_fdc(int drive, bool interruptible)
+static int lock_fdc(int drive)
 {
        if (WARN(atomic_read(&usage_count) == 0,
                 "Trying to lock fdc while usage count=0\n"))
@@ -2173,7 +2173,7 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 {
        int ret;
 
-       if (lock_fdc(drive, true))
+       if (lock_fdc(drive))
                return -EINTR;
 
        set_floppy(drive);
@@ -2960,7 +2960,7 @@ static int user_reset_fdc(int drive, int arg, bool interruptible)
 {
        int ret;
 
-       if (lock_fdc(drive, interruptible))
+       if (lock_fdc(drive))
                return -EINTR;
 
        if (arg == FD_RESET_ALWAYS)
@@ -3243,7 +3243,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                mutex_lock(&open_lock);
-               if (lock_fdc(drive, true)) {
+               if (lock_fdc(drive)) {
                        mutex_unlock(&open_lock);
                        return -EINTR;
                }
@@ -3263,7 +3263,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g,
        } else {
                int oldStretch;
 
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                if (cmd != FDDEFPRM) {
                        /* notice a disk change immediately, else
@@ -3349,7 +3349,7 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
        if (type)
                *g = &floppy_type[type];
        else {
-               if (lock_fdc(drive, false))
+               if (lock_fdc(drive))
                        return -EINTR;
                if (poll_drive(false, 0) == -EINTR)
                        return -EINTR;
@@ -3433,7 +3433,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
                if (UDRS->fd_ref != 1)
                        /* somebody else has this drive open */
                        return -EBUSY;
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
 
                /* do the actual eject. Fails on
@@ -3445,7 +3445,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
                process_fd_request();
                return ret;
        case FDCLRPRM:
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                current_type[drive] = NULL;
                floppy_sizes[drive] = MAX_DISK_SIZE << 1;
@@ -3467,7 +3467,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
                UDP->flags &= ~FTD_MSG;
                return 0;
        case FDFMTBEG:
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
                        return -EINTR;
@@ -3484,7 +3484,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
                return do_format(drive, &inparam.f);
        case FDFMTEND:
        case FDFLUSH:
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                return invalidate_drive(bdev);
        case FDSETEMSGTRESH:
@@ -3507,7 +3507,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
                outparam = UDP;
                break;
        case FDPOLLDRVSTAT:
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
                        return -EINTR;
@@ -3530,7 +3530,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
        case FDRAWCMD:
                if (type)
                        return -EINVAL;
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                set_floppy(drive);
                i = raw_cmd_ioctl(cmd, (void __user *)param);
@@ -3539,7 +3539,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
                process_fd_request();
                return i;
        case FDTWADDLE:
-               if (lock_fdc(drive, true))
+               if (lock_fdc(drive))
                        return -EINTR;
                twaddle();
                process_fd_request();
@@ -3663,6 +3663,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
 
        opened_bdev[drive] = bdev;
 
+       if (!(mode & (FMODE_READ|FMODE_WRITE))) {
+               res = -EINVAL;
+               goto out;
+       }
+
        res = -ENXIO;
 
        if (!floppy_track_buffer) {
@@ -3706,21 +3711,20 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
        if (UFDCS->rawcmd == 1)
                UFDCS->rawcmd = 2;
 
-       if (!(mode & FMODE_NDELAY)) {
-               if (mode & (FMODE_READ|FMODE_WRITE)) {
-                       UDRS->last_checked = 0;
-                       clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
-                       check_disk_change(bdev);
-                       if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
-                               goto out;
-                       if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
-                               goto out;
-               }
-               res = -EROFS;
-               if ((mode & FMODE_WRITE) &&
-                   !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
-                       goto out;
-       }
+       UDRS->last_checked = 0;
+       clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
+       check_disk_change(bdev);
+       if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
+               goto out;
+       if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
+               goto out;
+
+       res = -EROFS;
+
+       if ((mode & FMODE_WRITE) &&
+                       !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
+               goto out;
+
        mutex_unlock(&open_lock);
        mutex_unlock(&floppy_mutex);
        return 0;
@@ -3748,7 +3752,8 @@ static unsigned int floppy_check_events(struct gendisk *disk,
                return DISK_EVENT_MEDIA_CHANGE;
 
        if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
-               lock_fdc(drive, false);
+               if (lock_fdc(drive))
+                       return -EINTR;
                poll_drive(false, 0);
                process_fd_request();
        }
@@ -3847,7 +3852,9 @@ static int floppy_revalidate(struct gendisk *disk)
                         "VFS: revalidate called on non-open device.\n"))
                        return -EFAULT;
 
-               lock_fdc(drive, false);
+               res = lock_fdc(drive);
+               if (res)
+                       return res;
                cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
                      test_bit(FD_VERIFY_BIT, &UDRS->flags));
                if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) {
index 8ba1e97d573c3b804c2ee7d14946f94b4c32fc93..64a7b5971b57046eafd210d726fa039b05bc705d 100644 (file)
@@ -478,7 +478,7 @@ static int null_lnvm_id(struct nvm_dev *dev, struct nvm_id *id)
        id->ver_id = 0x1;
        id->vmnt = 0;
        id->cgrps = 1;
-       id->cap = 0x3;
+       id->cap = 0x2;
        id->dom = 0x1;
 
        id->ppaf.blk_offset = 0;
@@ -707,9 +707,7 @@ static int null_add_dev(void)
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q);
        queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nullb->q);
 
-
        mutex_lock(&lock);
-       list_add_tail(&nullb->list, &nullb_list);
        nullb->index = nullb_indexes++;
        mutex_unlock(&lock);
 
@@ -743,6 +741,10 @@ static int null_add_dev(void)
        strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
 
        add_disk(disk);
+
+       mutex_lock(&lock);
+       list_add_tail(&nullb->list, &nullb_list);
+       mutex_unlock(&lock);
 done:
        return 0;
 
index 8a8dc91c39f7292be4fc0b1c172e12e97f5fed5c..83eb9e6bf8b06673640ff5d5ef05db1555e4912f 100644 (file)
@@ -1873,6 +1873,43 @@ again:
        return err;
 }
 
+static int negotiate_mq(struct blkfront_info *info)
+{
+       unsigned int backend_max_queues = 0;
+       int err;
+       unsigned int i;
+
+       BUG_ON(info->nr_rings);
+
+       /* Check if backend supports multiple queues. */
+       err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                          "multi-queue-max-queues", "%u", &backend_max_queues);
+       if (err < 0)
+               backend_max_queues = 1;
+
+       info->nr_rings = min(backend_max_queues, xen_blkif_max_queues);
+       /* We need at least one ring. */
+       if (!info->nr_rings)
+               info->nr_rings = 1;
+
+       info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL);
+       if (!info->rinfo) {
+               xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < info->nr_rings; i++) {
+               struct blkfront_ring_info *rinfo;
+
+               rinfo = &info->rinfo[i];
+               INIT_LIST_HEAD(&rinfo->indirect_pages);
+               INIT_LIST_HEAD(&rinfo->grants);
+               rinfo->dev_info = info;
+               INIT_WORK(&rinfo->work, blkif_restart_queue);
+               spin_lock_init(&rinfo->ring_lock);
+       }
+       return 0;
+}
 /**
  * Entry point to this code when a new device is created.  Allocate the basic
  * structures and the ring buffer for communication with the backend, and
@@ -1883,9 +1920,7 @@ static int blkfront_probe(struct xenbus_device *dev,
                          const struct xenbus_device_id *id)
 {
        int err, vdevice;
-       unsigned int r_index;
        struct blkfront_info *info;
-       unsigned int backend_max_queues = 0;
 
        /* FIXME: Use dynamic device id if this is not set. */
        err = xenbus_scanf(XBT_NIL, dev->nodename,
@@ -1936,33 +1971,10 @@ static int blkfront_probe(struct xenbus_device *dev,
        }
 
        info->xbdev = dev;
-       /* Check if backend supports multiple queues. */
-       err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-                          "multi-queue-max-queues", "%u", &backend_max_queues);
-       if (err < 0)
-               backend_max_queues = 1;
-
-       info->nr_rings = min(backend_max_queues, xen_blkif_max_queues);
-       /* We need at least one ring. */
-       if (!info->nr_rings)
-               info->nr_rings = 1;
-
-       info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL);
-       if (!info->rinfo) {
-               xenbus_dev_fatal(dev, -ENOMEM, "allocating ring_info structure");
+       err = negotiate_mq(info);
+       if (err) {
                kfree(info);
-               return -ENOMEM;
-       }
-
-       for (r_index = 0; r_index < info->nr_rings; r_index++) {
-               struct blkfront_ring_info *rinfo;
-
-               rinfo = &info->rinfo[r_index];
-               INIT_LIST_HEAD(&rinfo->indirect_pages);
-               INIT_LIST_HEAD(&rinfo->grants);
-               rinfo->dev_info = info;
-               INIT_WORK(&rinfo->work, blkif_restart_queue);
-               spin_lock_init(&rinfo->ring_lock);
+               return err;
        }
 
        mutex_init(&info->mutex);
@@ -2123,12 +2135,16 @@ static int blkif_recover(struct blkfront_info *info)
 static int blkfront_resume(struct xenbus_device *dev)
 {
        struct blkfront_info *info = dev_get_drvdata(&dev->dev);
-       int err;
+       int err = 0;
 
        dev_dbg(&dev->dev, "blkfront_resume: %s\n", dev->nodename);
 
        blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
 
+       err = negotiate_mq(info);
+       if (err)
+               return err;
+
        err = talk_to_blkback(dev, info);
 
        /*
index 240b6cf1d97c66fc828f97df90726cb64d500fba..be54e5331a4517899e0e4ace0c48418cbb082a0e 100644 (file)
@@ -42,7 +42,7 @@
 /*
  * The High Precision Event Timer driver.
  * This driver is closely modelled after the rtc.c driver.
- * http://www.intel.com/hardwaredesign/hpetspec_1.pdf
+ * See HPET spec revision 1.
  */
 #define        HPET_USER_FREQ  (64)
 #define        HPET_DRIFT      (500)
index d0da5d852d41e5588bb9bd192431a403a9696848..b583e53366306db870a0d61918156f41985f075e 100644 (file)
@@ -1818,6 +1818,28 @@ unsigned int get_random_int(void)
 }
 EXPORT_SYMBOL(get_random_int);
 
+/*
+ * Same as get_random_int(), but returns unsigned long.
+ */
+unsigned long get_random_long(void)
+{
+       __u32 *hash;
+       unsigned long ret;
+
+       if (arch_get_random_long(&ret))
+               return ret;
+
+       hash = get_cpu_var(get_random_int_hash);
+
+       hash[0] += current->pid + jiffies + random_get_entropy();
+       md5_transform(hash, random_int_secret);
+       ret = *(unsigned long *)hash;
+       put_cpu_var(get_random_int_hash);
+
+       return ret;
+}
+EXPORT_SYMBOL(get_random_long);
+
 /*
  * randomize_range() returns a start address such that
  *
index b038e36660587aaf97d4c3b41de17d1175635694..bae4be6501dfb06a51dc0aaa3befb91b47156ca0 100644 (file)
@@ -43,7 +43,7 @@ obj-$(CONFIG_COMMON_CLK_SI514)                += clk-si514.o
 obj-$(CONFIG_COMMON_CLK_SI570)         += clk-si570.o
 obj-$(CONFIG_COMMON_CLK_CDCE925)       += clk-cdce925.o
 obj-$(CONFIG_ARCH_STM32)               += clk-stm32f4.o
-obj-$(CONFIG_ARCH_TANGOX)              += clk-tango4.o
+obj-$(CONFIG_ARCH_TANGO              += clk-tango4.o
 obj-$(CONFIG_CLK_TWL6040)              += clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)                        += clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)              += clk-vt8500.o
index 19fed65587e8206c20f6ee13a1b736276e8922ae..7b09a265d79fc8595a31332ecd40480beaed7bc5 100644 (file)
@@ -289,7 +289,7 @@ static void __init of_gpio_clk_setup(struct device_node *node,
 
        num_parents = of_clk_get_parent_count(node);
        if (num_parents < 0)
-               return;
+               num_parents = 0;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
index cd0f2726f5e0dd0da33b06e4518f02fc231cf1f7..89e9ca78bb947ec2ff8242d5d826ccf8449d6259 100644 (file)
@@ -299,7 +299,7 @@ static int scpi_clocks_probe(struct platform_device *pdev)
        /* Add the virtual cpufreq device */
        cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
                                                      -1, NULL, 0);
-       if (!cpufreq_dev)
+       if (IS_ERR(cpufreq_dev))
                pr_warn("unable to register cpufreq device");
 
        return 0;
index d5c5bfa35a5aef734a47e6d199c410eebe237d75..3e0b52daa35f8814a413ccfe7599ac80a3f59e8f 100644 (file)
@@ -247,7 +247,7 @@ static struct clk_onecell_data dove_divider_data = {
 
 void __init dove_divider_clk_init(struct device_node *np)
 {
-       void *base;
+       void __iomem *base;
 
        base = of_iomap(np, 0);
        if (WARN_ON(!base))
index cf73e539e9f63aee727a5f3bab2e2e28fae4e1d9..070037a29ea5842ba6cd332563570fc1ffd8689c 100644 (file)
@@ -3587,7 +3587,6 @@ static const struct regmap_config gcc_apq8084_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x1fc0,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_apq8084_desc = {
index b692ae881d6a978a8d1e665dd09fa52820f96a90..dd5402bac62029824fd059a353d0c00d4e8576fc 100644 (file)
@@ -3005,7 +3005,6 @@ static const struct regmap_config gcc_ipq806x_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x3e40,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_ipq806x_desc = {
index f6a2b14dfec4ecd026282d01167278df0f2c6c3b..ad413036f7c783ee0ba8576bf512dfe3dea08dda 100644 (file)
@@ -2702,7 +2702,6 @@ static const struct regmap_config gcc_msm8660_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x363c,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8660_desc = {
index e3bf09d7d0ef07f5672f9933dca6dd6896daff4c..8cc9b2868b41a83c1621d0b27bc18598888a6939 100644 (file)
@@ -3336,7 +3336,6 @@ static const struct regmap_config gcc_msm8916_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x80000,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8916_desc = {
index f31111e32d44314f7c808aa56c3b6f78f906bbbb..983dd7dc89a7970e3c1c8d35a427a56b48959929 100644 (file)
@@ -3468,7 +3468,6 @@ static const struct regmap_config gcc_msm8960_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x3660,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct regmap_config gcc_apq8064_regmap_config = {
@@ -3477,7 +3476,6 @@ static const struct regmap_config gcc_apq8064_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x3880,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8960_desc = {
index df164d618e34682ba4f99f9e517c7b1bdd8500fd..335952db309bd3260c4c86cd048417fb43ac9cbd 100644 (file)
@@ -2680,7 +2680,6 @@ static const struct regmap_config gcc_msm8974_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x1fc0,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc gcc_msm8974_desc = {
index 62e79fadd5f7aee5772bef7760f9c7e20e721501..db3998e5e2d83d77a5b07f8d1e29490b2e532f6d 100644 (file)
@@ -419,7 +419,6 @@ static const struct regmap_config lcc_ipq806x_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0xfc,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc lcc_ipq806x_desc = {
index bf95bb0ea1b8c536a5e058de40e33edffa412021..4fcf9d1d233c0a0c64c2455efcdd11015da89b18 100644 (file)
@@ -524,7 +524,6 @@ static const struct regmap_config lcc_msm8960_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0xfc,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc lcc_msm8960_desc = {
index 1e703fda8a0f8ee4f18a0434a7ed073c1762ed6a..30777f9f1a439eef1ad5e8d4446017d7f3999392 100644 (file)
@@ -3368,7 +3368,6 @@ static const struct regmap_config mmcc_apq8084_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x5104,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc mmcc_apq8084_desc = {
index d73a048d3b9dc59c62fc3b413a59121d3b47fa06..00e36192a1defe9131f1f1505f89b88b574f4284 100644 (file)
@@ -3029,7 +3029,6 @@ static const struct regmap_config mmcc_msm8960_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x334,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct regmap_config mmcc_apq8064_regmap_config = {
@@ -3038,7 +3037,6 @@ static const struct regmap_config mmcc_apq8064_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x350,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc mmcc_msm8960_desc = {
index bbe28ed936692da75079aace6aa1cbc1e2ce23e4..9d790bcadf25a75a360f8d5aebfdf4ab50237c61 100644 (file)
@@ -2594,7 +2594,6 @@ static const struct regmap_config mmcc_msm8974_regmap_config = {
        .val_bits       = 32,
        .max_register   = 0x5104,
        .fast_io        = true,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static const struct qcom_cc_desc mmcc_msm8974_desc = {
index ebce98033fbb76ea687d439b5842e707f62eeb80..bc7fbac83ab74dfca9e534401bc430f629d01357 100644 (file)
@@ -133,7 +133,7 @@ PNAME(mux_spdif_p)  = { "spdif_src", "spdif_frac", "xin12m" };
 PNAME(mux_uart0_p)     = { "uart0_src", "uart0_frac", "xin24m" };
 PNAME(mux_uart1_p)     = { "uart1_src", "uart1_frac", "xin24m" };
 PNAME(mux_uart2_p)     = { "uart2_src", "uart2_frac", "xin24m" };
-PNAME(mux_mac_p)       = { "mac_pll_src", "ext_gmac" };
+PNAME(mux_mac_p)       = { "mac_pll_src", "rmii_clkin" };
 PNAME(mux_dclk_p)      = { "dclk_lcdc", "dclk_cru" };
 
 static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = {
@@ -224,16 +224,16 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(2), 2, GFLAGS),
 
        COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED,
-                       RK2928_CLKSEL_CON(2), 4, 1, DFLAGS,
+                       RK2928_CLKSEL_CON(2), 4, 1, MFLAGS,
                        RK2928_CLKGATE_CON(1), 0, GFLAGS),
        COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED,
-                       RK2928_CLKSEL_CON(2), 5, 1, DFLAGS,
+                       RK2928_CLKSEL_CON(2), 5, 1, MFLAGS,
                        RK2928_CLKGATE_CON(1), 1, GFLAGS),
        COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED,
-                       RK2928_CLKSEL_CON(2), 6, 1, DFLAGS,
+                       RK2928_CLKSEL_CON(2), 6, 1, MFLAGS,
                        RK2928_CLKGATE_CON(2), 4, GFLAGS),
        COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED,
-                       RK2928_CLKSEL_CON(2), 7, 1, DFLAGS,
+                       RK2928_CLKSEL_CON(2), 7, 1, MFLAGS,
                        RK2928_CLKGATE_CON(2), 5, GFLAGS),
 
        MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
@@ -242,11 +242,11 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
                        RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(1), 8, GFLAGS),
        COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0,
-                       RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
-                       RK2928_CLKGATE_CON(1), 8, GFLAGS),
+                       RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
+                       RK2928_CLKGATE_CON(1), 10, GFLAGS),
        COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0,
-                       RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
-                       RK2928_CLKGATE_CON(1), 8, GFLAGS),
+                       RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
+                       RK2928_CLKGATE_CON(1), 12, GFLAGS),
        COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(17), 0,
                        RK2928_CLKGATE_CON(1), 9, GFLAGS,
@@ -279,13 +279,13 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(3), 2, GFLAGS),
 
        COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0,
-                       RK2928_CLKSEL_CON(12), 8, 2, DFLAGS,
+                       RK2928_CLKSEL_CON(12), 8, 2, MFLAGS,
                        RK2928_CLKGATE_CON(2), 11, GFLAGS),
        DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0,
                        RK2928_CLKSEL_CON(11), 0, 7, DFLAGS),
 
        COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
-                       RK2928_CLKSEL_CON(12), 10, 2, DFLAGS,
+                       RK2928_CLKSEL_CON(12), 10, 2, MFLAGS,
                        RK2928_CLKGATE_CON(2), 13, GFLAGS),
        DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
                        RK2928_CLKSEL_CON(11), 8, 7, DFLAGS),
@@ -344,12 +344,12 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(10), 5, GFLAGS),
 
        COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0,
-                       RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS),
+                       RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS),
        MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(21), 3, 1, MFLAGS),
 
        COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0,
-                       RK2928_CLKSEL_CON(21), 9, 5, DFLAGS,
+                       RK2928_CLKSEL_CON(21), 4, 5, DFLAGS,
                        RK2928_CLKGATE_CON(2), 6, GFLAGS),
 
        MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0,
index be0ede52226994a0ae7248c8098285e0ebfd4a86..21f3ea909fabdb7c4f753cd4ed817035c15a31e0 100644 (file)
@@ -780,13 +780,13 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
        GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS),
 
        /* pclk_pd_alive gates */
-       GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS),
-       GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS),
-       GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS),
-       GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS),
-       GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS),
-       GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS),
-       GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS),
+       GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 13, GFLAGS),
+       GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 12, GFLAGS),
+       GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 9, GFLAGS),
+       GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 8, GFLAGS),
+       GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 3, GFLAGS),
+       GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 2, GFLAGS),
+       GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 1, GFLAGS),
 
        /*
         * pclk_vio gates
@@ -796,12 +796,12 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
        GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
 
        /* pclk_pd_pmu gates */
-       GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS),
-       GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
-       GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS),
-       GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
-       GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS),
-       GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+       GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 5, GFLAGS),
+       GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(23), 4, GFLAGS),
+       GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 3, GFLAGS),
+       GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 2, GFLAGS),
+       GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 1, GFLAGS),
+       GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 0, GFLAGS),
 
        /* timer gates */
        GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
index e1fe8f35d45c47c553997845657e09d3b71ca9a1..74e7544f861ba083f63f1d5aa886a7a90b0f295f 100644 (file)
@@ -450,8 +450,10 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
                struct emc_timing *timing = tegra->timings + (i++);
 
                err = load_one_timing_from_dt(tegra, timing, child);
-               if (err)
+               if (err) {
+                       of_node_put(child);
                        return err;
+               }
 
                timing->ram_code = ram_code;
        }
@@ -499,9 +501,9 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
                 * fuses until the apbmisc driver is loaded.
                 */
                err = load_timings_from_dt(tegra, node, node_ram_code);
+               of_node_put(node);
                if (err)
                        return ERR_PTR(err);
-               of_node_put(node);
                break;
        }
 
index 19ce0738ee764bb13e9dfde5ca542fd2cf472e9a..62ea38187b715814ac5d7b5265cbd4cd934a22c3 100644 (file)
@@ -11,6 +11,7 @@ enum clk_id {
        tegra_clk_afi,
        tegra_clk_amx,
        tegra_clk_amx1,
+       tegra_clk_apb2ape,
        tegra_clk_apbdma,
        tegra_clk_apbif,
        tegra_clk_ape,
index a534bfab30b39ee53c81a89c3a5c5b1d2979144e..6ac3f843e7caa3a8abb6513a0eb9fc2c829d3a39 100644 (file)
 #define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\
                                PLLE_SS_CNTL_SSC_BYP)
 #define PLLE_SS_MAX_MASK 0x1ff
-#define PLLE_SS_MAX_VAL 0x25
+#define PLLE_SS_MAX_VAL_TEGRA114 0x25
+#define PLLE_SS_MAX_VAL_TEGRA210 0x21
 #define PLLE_SS_INC_MASK (0xff << 16)
 #define PLLE_SS_INC_VAL (0x1 << 16)
 #define PLLE_SS_INCINTRV_MASK (0x3f << 24)
-#define PLLE_SS_INCINTRV_VAL (0x20 << 24)
+#define PLLE_SS_INCINTRV_VAL_TEGRA114 (0x20 << 24)
+#define PLLE_SS_INCINTRV_VAL_TEGRA210 (0x23 << 24)
 #define PLLE_SS_COEFFICIENTS_MASK \
        (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK)
-#define PLLE_SS_COEFFICIENTS_VAL \
-       (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
+#define PLLE_SS_COEFFICIENTS_VAL_TEGRA114 \
+       (PLLE_SS_MAX_VAL_TEGRA114 | PLLE_SS_INC_VAL |\
+        PLLE_SS_INCINTRV_VAL_TEGRA114)
+#define PLLE_SS_COEFFICIENTS_VAL_TEGRA210 \
+       (PLLE_SS_MAX_VAL_TEGRA210 | PLLE_SS_INC_VAL |\
+        PLLE_SS_INCINTRV_VAL_TEGRA210)
 
 #define PLLE_AUX_PLLP_SEL      BIT(2)
 #define PLLE_AUX_USE_LOCKDET   BIT(3)
@@ -880,7 +886,7 @@ static int clk_plle_training(struct tegra_clk_pll *pll)
 static int clk_plle_enable(struct clk_hw *hw)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
-       unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+       unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
        struct tegra_clk_pll_freq_table sel;
        u32 val;
        int err;
@@ -1378,7 +1384,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        u32 val;
        int ret;
        unsigned long flags = 0;
-       unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+       unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
@@ -1401,7 +1407,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        val |= PLLE_MISC_IDDQ_SW_CTRL;
        val &= ~PLLE_MISC_IDDQ_SW_VALUE;
        val |= PLLE_MISC_PLLE_PTS;
-       val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
+       val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK);
        pll_writel_misc(val, pll);
        udelay(5);
 
@@ -1428,7 +1434,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        val = pll_readl(PLLE_SS_CTRL, pll);
        val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);
        val &= ~PLLE_SS_COEFFICIENTS_MASK;
-       val |= PLLE_SS_COEFFICIENTS_VAL;
+       val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA114;
        pll_writel(val, PLLE_SS_CTRL, pll);
        val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);
        pll_writel(val, PLLE_SS_CTRL, pll);
@@ -2012,9 +2018,9 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw)
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        struct tegra_clk_pll_freq_table sel;
        u32 val;
-       int ret;
+       int ret = 0;
        unsigned long flags = 0;
-       unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+       unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
@@ -2022,22 +2028,20 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw)
        if (pll->lock)
                spin_lock_irqsave(pll->lock, flags);
 
+       val = pll_readl(pll->params->aux_reg, pll);
+       if (val & PLLE_AUX_SEQ_ENABLE)
+               goto out;
+
        val = pll_readl_base(pll);
        val &= ~BIT(30); /* Disable lock override */
        pll_writel_base(val, pll);
 
-       val = pll_readl(pll->params->aux_reg, pll);
-       val |= PLLE_AUX_ENABLE_SWCTL;
-       val &= ~PLLE_AUX_SEQ_ENABLE;
-       pll_writel(val, pll->params->aux_reg, pll);
-       udelay(1);
-
        val = pll_readl_misc(pll);
        val |= PLLE_MISC_LOCK_ENABLE;
        val |= PLLE_MISC_IDDQ_SW_CTRL;
        val &= ~PLLE_MISC_IDDQ_SW_VALUE;
        val |= PLLE_MISC_PLLE_PTS;
-       val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
+       val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK);
        pll_writel_misc(val, pll);
        udelay(5);
 
@@ -2067,7 +2071,7 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw)
        val = pll_readl(PLLE_SS_CTRL, pll);
        val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);
        val &= ~PLLE_SS_COEFFICIENTS_MASK;
-       val |= PLLE_SS_COEFFICIENTS_VAL;
+       val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA210;
        pll_writel(val, PLLE_SS_CTRL, pll);
        val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);
        pll_writel(val, PLLE_SS_CTRL, pll);
@@ -2104,15 +2108,25 @@ static void clk_plle_tegra210_disable(struct clk_hw *hw)
        if (pll->lock)
                spin_lock_irqsave(pll->lock, flags);
 
+       /* If PLLE HW sequencer is enabled, SW should not disable PLLE */
+       val = pll_readl(pll->params->aux_reg, pll);
+       if (val & PLLE_AUX_SEQ_ENABLE)
+               goto out;
+
        val = pll_readl_base(pll);
        val &= ~PLLE_BASE_ENABLE;
        pll_writel_base(val, pll);
 
+       val = pll_readl(pll->params->aux_reg, pll);
+       val |= PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL;
+       pll_writel(val, pll->params->aux_reg, pll);
+
        val = pll_readl_misc(pll);
        val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
        pll_writel_misc(val, pll);
        udelay(1);
 
+out:
        if (pll->lock)
                spin_unlock_irqrestore(pll->lock, flags);
 }
index 6ad381a888a6176801494c60bcc4f057f23ebe82..ea2b9cbf9e70b0c10204d5d34dc96ab929d36427 100644 (file)
@@ -773,7 +773,7 @@ static struct tegra_periph_init_data periph_clks[] = {
        XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
        XUSB("xusb_dev_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src_8),
        MUX8("dbgapb", mux_pllp_clkm_2, CLK_SOURCE_DBGAPB, 185, TEGRA_PERIPH_NO_RESET, tegra_clk_dbgapb),
-       MUX8("msenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc),
+       MUX8("nvenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc),
        MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec),
        MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg),
        MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape),
@@ -782,7 +782,7 @@ static struct tegra_periph_init_data periph_clks[] = {
        NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock),
        MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy),
        MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi),
-       MUX("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, TEGRA_PERIPH_ON_APB, tegra_clk_vi_i2c),
+       I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c),
        MUX("mipibif", mux_pllp_clkm, CLK_SOURCE_MIPIBIF, 173, TEGRA_PERIPH_ON_APB, tegra_clk_mipibif),
        MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape),
        MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb),
@@ -829,6 +829,7 @@ static struct tegra_periph_init_data gate_clks[] = {
        GATE("xusb_gate", "osc", 143, 0, tegra_clk_xusb_gate, 0),
        GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0),
        GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0),
+       GATE("apb2ape", "clk_m", 107, 0, tegra_clk_apb2ape, 0),
 };
 
 static struct tegra_periph_init_data div_clks[] = {
index 4559a20e3af6e424e52c7b08930cd7664965fea2..474de0f0c26d80b0f9b20ff845575ce049165038 100644 (file)
@@ -67,7 +67,7 @@ static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
                                         "pll_p", "pll_p_out4", "unused",
                                         "unused", "pll_x", "pll_x_out0" };
 
-const struct tegra_super_gen_info tegra_super_gen_info_gen4 = {
+static const struct tegra_super_gen_info tegra_super_gen_info_gen4 = {
        .gen = gen4,
        .sclk_parents = sclk_parents,
        .cclk_g_parents = cclk_g_parents,
@@ -93,7 +93,7 @@ static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unu
                                        "unused", "unused", "unused", "unused",
                                        "dfllCPU_out" };
 
-const struct tegra_super_gen_info tegra_super_gen_info_gen5 = {
+static const struct tegra_super_gen_info tegra_super_gen_info_gen5 = {
        .gen = gen5,
        .sclk_parents = sclk_parents_gen5,
        .cclk_g_parents = cclk_g_parents_gen5,
@@ -171,7 +171,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
        *dt_clk = clk;
 }
 
-void __init tegra_super_clk_init(void __iomem *clk_base,
+static void __init tegra_super_clk_init(void __iomem *clk_base,
                                void __iomem *pmc_base,
                                struct tegra_clk *tegra_clks,
                                struct tegra_clk_pll_params *params,
index 58514c44ea830c476b8b23606e962ecf8ef8ef7a..637041fd53ad11b95cd305952cb0a80eaf0d3b61 100644 (file)
@@ -59,8 +59,8 @@
 #define PLLC3_MISC3 0x50c
 
 #define PLLM_BASE 0x90
-#define PLLM_MISC0 0x9c
 #define PLLM_MISC1 0x98
+#define PLLM_MISC2 0x9c
 #define PLLP_BASE 0xa0
 #define PLLP_MISC0 0xac
 #define PLLP_MISC1 0x680
@@ -99,7 +99,7 @@
 #define PLLC4_MISC0 0x5a8
 #define PLLC4_OUT 0x5e4
 #define PLLMB_BASE 0x5e8
-#define PLLMB_MISC0 0x5ec
+#define PLLMB_MISC1 0x5ec
 #define PLLA1_BASE 0x6a4
 #define PLLA1_MISC0 0x6a8
 #define PLLA1_MISC1 0x6ac
@@ -243,7 +243,8 @@ static unsigned long tegra210_input_freq[] = {
 };
 
 static const char *mux_pllmcp_clkm[] = {
-       "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
+       "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb", "pll_mb",
+       "pll_p",
 };
 #define mux_pllmcp_clkm_idx NULL
 
@@ -367,12 +368,12 @@ static const char *mux_pllmcp_clkm[] = {
 /* PLLMB */
 #define PLLMB_BASE_LOCK                        (1 << 27)
 
-#define PLLMB_MISC0_LOCK_OVERRIDE      (1 << 18)
-#define PLLMB_MISC0_IDDQ               (1 << 17)
-#define PLLMB_MISC0_LOCK_ENABLE                (1 << 16)
+#define PLLMB_MISC1_LOCK_OVERRIDE      (1 << 18)
+#define PLLMB_MISC1_IDDQ               (1 << 17)
+#define PLLMB_MISC1_LOCK_ENABLE                (1 << 16)
 
-#define PLLMB_MISC0_DEFAULT_VALUE      0x00030000
-#define PLLMB_MISC0_WRITE_MASK         0x0007ffff
+#define PLLMB_MISC1_DEFAULT_VALUE      0x00030000
+#define PLLMB_MISC1_WRITE_MASK         0x0007ffff
 
 /* PLLP */
 #define PLLP_BASE_OVERRIDE             (1 << 28)
@@ -457,7 +458,8 @@ static void pllcx_check_defaults(struct tegra_clk_pll_params *params)
                        PLLCX_MISC3_WRITE_MASK);
 }
 
-void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx)
+static void tegra210_pllcx_set_defaults(const char *name,
+                                       struct tegra_clk_pll *pllcx)
 {
        pllcx->params->defaults_set = true;
 
@@ -482,22 +484,22 @@ void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx)
        udelay(1);
 }
 
-void _pllc_set_defaults(struct tegra_clk_pll *pllcx)
+static void _pllc_set_defaults(struct tegra_clk_pll *pllcx)
 {
        tegra210_pllcx_set_defaults("PLL_C", pllcx);
 }
 
-void _pllc2_set_defaults(struct tegra_clk_pll *pllcx)
+static void _pllc2_set_defaults(struct tegra_clk_pll *pllcx)
 {
        tegra210_pllcx_set_defaults("PLL_C2", pllcx);
 }
 
-void _pllc3_set_defaults(struct tegra_clk_pll *pllcx)
+static void _pllc3_set_defaults(struct tegra_clk_pll *pllcx)
 {
        tegra210_pllcx_set_defaults("PLL_C3", pllcx);
 }
 
-void _plla1_set_defaults(struct tegra_clk_pll *pllcx)
+static void _plla1_set_defaults(struct tegra_clk_pll *pllcx)
 {
        tegra210_pllcx_set_defaults("PLL_A1", pllcx);
 }
@@ -507,7 +509,7 @@ void _plla1_set_defaults(struct tegra_clk_pll *pllcx)
  * PLL with dynamic ramp and fractional SDM. Dynamic ramp is not used.
  * Fractional SDM is allowed to provide exact audio rates.
  */
-void tegra210_plla_set_defaults(struct tegra_clk_pll *plla)
+static void tegra210_plla_set_defaults(struct tegra_clk_pll *plla)
 {
        u32 mask;
        u32 val = readl_relaxed(clk_base + plla->params->base_reg);
@@ -559,7 +561,7 @@ void tegra210_plla_set_defaults(struct tegra_clk_pll *plla)
  * PLLD
  * PLL with fractional SDM.
  */
-void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
+static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
 {
        u32 val;
        u32 mask = 0xffff;
@@ -698,7 +700,7 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss,
        udelay(1);
 }
 
-void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2)
+static void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2)
 {
        plldss_defaults("PLL_D2", plld2, PLLD2_MISC0_DEFAULT_VALUE,
                        PLLD2_MISC1_CFG_DEFAULT_VALUE,
@@ -706,7 +708,7 @@ void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2)
                        PLLD2_MISC3_CTRL2_DEFAULT_VALUE);
 }
 
-void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp)
+static void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp)
 {
        plldss_defaults("PLL_DP", plldp, PLLDP_MISC0_DEFAULT_VALUE,
                        PLLDP_MISC1_CFG_DEFAULT_VALUE,
@@ -719,7 +721,7 @@ void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp)
  * Base and misc0 layout is the same as PLLD2/PLLDP, but no SDM/SSC support.
  * VCO is exposed to the clock tree via fixed 1/3 and 1/5 dividers.
  */
-void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4)
+static void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4)
 {
        plldss_defaults("PLL_C4", pllc4, PLLC4_MISC0_DEFAULT_VALUE, 0, 0, 0);
 }
@@ -728,7 +730,7 @@ void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4)
  * PLLRE
  * VCO is exposed to the clock tree directly along with post-divider output
  */
-void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre)
+static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre)
 {
        u32 mask;
        u32 val = readl_relaxed(clk_base + pllre->params->base_reg);
@@ -780,13 +782,13 @@ static void pllx_get_dyn_steps(struct clk_hw *hw, u32 *step_a, u32 *step_b)
 {
        unsigned long input_rate;
 
-       if (!IS_ERR_OR_NULL(hw->clk)) {
+       /* cf rate */
+       if (!IS_ERR_OR_NULL(hw->clk))
                input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
-               /* cf rate */
-               input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate);
-       } else {
+       else
                input_rate = 38400000;
-       }
+
+       input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate);
 
        switch (input_rate) {
        case 12000000:
@@ -841,7 +843,7 @@ static void pllx_check_defaults(struct tegra_clk_pll *pll)
                        PLLX_MISC5_WRITE_MASK);
 }
 
-void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
+static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
 {
        u32 val;
        u32 step_a, step_b;
@@ -901,7 +903,7 @@ void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
 }
 
 /* PLLMB */
-void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
+static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
 {
        u32 mask, val = readl_relaxed(clk_base + pllmb->params->base_reg);
 
@@ -914,15 +916,15 @@ void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
                 * PLL is ON: check if defaults already set, then set those
                 * that can be updated in flight.
                 */
-               val = PLLMB_MISC0_DEFAULT_VALUE & (~PLLMB_MISC0_IDDQ);
-               mask = PLLMB_MISC0_LOCK_ENABLE | PLLMB_MISC0_LOCK_OVERRIDE;
+               val = PLLMB_MISC1_DEFAULT_VALUE & (~PLLMB_MISC1_IDDQ);
+               mask = PLLMB_MISC1_LOCK_ENABLE | PLLMB_MISC1_LOCK_OVERRIDE;
                _pll_misc_chk_default(clk_base, pllmb->params, 0, val,
-                               ~mask & PLLMB_MISC0_WRITE_MASK);
+                               ~mask & PLLMB_MISC1_WRITE_MASK);
 
                /* Enable lock detect */
                val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]);
                val &= ~mask;
-               val |= PLLMB_MISC0_DEFAULT_VALUE & mask;
+               val |= PLLMB_MISC1_DEFAULT_VALUE & mask;
                writel_relaxed(val, clk_base + pllmb->params->ext_misc_reg[0]);
                udelay(1);
 
@@ -930,7 +932,7 @@ void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
        }
 
        /* set IDDQ, enable lock detect */
-       writel_relaxed(PLLMB_MISC0_DEFAULT_VALUE,
+       writel_relaxed(PLLMB_MISC1_DEFAULT_VALUE,
                        clk_base + pllmb->params->ext_misc_reg[0]);
        udelay(1);
 }
@@ -960,7 +962,7 @@ static void pllp_check_defaults(struct tegra_clk_pll *pll, bool enabled)
                        ~mask & PLLP_MISC1_WRITE_MASK);
 }
 
-void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
+static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
 {
        u32 mask;
        u32 val = readl_relaxed(clk_base + pllp->params->base_reg);
@@ -1022,7 +1024,7 @@ static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control)
                        ~mask & PLLU_MISC1_WRITE_MASK);
 }
 
-void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
+static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
 {
        u32 val = readl_relaxed(clk_base + pllu->params->base_reg);
 
@@ -1212,8 +1214,9 @@ static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg)
        cfg->m *= PLL_SDM_COEFF;
 }
 
-unsigned long tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params,
-                                         unsigned long parent_rate)
+static unsigned long
+tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params,
+                           unsigned long parent_rate)
 {
        unsigned long vco_min = params->vco_min;
 
@@ -1386,7 +1389,7 @@ static struct tegra_clk_pll_params pll_c_params = {
        .mdiv_default = 3,
        .div_nmp = &pllc_nmp,
        .freq_table = pll_cx_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .set_defaults = _pllc_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1425,7 +1428,7 @@ static struct tegra_clk_pll_params pll_c2_params = {
        .ext_misc_reg[2] = PLLC2_MISC2,
        .ext_misc_reg[3] = PLLC2_MISC3,
        .freq_table = pll_cx_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .set_defaults = _pllc2_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1455,7 +1458,7 @@ static struct tegra_clk_pll_params pll_c3_params = {
        .ext_misc_reg[2] = PLLC3_MISC2,
        .ext_misc_reg[3] = PLLC3_MISC3,
        .freq_table = pll_cx_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .set_defaults = _pllc3_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1505,7 +1508,6 @@ static struct tegra_clk_pll_params pll_c4_vco_params = {
        .base_reg = PLLC4_BASE,
        .misc_reg = PLLC4_MISC0,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .max_p = PLL_QLIN_PDIV_MAX,
        .ext_misc_reg[0] = PLLC4_MISC0,
@@ -1517,8 +1519,7 @@ static struct tegra_clk_pll_params pll_c4_vco_params = {
        .div_nmp = &pllss_nmp,
        .freq_table = pll_c4_vco_freq_table,
        .set_defaults = tegra210_pllc4_set_defaults,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
-                TEGRA_PLL_VCO_OUT,
+       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
 
@@ -1559,15 +1560,15 @@ static struct tegra_clk_pll_params pll_m_params = {
        .vco_min = 800000000,
        .vco_max = 1866000000,
        .base_reg = PLLM_BASE,
-       .misc_reg = PLLM_MISC1,
+       .misc_reg = PLLM_MISC2,
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLM_MISC_LOCK_ENABLE,
        .lock_delay = 300,
-       .iddq_reg = PLLM_MISC0,
+       .iddq_reg = PLLM_MISC2,
        .iddq_bit_idx = PLLM_IDDQ_BIT,
        .max_p = PLL_QLIN_PDIV_MAX,
-       .ext_misc_reg[0] = PLLM_MISC0,
-       .ext_misc_reg[0] = PLLM_MISC1,
+       .ext_misc_reg[0] = PLLM_MISC2,
+       .ext_misc_reg[1] = PLLM_MISC1,
        .round_p_to_pdiv = pll_qlin_p_to_pdiv,
        .pdiv_tohw = pll_qlin_pdiv_to_hw,
        .div_nmp = &pllm_nmp,
@@ -1586,19 +1587,18 @@ static struct tegra_clk_pll_params pll_mb_params = {
        .vco_min = 800000000,
        .vco_max = 1866000000,
        .base_reg = PLLMB_BASE,
-       .misc_reg = PLLMB_MISC0,
+       .misc_reg = PLLMB_MISC1,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLMB_MISC_LOCK_ENABLE,
        .lock_delay = 300,
-       .iddq_reg = PLLMB_MISC0,
+       .iddq_reg = PLLMB_MISC1,
        .iddq_bit_idx = PLLMB_IDDQ_BIT,
        .max_p = PLL_QLIN_PDIV_MAX,
-       .ext_misc_reg[0] = PLLMB_MISC0,
+       .ext_misc_reg[0] = PLLMB_MISC1,
        .round_p_to_pdiv = pll_qlin_p_to_pdiv,
        .pdiv_tohw = pll_qlin_pdiv_to_hw,
        .div_nmp = &pllm_nmp,
        .freq_table = pll_m_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .set_defaults = tegra210_pllmb_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1671,7 +1671,6 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
        .base_reg = PLLRE_BASE,
        .misc_reg = PLLRE_MISC0,
        .lock_mask = PLLRE_MISC_LOCK,
-       .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .max_p = PLL_QLIN_PDIV_MAX,
        .ext_misc_reg[0] = PLLRE_MISC0,
@@ -1681,8 +1680,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
        .pdiv_tohw = pll_qlin_pdiv_to_hw,
        .div_nmp = &pllre_nmp,
        .freq_table = pll_re_vco_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC |
-                TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT,
+       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC | TEGRA_PLL_VCO_OUT,
        .set_defaults = tegra210_pllre_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1712,7 +1710,6 @@ static struct tegra_clk_pll_params pll_p_params = {
        .base_reg = PLLP_BASE,
        .misc_reg = PLLP_MISC0,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLP_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .iddq_reg = PLLP_MISC0,
        .iddq_bit_idx = PLLXP_IDDQ_BIT,
@@ -1721,8 +1718,7 @@ static struct tegra_clk_pll_params pll_p_params = {
        .div_nmp = &pllp_nmp,
        .freq_table = pll_p_freq_table,
        .fixed_rate = 408000000,
-       .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK |
-                TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_VCO_OUT,
+       .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT,
        .set_defaults = tegra210_pllp_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1750,7 +1746,7 @@ static struct tegra_clk_pll_params pll_a1_params = {
        .ext_misc_reg[2] = PLLA1_MISC2,
        .ext_misc_reg[3] = PLLA1_MISC3,
        .freq_table = pll_cx_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .set_defaults = _plla1_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -1787,7 +1783,6 @@ static struct tegra_clk_pll_params pll_a_params = {
        .base_reg = PLLA_BASE,
        .misc_reg = PLLA_MISC0,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLA_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .round_p_to_pdiv = pll_qlin_p_to_pdiv,
        .pdiv_tohw = pll_qlin_pdiv_to_hw,
@@ -1802,8 +1797,7 @@ static struct tegra_clk_pll_params pll_a_params = {
        .ext_misc_reg[1] = PLLA_MISC1,
        .ext_misc_reg[2] = PLLA_MISC2,
        .freq_table = pll_a_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW |
-                TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW,
        .set_defaults = tegra210_plla_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
        .set_gain = tegra210_clk_pll_set_gain,
@@ -1836,7 +1830,6 @@ static struct tegra_clk_pll_params pll_d_params = {
        .base_reg = PLLD_BASE,
        .misc_reg = PLLD_MISC0,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLD_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
        .iddq_reg = PLLD_MISC0,
        .iddq_bit_idx = PLLD_IDDQ_BIT,
@@ -1850,7 +1843,7 @@ static struct tegra_clk_pll_params pll_d_params = {
        .ext_misc_reg[0] = PLLD_MISC0,
        .ext_misc_reg[1] = PLLD_MISC1,
        .freq_table = pll_d_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .mdiv_default = 1,
        .set_defaults = tegra210_plld_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
@@ -1876,7 +1869,6 @@ static struct tegra_clk_pll_params pll_d2_params = {
        .base_reg = PLLD2_BASE,
        .misc_reg = PLLD2_MISC0,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .iddq_reg = PLLD2_BASE,
        .iddq_bit_idx = PLLSS_IDDQ_BIT,
@@ -1897,7 +1889,7 @@ static struct tegra_clk_pll_params pll_d2_params = {
        .mdiv_default = 1,
        .freq_table = tegra210_pll_d2_freq_table,
        .set_defaults = tegra210_plld2_set_defaults,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
        .set_gain = tegra210_clk_pll_set_gain,
        .adjust_vco = tegra210_clk_adjust_vco_min,
@@ -1920,7 +1912,6 @@ static struct tegra_clk_pll_params pll_dp_params = {
        .base_reg = PLLDP_BASE,
        .misc_reg = PLLDP_MISC,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLSS_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .iddq_reg = PLLDP_BASE,
        .iddq_bit_idx = PLLSS_IDDQ_BIT,
@@ -1941,7 +1932,7 @@ static struct tegra_clk_pll_params pll_dp_params = {
        .mdiv_default = 1,
        .freq_table = pll_dp_freq_table,
        .set_defaults = tegra210_plldp_set_defaults,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
        .set_gain = tegra210_clk_pll_set_gain,
        .adjust_vco = tegra210_clk_adjust_vco_min,
@@ -1973,7 +1964,6 @@ static struct tegra_clk_pll_params pll_u_vco_params = {
        .base_reg = PLLU_BASE,
        .misc_reg = PLLU_MISC0,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLLU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
        .iddq_reg = PLLU_MISC0,
        .iddq_bit_idx = PLLU_IDDQ_BIT,
@@ -1983,8 +1973,7 @@ static struct tegra_clk_pll_params pll_u_vco_params = {
        .pdiv_tohw = pll_qlin_pdiv_to_hw,
        .div_nmp = &pllu_nmp,
        .freq_table = pll_u_freq_table,
-       .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
-                TEGRA_PLL_VCO_OUT,
+       .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT,
        .set_defaults = tegra210_pllu_set_defaults,
        .calc_rate = tegra210_pll_fixed_mdiv_cfg,
 };
@@ -2218,6 +2207,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
        [tegra_clk_pll_c4_out1] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT1, .present = true },
        [tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true },
        [tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true },
+       [tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true },
 };
 
 static struct tegra_devclk devclks[] __initdata = {
@@ -2519,7 +2509,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
 
        /* PLLU_VCO */
        val = readl(clk_base + pll_u_vco_params.base_reg);
-       val &= ~BIT(24); /* disable PLLU_OVERRIDE */
+       val &= ~PLLU_BASE_OVERRIDE; /* disable PLLU_OVERRIDE */
        writel(val, clk_base + pll_u_vco_params.base_reg);
 
        clk = tegra_clk_register_pllre("pll_u_vco", "pll_ref", clk_base, pmc,
@@ -2738,8 +2728,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 },
        { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 },
        { TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 },
-       { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
-       { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
        { TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 },
        { TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 },
index 1c300388782ba19d1377bdbbbf9ab05a8939791d..cc739291a3ce47466e87023c2bdfd56951e7bf2f 100644 (file)
@@ -460,7 +460,8 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
 
        parent = clk_hw_get_parent(hw);
 
-       if (clk_hw_get_rate(hw) == clk_get_rate(dd->clk_bypass)) {
+       if (clk_hw_get_rate(hw) ==
+           clk_hw_get_rate(__clk_get_hw(dd->clk_bypass))) {
                WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
index e62f8cb2c9b53ec4f22811549878ad844e24b612..3bca438ecd19dabbc3df761dedb81c96a463b449 100644 (file)
@@ -78,6 +78,9 @@ static int vco_set(struct clk_icst *icst, struct icst_vco vco)
        ret = regmap_read(icst->map, icst->vcoreg_off, &val);
        if (ret)
                return ret;
+
+       /* Mask the 18 bits used by the VCO */
+       val &= ~0x7ffff;
        val |= vco.v | (vco.r << 9) | (vco.s << 16);
 
        /* This magic unlocks the VCO so it can be controlled */
index 659879a56dbac59c7f18e0d2f51393bf9a3e645f..f93511031177f7801bf4e6bc5c29a0da22b47f5c 100644 (file)
@@ -296,6 +296,7 @@ endif
 config QORIQ_CPUFREQ
        tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
        depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
+       depends on !CPU_THERMAL || THERMAL
        select CLK_QORIQ
        help
          This adds the CPUFreq driver support for Freescale QorIQ SoCs
index 0031069b64c95aa93f2d1d0696ee8a9c63cc59ef..14b1f9393b057e106d7b068883ce486ea70239ec 100644 (file)
@@ -84,10 +84,10 @@ config ARM_KIRKWOOD_CPUFREQ
          SoCs.
 
 config ARM_MT8173_CPUFREQ
-       bool "Mediatek MT8173 CPUFreq support"
+       tristate "Mediatek MT8173 CPUFreq support"
        depends on ARCH_MEDIATEK && REGULATOR
        depends on ARM64 || (ARM_CPU_TOPOLOGY && COMPILE_TEST)
-       depends on !CPU_THERMAL || THERMAL=y
+       depends on !CPU_THERMAL || THERMAL
        select PM_OPP
        help
          This adds the CPUFreq driver support for Mediatek MT8173 SoC.
index 1efba340456dfc5df4b2005517fe0c1b048e198a..2058e6d292ce95fbcd6fb3099b08adf36f857cd1 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/cpu_cooling.h>
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_opp.h>
index 20de861aa0ea6c275edb746e14fcb372344fcd48..8bf9914d4d150b439e087688b51c884fdd1d022c 100644 (file)
@@ -782,7 +782,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err)
        dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
                        SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
 
-       clk_disable_unprepare(dd->iclk);
+       clk_disable(dd->iclk);
 
        if (req->base.complete)
                req->base.complete(&req->base, err);
@@ -795,7 +795,7 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
 {
        int err;
 
-       err = clk_prepare_enable(dd->iclk);
+       err = clk_enable(dd->iclk);
        if (err)
                return err;
 
@@ -822,7 +822,7 @@ static void atmel_sha_hw_version_init(struct atmel_sha_dev *dd)
        dev_info(dd->dev,
                        "version: 0x%x\n", dd->hw_version);
 
-       clk_disable_unprepare(dd->iclk);
+       clk_disable(dd->iclk);
 }
 
 static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
@@ -1410,6 +1410,10 @@ static int atmel_sha_probe(struct platform_device *pdev)
                goto res_err;
        }
 
+       err = clk_prepare(sha_dd->iclk);
+       if (err)
+               goto res_err;
+
        atmel_sha_hw_version_init(sha_dd);
 
        atmel_sha_get_cap(sha_dd);
@@ -1421,12 +1425,12 @@ static int atmel_sha_probe(struct platform_device *pdev)
                        if (IS_ERR(pdata)) {
                                dev_err(&pdev->dev, "platform data not available\n");
                                err = PTR_ERR(pdata);
-                               goto res_err;
+                               goto iclk_unprepare;
                        }
                }
                if (!pdata->dma_slave) {
                        err = -ENXIO;
-                       goto res_err;
+                       goto iclk_unprepare;
                }
                err = atmel_sha_dma_init(sha_dd, pdata);
                if (err)
@@ -1457,6 +1461,8 @@ err_algs:
        if (sha_dd->caps.has_dma)
                atmel_sha_dma_cleanup(sha_dd);
 err_sha_dma:
+iclk_unprepare:
+       clk_unprepare(sha_dd->iclk);
 res_err:
        tasklet_kill(&sha_dd->done_task);
 sha_dd_err:
@@ -1483,12 +1489,7 @@ static int atmel_sha_remove(struct platform_device *pdev)
        if (sha_dd->caps.has_dma)
                atmel_sha_dma_cleanup(sha_dd);
 
-       iounmap(sha_dd->io_base);
-
-       clk_put(sha_dd->iclk);
-
-       if (sha_dd->irq >= 0)
-               free_irq(sha_dd->irq, sha_dd);
+       clk_unprepare(sha_dd->iclk);
 
        return 0;
 }
index 0643e3366e3309de88a03e687a2d5353f5715a22..c0656e7f37b5993672002a8a192dc1c9dcf0c4bd 100644 (file)
@@ -306,7 +306,7 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa)
                return -ENOMEM;
 
        dma->padding_pool = dmam_pool_create("cesa_padding", dev, 72, 1, 0);
-       if (!dma->cache_pool)
+       if (!dma->padding_pool)
                return -ENOMEM;
 
        cesa->dma = dma;
index 848b93ee930fd8ec204a332755c57b18457bfede..fe9dce0245bf0c7d32b2c8eb3590e7f73651ae6d 100644 (file)
@@ -500,6 +500,8 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
        clk_set_min_rate(tegra->emc_clock, rate);
        clk_set_rate(tegra->emc_clock, 0);
 
+       *freq = rate;
+
        return 0;
 }
 
index e893318560db9f79300579ff01e73b07b5baae38..5ad0ec1f0e29f750eee5c70889df5427d7413556 100644 (file)
@@ -156,7 +156,6 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 
        /* Enable interrupts */
        channel_set_bit(dw, MASK.XFER, dwc->mask);
-       channel_set_bit(dw, MASK.BLOCK, dwc->mask);
        channel_set_bit(dw, MASK.ERROR, dwc->mask);
 
        dwc->initialized = true;
@@ -588,6 +587,9 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
 
                spin_unlock_irqrestore(&dwc->lock, flags);
        }
+
+       /* Re-enable interrupts */
+       channel_set_bit(dw, MASK.BLOCK, dwc->mask);
 }
 
 /* ------------------------------------------------------------------------- */
@@ -618,11 +620,8 @@ static void dw_dma_tasklet(unsigned long data)
                        dwc_scan_descriptors(dw, dwc);
        }
 
-       /*
-        * Re-enable interrupts.
-        */
+       /* Re-enable interrupts */
        channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
-       channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
        channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
 }
 
@@ -1261,6 +1260,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 int dw_dma_cyclic_start(struct dma_chan *chan)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
+       struct dw_dma           *dw = to_dw_dma(chan->device);
        unsigned long           flags;
 
        if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) {
@@ -1269,7 +1269,12 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
        }
 
        spin_lock_irqsave(&dwc->lock, flags);
+
+       /* Enable interrupts to perform cyclic transfer */
+       channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+
        dwc_dostart(dwc, dwc->cdesc->desc[0]);
+
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
index 4c30fdd092b3b1e5b7e6050b7e7d1afee6c11e57..358f9689a3f5ace77d3dfd601f1873b880704060 100644 (file)
@@ -108,6 +108,10 @@ static const struct pci_device_id dw_pci_id_table[] = {
 
        /* Haswell */
        { PCI_VDEVICE(INTEL, 0x9c60) },
+
+       /* Broadwell */
+       { PCI_VDEVICE(INTEL, 0x9ce0) },
+
        { }
 };
 MODULE_DEVICE_TABLE(pci, dw_pci_id_table);
index d92d655494068992f5a689ff83604158115bee4d..e3d7fcb69b4c2e4ffc4221c8ea8ec4e360648fd7 100644 (file)
 #define GET_NUM_REGN(x)                ((x & 0x300000) >> 20) /* bits 20-21 */
 #define CHMAP_EXIST            BIT(24)
 
+/* CCSTAT register */
+#define EDMA_CCSTAT_ACTV       BIT(4)
+
 /*
  * Max of 20 segments per channel to conserve PaRAM slots
  * Also note that MAX_NR_SG should be atleast the no.of periods
@@ -1680,9 +1683,20 @@ static void edma_issue_pending(struct dma_chan *chan)
        spin_unlock_irqrestore(&echan->vchan.lock, flags);
 }
 
+/*
+ * This limit exists to avoid a possible infinite loop when waiting for proof
+ * that a particular transfer is completed. This limit can be hit if there
+ * are large bursts to/from slow devices or the CPU is never able to catch
+ * the DMA hardware idle. On an AM335x transfering 48 bytes from the UART
+ * RX-FIFO, as many as 55 loops have been seen.
+ */
+#define EDMA_MAX_TR_WAIT_LOOPS 1000
+
 static u32 edma_residue(struct edma_desc *edesc)
 {
        bool dst = edesc->direction == DMA_DEV_TO_MEM;
+       int loop_count = EDMA_MAX_TR_WAIT_LOOPS;
+       struct edma_chan *echan = edesc->echan;
        struct edma_pset *pset = edesc->pset;
        dma_addr_t done, pos;
        int i;
@@ -1691,7 +1705,32 @@ static u32 edma_residue(struct edma_desc *edesc)
         * We always read the dst/src position from the first RamPar
         * pset. That's the one which is active now.
         */
-       pos = edma_get_position(edesc->echan->ecc, edesc->echan->slot[0], dst);
+       pos = edma_get_position(echan->ecc, echan->slot[0], dst);
+
+       /*
+        * "pos" may represent a transfer request that is still being
+        * processed by the EDMACC or EDMATC. We will busy wait until
+        * any one of the situations occurs:
+        *   1. the DMA hardware is idle
+        *   2. a new transfer request is setup
+        *   3. we hit the loop limit
+        */
+       while (edma_read(echan->ecc, EDMA_CCSTAT) & EDMA_CCSTAT_ACTV) {
+               /* check if a new transfer request is setup */
+               if (edma_get_position(echan->ecc,
+                                     echan->slot[0], dst) != pos) {
+                       break;
+               }
+
+               if (!--loop_count) {
+                       dev_dbg_ratelimited(echan->vchan.chan.device->dev,
+                               "%s: timeout waiting for PaRAM update\n",
+                               __func__);
+                       break;
+               }
+
+               cpu_relax();
+       }
 
        /*
         * Cyclic is simple. Just subtract pset[0].addr from pos.
index 1d5df2ef148b16d3c379a11e14a7da5283f9d5b8..21539d5c54c3d5c2d2dc3244650691bf414cf879 100644 (file)
@@ -861,32 +861,42 @@ void ioat_timer_event(unsigned long data)
                        return;
        }
 
+       spin_lock_bh(&ioat_chan->cleanup_lock);
+
+       /* handle the no-actives case */
+       if (!ioat_ring_active(ioat_chan)) {
+               spin_lock_bh(&ioat_chan->prep_lock);
+               check_active(ioat_chan);
+               spin_unlock_bh(&ioat_chan->prep_lock);
+               spin_unlock_bh(&ioat_chan->cleanup_lock);
+               return;
+       }
+
        /* if we haven't made progress and we have already
         * acknowledged a pending completion once, then be more
         * forceful with a restart
         */
-       spin_lock_bh(&ioat_chan->cleanup_lock);
        if (ioat_cleanup_preamble(ioat_chan, &phys_complete))
                __cleanup(ioat_chan, phys_complete);
        else if (test_bit(IOAT_COMPLETION_ACK, &ioat_chan->state)) {
+               u32 chanerr;
+
+               chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+               dev_warn(to_dev(ioat_chan), "Restarting channel...\n");
+               dev_warn(to_dev(ioat_chan), "CHANSTS: %#Lx CHANERR: %#x\n",
+                        status, chanerr);
+               dev_warn(to_dev(ioat_chan), "Active descriptors: %d\n",
+                        ioat_ring_active(ioat_chan));
+
                spin_lock_bh(&ioat_chan->prep_lock);
                ioat_restart_channel(ioat_chan);
                spin_unlock_bh(&ioat_chan->prep_lock);
                spin_unlock_bh(&ioat_chan->cleanup_lock);
                return;
-       } else {
+       } else
                set_bit(IOAT_COMPLETION_ACK, &ioat_chan->state);
-               mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT);
-       }
-
 
-       if (ioat_ring_active(ioat_chan))
-               mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT);
-       else {
-               spin_lock_bh(&ioat_chan->prep_lock);
-               check_active(ioat_chan);
-               spin_unlock_bh(&ioat_chan->prep_lock);
-       }
+       mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT);
        spin_unlock_bh(&ioat_chan->cleanup_lock);
 }
 
index f2a0310ae7718c3c49a6ef5a516a50851e1b0359..debca824bed676f0ecacc9e71476ecc33a477298 100644 (file)
@@ -583,6 +583,8 @@ static void set_updater_desc(struct pxad_desc_sw *sw_desc,
                (PXA_DCMD_LENGTH & sizeof(u32));
        if (flags & DMA_PREP_INTERRUPT)
                updater->dcmd |= PXA_DCMD_ENDIRQEN;
+       if (sw_desc->cyclic)
+               sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first;
 }
 
 static bool is_desc_completed(struct virt_dma_desc *vd)
@@ -673,6 +675,10 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id)
                dev_dbg(&chan->vc.chan.dev->device,
                        "%s(): checking txd %p[%x]: completed=%d\n",
                        __func__, vd, vd->tx.cookie, is_desc_completed(vd));
+               if (to_pxad_sw_desc(vd)->cyclic) {
+                       vchan_cyclic_callback(vd);
+                       break;
+               }
                if (is_desc_completed(vd)) {
                        list_del(&vd->node);
                        vchan_cookie_complete(vd);
@@ -1080,7 +1086,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dchan,
                return NULL;
 
        pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr);
-       dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH | period_len);
+       dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len);
        dev_dbg(&chan->vc.chan.dev->device,
                "%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n",
                __func__, (unsigned long)buf_addr, len, period_len, dir, flags);
index 756eca8c4cf8f291025a3ad44f7cbb9981aeb5fd..10e6774ab2a2248d0a04d935b773c15a38519f46 100644 (file)
@@ -221,7 +221,7 @@ sanity_check(struct efi_variable *var, efi_char16_t *name, efi_guid_t vendor,
        }
 
        if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
-           efivar_validate(name, data, size) == false) {
+           efivar_validate(vendor, name, data, size) == false) {
                printk(KERN_ERR "efivars: Malformed variable content\n");
                return -EINVAL;
        }
@@ -447,7 +447,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
        }
 
        if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
-           efivar_validate(name, data, size) == false) {
+           efivar_validate(new_var->VendorGuid, name, data,
+                           size) == false) {
                printk(KERN_ERR "efivars: Malformed variable content\n");
                return -EINVAL;
        }
@@ -540,38 +541,30 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
 static int
 efivar_create_sysfs_entry(struct efivar_entry *new_var)
 {
-       int i, short_name_size;
+       int short_name_size;
        char *short_name;
-       unsigned long variable_name_size;
-       efi_char16_t *variable_name;
+       unsigned long utf8_name_size;
+       efi_char16_t *variable_name = new_var->var.VariableName;
        int ret;
 
-       variable_name = new_var->var.VariableName;
-       variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);
-
        /*
-        * Length of the variable bytes in ASCII, plus the '-' separator,
+        * Length of the variable bytes in UTF8, plus the '-' separator,
         * plus the GUID, plus trailing NUL
         */
-       short_name_size = variable_name_size / sizeof(efi_char16_t)
-                               + 1 + EFI_VARIABLE_GUID_LEN + 1;
-
-       short_name = kzalloc(short_name_size, GFP_KERNEL);
+       utf8_name_size = ucs2_utf8size(variable_name);
+       short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
 
+       short_name = kmalloc(short_name_size, GFP_KERNEL);
        if (!short_name)
                return -ENOMEM;
 
-       /* Convert Unicode to normal chars (assume top bits are 0),
-          ala UTF-8 */
-       for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
-               short_name[i] = variable_name[i] & 0xFF;
-       }
+       ucs2_as_utf8(short_name, variable_name, short_name_size);
+
        /* This is ugly, but necessary to separate one vendor's
           private variables from another's.         */
-
-       *(short_name + strlen(short_name)) = '-';
+       short_name[utf8_name_size] = '-';
        efi_guid_to_str(&new_var->var.VendorGuid,
-                        short_name + strlen(short_name));
+                        short_name + utf8_name_size + 1);
 
        new_var->kobj.kset = efivars_kset;
 
index 70a0fb10517f94ea5b28bada280d9935f0693cc7..7f2ea21c730dd76a86f3ab5a1e253878878960a7 100644 (file)
@@ -165,67 +165,133 @@ validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
 }
 
 struct variable_validate {
+       efi_guid_t vendor;
        char *name;
        bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
                         unsigned long len);
 };
 
+/*
+ * This is the list of variables we need to validate, as well as the
+ * whitelist for what we think is safe not to default to immutable.
+ *
+ * If it has a validate() method that's not NULL, it'll go into the
+ * validation routine.  If not, it is assumed valid, but still used for
+ * whitelisting.
+ *
+ * Note that it's sorted by {vendor,name}, but globbed names must come after
+ * any other name with the same prefix.
+ */
 static const struct variable_validate variable_validate[] = {
-       { "BootNext", validate_uint16 },
-       { "BootOrder", validate_boot_order },
-       { "DriverOrder", validate_boot_order },
-       { "Boot*", validate_load_option },
-       { "Driver*", validate_load_option },
-       { "ConIn", validate_device_path },
-       { "ConInDev", validate_device_path },
-       { "ConOut", validate_device_path },
-       { "ConOutDev", validate_device_path },
-       { "ErrOut", validate_device_path },
-       { "ErrOutDev", validate_device_path },
-       { "Timeout", validate_uint16 },
-       { "Lang", validate_ascii_string },
-       { "PlatformLang", validate_ascii_string },
-       { "", NULL },
+       { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
+       { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
+       { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
+       { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
+       { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
+       { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
+       { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
+       { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
+       { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
+       { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
+       { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
+       { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
+       { EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
+       { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
+       { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
+       { LINUX_EFI_CRASH_GUID, "*", NULL },
+       { NULL_GUID, "", NULL },
 };
 
+static bool
+variable_matches(const char *var_name, size_t len, const char *match_name,
+                int *match)
+{
+       for (*match = 0; ; (*match)++) {
+               char c = match_name[*match];
+               char u = var_name[*match];
+
+               /* Wildcard in the matching name means we've matched */
+               if (c == '*')
+                       return true;
+
+               /* Case sensitive match */
+               if (!c && *match == len)
+                       return true;
+
+               if (c != u)
+                       return false;
+
+               if (!c)
+                       return true;
+       }
+       return true;
+}
+
 bool
-efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len)
+efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
+               unsigned long data_size)
 {
        int i;
-       u16 *unicode_name = var_name;
+       unsigned long utf8_size;
+       u8 *utf8_name;
 
-       for (i = 0; variable_validate[i].validate != NULL; i++) {
-               const char *name = variable_validate[i].name;
-               int match;
+       utf8_size = ucs2_utf8size(var_name);
+       utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
+       if (!utf8_name)
+               return false;
 
-               for (match = 0; ; match++) {
-                       char c = name[match];
-                       u16 u = unicode_name[match];
+       ucs2_as_utf8(utf8_name, var_name, utf8_size);
+       utf8_name[utf8_size] = '\0';
 
-                       /* All special variables are plain ascii */
-                       if (u > 127)
-                               return true;
+       for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
+               const char *name = variable_validate[i].name;
+               int match = 0;
 
-                       /* Wildcard in the matching name means we've matched */
-                       if (c == '*')
-                               return variable_validate[i].validate(var_name,
-                                                            match, data, len);
+               if (efi_guidcmp(vendor, variable_validate[i].vendor))
+                       continue;
 
-                       /* Case sensitive match */
-                       if (c != u)
+               if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
+                       if (variable_validate[i].validate == NULL)
                                break;
-
-                       /* Reached the end of the string while matching */
-                       if (!c)
-                               return variable_validate[i].validate(var_name,
-                                                            match, data, len);
+                       kfree(utf8_name);
+                       return variable_validate[i].validate(var_name, match,
+                                                            data, data_size);
                }
        }
-
+       kfree(utf8_name);
        return true;
 }
 EXPORT_SYMBOL_GPL(efivar_validate);
 
+bool
+efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
+                            size_t len)
+{
+       int i;
+       bool found = false;
+       int match = 0;
+
+       /*
+        * Check if our variable is in the validated variables list
+        */
+       for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
+               if (efi_guidcmp(variable_validate[i].vendor, vendor))
+                       continue;
+
+               if (variable_matches(var_name, len,
+                                    variable_validate[i].name, &match)) {
+                       found = true;
+                       break;
+               }
+       }
+
+       /*
+        * If it's in our list, it is removable.
+        */
+       return found;
+}
+EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
+
 static efi_status_t
 check_var_size(u32 attributes, unsigned long size)
 {
@@ -852,7 +918,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
 
        *set = false;
 
-       if (efivar_validate(name, data, *size) == false)
+       if (efivar_validate(*vendor, name, data, *size) == false)
                return -EINVAL;
 
        /*
index 2aeaebd1c6e7af574fca9058cd0cf758e635943b..3f87a03abc222bc31cbc68eef98993c9e3303ad4 100644 (file)
@@ -312,8 +312,8 @@ static int altera_gpio_probe(struct platform_device *pdev)
                handle_simple_irq, IRQ_TYPE_NONE);
 
        if (ret) {
-               dev_info(&pdev->dev, "could not add irqchip\n");
-               return ret;
+               dev_err(&pdev->dev, "could not add irqchip\n");
+               goto teardown;
        }
 
        gpiochip_set_chained_irqchip(&altera_gc->mmchip.gc,
@@ -326,6 +326,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
 skip_irq:
        return 0;
 teardown:
+       of_mm_gpiochip_remove(&altera_gc->mmchip);
        pr_err("%s: registration failed with status %d\n",
                node->full_name, ret);
 
index ec58f4288649b4ee1f0c98f7761439a525ac093e..cd007a67b3021e6e384889bf06ff7c9b292a7906 100644 (file)
@@ -195,7 +195,7 @@ static int davinci_gpio_of_xlate(struct gpio_chip *gc,
 static int davinci_gpio_probe(struct platform_device *pdev)
 {
        int i, base;
-       unsigned ngpio;
+       unsigned ngpio, nbank;
        struct davinci_gpio_controller *chips;
        struct davinci_gpio_platform_data *pdata;
        struct davinci_gpio_regs __iomem *regs;
@@ -224,8 +224,9 @@ static int davinci_gpio_probe(struct platform_device *pdev)
        if (WARN_ON(ARCH_NR_GPIOS < ngpio))
                ngpio = ARCH_NR_GPIOS;
 
+       nbank = DIV_ROUND_UP(ngpio, 32);
        chips = devm_kzalloc(dev,
-                            ngpio * sizeof(struct davinci_gpio_controller),
+                            nbank * sizeof(struct davinci_gpio_controller),
                             GFP_KERNEL);
        if (!chips)
                return -ENOMEM;
@@ -511,7 +512,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
                        return irq;
                }
 
-               irq_domain = irq_domain_add_legacy(NULL, ngpio, irq, 0,
+               irq_domain = irq_domain_add_legacy(dev->of_node, ngpio, irq, 0,
                                                        &davinci_gpio_irq_ops,
                                                        chips);
                if (!irq_domain) {
index cf41440aff91971e89090138e7912a3713427623..d9ab0cd1d205963528d7022d66213c26bf8304e5 100644 (file)
@@ -196,6 +196,44 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
        return 0;
 }
 
+static void gpio_rcar_irq_bus_lock(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+
+       pm_runtime_get_sync(&p->pdev->dev);
+}
+
+static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+
+       pm_runtime_put(&p->pdev->dev);
+}
+
+
+static int gpio_rcar_irq_request_resources(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+       int error;
+
+       error = pm_runtime_get_sync(&p->pdev->dev);
+       if (error < 0)
+               return error;
+
+       return 0;
+}
+
+static void gpio_rcar_irq_release_resources(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+
+       pm_runtime_put(&p->pdev->dev);
+}
+
 static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
 {
        struct gpio_rcar_priv *p = dev_id;
@@ -450,6 +488,10 @@ static int gpio_rcar_probe(struct platform_device *pdev)
        irq_chip->irq_unmask = gpio_rcar_irq_enable;
        irq_chip->irq_set_type = gpio_rcar_irq_set_type;
        irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
+       irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock;
+       irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock;
+       irq_chip->irq_request_resources = gpio_rcar_irq_request_resources;
+       irq_chip->irq_release_resources = gpio_rcar_irq_release_resources;
        irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
 
        ret = gpiochip_add_data(gpio_chip, p);
index 82edf95b7740d7fe9070cba62009374c08c34562..5e7770f9a415be24140df77708e9d9d39dee7faa 100644 (file)
@@ -87,6 +87,8 @@ extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
 extern int amdgpu_enable_semaphores;
 extern int amdgpu_powerplay;
+extern unsigned amdgpu_pcie_gen_cap;
+extern unsigned amdgpu_pcie_lane_cap;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS         3000
 #define AMDGPU_MAX_USEC_TIMEOUT                        100000  /* 100 ms */
@@ -132,47 +134,6 @@ extern int amdgpu_powerplay;
 #define AMDGPU_RESET_VCE                       (1 << 13)
 #define AMDGPU_RESET_VCE1                      (1 << 14)
 
-/* CG block flags */
-#define AMDGPU_CG_BLOCK_GFX                    (1 << 0)
-#define AMDGPU_CG_BLOCK_MC                     (1 << 1)
-#define AMDGPU_CG_BLOCK_SDMA                   (1 << 2)
-#define AMDGPU_CG_BLOCK_UVD                    (1 << 3)
-#define AMDGPU_CG_BLOCK_VCE                    (1 << 4)
-#define AMDGPU_CG_BLOCK_HDP                    (1 << 5)
-#define AMDGPU_CG_BLOCK_BIF                    (1 << 6)
-
-/* CG flags */
-#define AMDGPU_CG_SUPPORT_GFX_MGCG             (1 << 0)
-#define AMDGPU_CG_SUPPORT_GFX_MGLS             (1 << 1)
-#define AMDGPU_CG_SUPPORT_GFX_CGCG             (1 << 2)
-#define AMDGPU_CG_SUPPORT_GFX_CGLS             (1 << 3)
-#define AMDGPU_CG_SUPPORT_GFX_CGTS             (1 << 4)
-#define AMDGPU_CG_SUPPORT_GFX_CGTS_LS          (1 << 5)
-#define AMDGPU_CG_SUPPORT_GFX_CP_LS            (1 << 6)
-#define AMDGPU_CG_SUPPORT_GFX_RLC_LS           (1 << 7)
-#define AMDGPU_CG_SUPPORT_MC_LS                        (1 << 8)
-#define AMDGPU_CG_SUPPORT_MC_MGCG              (1 << 9)
-#define AMDGPU_CG_SUPPORT_SDMA_LS              (1 << 10)
-#define AMDGPU_CG_SUPPORT_SDMA_MGCG            (1 << 11)
-#define AMDGPU_CG_SUPPORT_BIF_LS               (1 << 12)
-#define AMDGPU_CG_SUPPORT_UVD_MGCG             (1 << 13)
-#define AMDGPU_CG_SUPPORT_VCE_MGCG             (1 << 14)
-#define AMDGPU_CG_SUPPORT_HDP_LS               (1 << 15)
-#define AMDGPU_CG_SUPPORT_HDP_MGCG             (1 << 16)
-
-/* PG flags */
-#define AMDGPU_PG_SUPPORT_GFX_PG               (1 << 0)
-#define AMDGPU_PG_SUPPORT_GFX_SMG              (1 << 1)
-#define AMDGPU_PG_SUPPORT_GFX_DMG              (1 << 2)
-#define AMDGPU_PG_SUPPORT_UVD                  (1 << 3)
-#define AMDGPU_PG_SUPPORT_VCE                  (1 << 4)
-#define AMDGPU_PG_SUPPORT_CP                   (1 << 5)
-#define AMDGPU_PG_SUPPORT_GDS                  (1 << 6)
-#define AMDGPU_PG_SUPPORT_RLC_SMU_HS           (1 << 7)
-#define AMDGPU_PG_SUPPORT_SDMA                 (1 << 8)
-#define AMDGPU_PG_SUPPORT_ACP                  (1 << 9)
-#define AMDGPU_PG_SUPPORT_SAMU                 (1 << 10)
-
 /* GFX current status */
 #define AMDGPU_GFX_NORMAL_MODE                 0x00000000L
 #define AMDGPU_GFX_SAFE_MODE                   0x00000001L
@@ -606,8 +567,6 @@ struct amdgpu_sa_manager {
        uint32_t                align;
 };
 
-struct amdgpu_sa_bo;
-
 /* sub-allocation buffer */
 struct amdgpu_sa_bo {
        struct list_head                olist;
@@ -2360,6 +2319,8 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo);
 int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr,
                                     uint32_t flags);
 bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm);
+bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
+                                 unsigned long end);
 bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm);
 uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
                                 struct ttm_mem_reg *mem);
index a081dda9fa2f6e66e82ee135fcdcd8446bd1674a..7a4b101e10c63564aa3b0b8fffc638c171c1d199 100644 (file)
@@ -795,6 +795,12 @@ static int amdgpu_cgs_query_system_info(void *cgs_device,
        case CGS_SYSTEM_INFO_PCIE_MLW:
                sys_info->value = adev->pm.pcie_mlw_mask;
                break;
+       case CGS_SYSTEM_INFO_CG_FLAGS:
+               sys_info->value = adev->cg_flags;
+               break;
+       case CGS_SYSTEM_INFO_PG_FLAGS:
+               sys_info->value = adev->pg_flags;
+               break;
        default:
                return -ENODEV;
        }
index 89c3dd62ba21ecd116b8490ed105573cecd86a82..119cdc2c43e7cef7fadf72736100cfcef1e200cd 100644 (file)
@@ -77,7 +77,7 @@ void amdgpu_connector_hotplug(struct drm_connector *connector)
                        } else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) {
                                /* Don't try to start link training before we
                                 * have the dpcd */
-                               if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
+                               if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
                                        return;
 
                                /* set it to OFF so that drm_helper_connector_dpms()
index 65531463f88e5b9eb736fdd5e9df357f2f191680..51bfc114584ed5e2fcd086efed40b57f344d2c4f 100644 (file)
@@ -1795,15 +1795,20 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        }
 
        /* post card */
-       amdgpu_atom_asic_init(adev->mode_info.atom_context);
+       if (!amdgpu_card_posted(adev))
+               amdgpu_atom_asic_init(adev->mode_info.atom_context);
 
        r = amdgpu_resume(adev);
+       if (r)
+               DRM_ERROR("amdgpu_resume failed (%d).\n", r);
 
        amdgpu_fence_driver_resume(adev);
 
-       r = amdgpu_ib_ring_tests(adev);
-       if (r)
-               DRM_ERROR("ib ring test failed (%d).\n", r);
+       if (resume) {
+               r = amdgpu_ib_ring_tests(adev);
+               if (r)
+                       DRM_ERROR("ib ring test failed (%d).\n", r);
+       }
 
        r = amdgpu_late_init(adev);
        if (r)
@@ -1933,80 +1938,97 @@ retry:
        return r;
 }
 
+#define AMDGPU_DEFAULT_PCIE_GEN_MASK 0x30007  /* gen: chipset 1/2, asic 1/2/3 */
+#define AMDGPU_DEFAULT_PCIE_MLW_MASK 0x2f0000 /* 1/2/4/8/16 lanes */
+
 void amdgpu_get_pcie_info(struct amdgpu_device *adev)
 {
        u32 mask;
        int ret;
 
-       if (pci_is_root_bus(adev->pdev->bus))
-               return;
+       if (amdgpu_pcie_gen_cap)
+               adev->pm.pcie_gen_mask = amdgpu_pcie_gen_cap;
 
-       if (amdgpu_pcie_gen2 == 0)
-               return;
+       if (amdgpu_pcie_lane_cap)
+               adev->pm.pcie_mlw_mask = amdgpu_pcie_lane_cap;
 
-       if (adev->flags & AMD_IS_APU)
+       /* covers APUs as well */
+       if (pci_is_root_bus(adev->pdev->bus)) {
+               if (adev->pm.pcie_gen_mask == 0)
+                       adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK;
+               if (adev->pm.pcie_mlw_mask == 0)
+                       adev->pm.pcie_mlw_mask = AMDGPU_DEFAULT_PCIE_MLW_MASK;
                return;
+       }
 
-       ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask);
-       if (!ret) {
-               adev->pm.pcie_gen_mask = (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
-                                         CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
-                                         CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
-
-               if (mask & DRM_PCIE_SPEED_25)
-                       adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1;
-               if (mask & DRM_PCIE_SPEED_50)
-                       adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2;
-               if (mask & DRM_PCIE_SPEED_80)
-                       adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3;
-       }
-       ret = drm_pcie_get_max_link_width(adev->ddev, &mask);
-       if (!ret) {
-               switch (mask) {
-               case 32:
-                       adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
-                       break;
-               case 16:
-                       adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
-                       break;
-               case 12:
-                       adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
-                       break;
-               case 8:
-                       adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
-                       break;
-               case 4:
-                       adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
-                       break;
-               case 2:
-                       adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
-                                                 CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
-                       break;
-               case 1:
-                       adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1;
-                       break;
-               default:
-                       break;
+       if (adev->pm.pcie_gen_mask == 0) {
+               ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask);
+               if (!ret) {
+                       adev->pm.pcie_gen_mask = (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
+                                                 CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
+                                                 CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
+
+                       if (mask & DRM_PCIE_SPEED_25)
+                               adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1;
+                       if (mask & DRM_PCIE_SPEED_50)
+                               adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2;
+                       if (mask & DRM_PCIE_SPEED_80)
+                               adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3;
+               } else {
+                       adev->pm.pcie_gen_mask = AMDGPU_DEFAULT_PCIE_GEN_MASK;
+               }
+       }
+       if (adev->pm.pcie_mlw_mask == 0) {
+               ret = drm_pcie_get_max_link_width(adev->ddev, &mask);
+               if (!ret) {
+                       switch (mask) {
+                       case 32:
+                               adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+                               break;
+                       case 16:
+                               adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+                               break;
+                       case 12:
+                               adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+                               break;
+                       case 8:
+                               adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+                               break;
+                       case 4:
+                               adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+                               break;
+                       case 2:
+                               adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 |
+                                                         CAIL_PCIE_LINK_WIDTH_SUPPORT_X1);
+                               break;
+                       case 1:
+                               adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1;
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
+                       adev->pm.pcie_mlw_mask = AMDGPU_DEFAULT_PCIE_MLW_MASK;
                }
        }
 }
index acd066d0a8051d0ad17f7311d8db1acd37348060..8297bc319369d6e4e4dd1579195ca1b6161a57d1 100644 (file)
@@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
 
        struct drm_crtc *crtc = &amdgpuCrtc->base;
        unsigned long flags;
-       unsigned i;
-       int vpos, hpos, stat, min_udelay;
+       unsigned i, repcnt = 4;
+       int vpos, hpos, stat, min_udelay = 0;
        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
 
        amdgpu_flip_wait_fence(adev, &work->excl);
@@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
         * In practice this won't execute very often unless on very fast
         * machines because the time window for this to happen is very small.
         */
-       for (;;) {
+       while (amdgpuCrtc->enabled && repcnt--) {
                /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
                 * start in hpos, and to the "fudged earlier" vblank start in
                 * vpos.
@@ -114,10 +114,22 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
                /* Sleep at least until estimated real start of hw vblank */
                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
+               if (min_udelay > vblank->framedur_ns / 2000) {
+                       /* Don't wait ridiculously long - something is wrong */
+                       repcnt = 0;
+                       break;
+               }
                usleep_range(min_udelay, 2 * min_udelay);
                spin_lock_irqsave(&crtc->dev->event_lock, flags);
        };
 
+       if (!repcnt)
+               DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
+                                "framedur %d, linedur %d, stat %d, vpos %d, "
+                                "hpos %d\n", work->crtc_id, min_udelay,
+                                vblank->framedur_ns / 1000,
+                                vblank->linedur_ns / 1000, stat, vpos, hpos);
+
        /* do the flip (mmio) */
        adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
        /* set the flip status */
index 9c1af8976befea20cf371cc4a15f226dbe434d75..9ef1db87cf260c2a6a8abd423dde4be313f355ae 100644 (file)
@@ -83,6 +83,8 @@ int amdgpu_sched_jobs = 32;
 int amdgpu_sched_hw_submission = 2;
 int amdgpu_enable_semaphores = 0;
 int amdgpu_powerplay = -1;
+unsigned amdgpu_pcie_gen_cap = 0;
+unsigned amdgpu_pcie_lane_cap = 0;
 
 MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
 module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -170,6 +172,12 @@ MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 =
 module_param_named(powerplay, amdgpu_powerplay, int, 0444);
 #endif
 
+MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))");
+module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444);
+
+MODULE_PARM_DESC(pcie_lane_cap, "PCIE Lane Caps (0: autodetect (default))");
+module_param_named(pcie_lane_cap, amdgpu_pcie_lane_cap, uint, 0444);
+
 static struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
        /* Kaveri */
index 7380f782cd14a2ba1b3bb182832971368545e404..d20c2a8929cbdaf39164e6c709df67d36b352f35 100644 (file)
@@ -596,7 +596,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                break;
        }
        ttm_eu_backoff_reservation(&ticket, &list);
-       if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
+       if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
+           !amdgpu_vm_debug)
                amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
 
        drm_gem_object_unreference_unlocked(gobj);
index b1969f2b2038db79af8447fc9826ba8257207cf4..d4e2780c079663a643bddeaa7e2da5e15a2ff47d 100644 (file)
@@ -142,7 +142,8 @@ static void amdgpu_mn_invalidate_range_start(struct mmu_notifier *mn,
 
                list_for_each_entry(bo, &node->bos, mn_list) {
 
-                       if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound)
+                       if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start,
+                                                         end))
                                continue;
 
                        r = amdgpu_bo_reserve(bo, true);
index 7d8d84eaea4a5ab258eb5dac4a383f6aff81850d..95a4a25d8df9e8d37e1ec06d2d566e337353f222 100644 (file)
@@ -113,6 +113,10 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = ddev->dev_private;
 
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return snprintf(buf, PAGE_SIZE, "off\n");
+
        if (adev->pp_enabled) {
                enum amd_dpm_forced_level level;
 
@@ -140,6 +144,11 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
        enum amdgpu_dpm_forced_level level;
        int ret = 0;
 
+       /* Can't force performance level when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        if (strncmp("low", buf, strlen("low")) == 0) {
                level = AMDGPU_DPM_FORCED_LEVEL_LOW;
        } else if (strncmp("high", buf, strlen("high")) == 0) {
@@ -157,6 +166,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
                mutex_lock(&adev->pm.mutex);
                if (adev->pm.dpm.thermal_active) {
                        count = -EINVAL;
+                       mutex_unlock(&adev->pm.mutex);
                        goto fail;
                }
                ret = amdgpu_dpm_force_performance_level(adev, level);
@@ -167,8 +177,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
                mutex_unlock(&adev->pm.mutex);
        }
 fail:
-       mutex_unlock(&adev->pm.mutex);
-
        return count;
 }
 
@@ -182,8 +190,14 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
                                      char *buf)
 {
        struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
        int temp;
 
+       /* Can't get temperature when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        if (!adev->pp_enabled && !adev->pm.funcs->get_temperature)
                temp = 0;
        else
@@ -634,11 +648,6 @@ force:
 
        /* update display watermarks based on new power state */
        amdgpu_display_bandwidth_update(adev);
-       /* update displays */
-       amdgpu_dpm_display_configuration_changed(adev);
-
-       adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
-       adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
 
        /* wait for the rings to drain */
        for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
@@ -655,6 +664,12 @@ force:
 
        amdgpu_dpm_post_set_power_state(adev);
 
+       /* update displays */
+       amdgpu_dpm_display_configuration_changed(adev);
+
+       adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
+       adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
+
        if (adev->pm.funcs->force_performance_level) {
                if (adev->pm.dpm.thermal_active) {
                        enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
@@ -847,12 +862,16 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct amdgpu_device *adev = dev->dev_private;
+       struct drm_device *ddev = adev->ddev;
 
        if (!adev->pm.dpm_enabled) {
                seq_printf(m, "dpm not enabled\n");
                return 0;
        }
-       if (adev->pp_enabled) {
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
+               seq_printf(m, "PX asic powered off\n");
+       } else if (adev->pp_enabled) {
                amdgpu_dpm_debugfs_print_current_performance_level(adev, m);
        } else {
                mutex_lock(&adev->pm.mutex);
index b9d0d55f6b47df33ab7ebf7024fe7ca6e821892a..3cb6d6c413c71b0207fe1766d26ca190a083e880 100644 (file)
@@ -143,8 +143,10 @@ static int amdgpu_pp_late_init(void *handle)
                                        adev->powerplay.pp_handle);
 
 #ifdef CONFIG_DRM_AMD_POWERPLAY
-       if (adev->pp_enabled)
+       if (adev->pp_enabled) {
                amdgpu_pm_sysfs_init(adev);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL);
+       }
 #endif
        return ret;
 }
index 8b88edb0434bfb43ed4b7aae7e6f3e7dc63d0893..ca72a2e487b9b9d846b65479e9b865dd1ef71281 100644 (file)
@@ -354,12 +354,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
 
                for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i)
                        if (fences[i])
-                               fences[count++] = fences[i];
+                               fences[count++] = fence_get(fences[i]);
 
                if (count) {
                        spin_unlock(&sa_manager->wq.lock);
                        t = fence_wait_any_timeout(fences, count, false,
                                                   MAX_SCHEDULE_TIMEOUT);
+                       for (i = 0; i < count; ++i)
+                               fence_put(fences[i]);
+
                        r = (t > 0) ? 0 : t;
                        spin_lock(&sa_manager->wq.lock);
                } else {
index 55cf05e1c81c398fc747f598d1ce0bc78a38a435..1cbb16e153079e7463a0ac070d1a19461deb588e 100644 (file)
@@ -712,7 +712,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm)
                                                       0, PAGE_SIZE,
                                                       PCI_DMA_BIDIRECTIONAL);
                if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) {
-                       while (--i) {
+                       while (i--) {
                                pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i],
                                               PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
                                gtt->ttm.dma_address[i] = 0;
@@ -783,6 +783,25 @@ bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm)
        return !!gtt->userptr;
 }
 
+bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
+                                 unsigned long end)
+{
+       struct amdgpu_ttm_tt *gtt = (void *)ttm;
+       unsigned long size;
+
+       if (gtt == NULL)
+               return false;
+
+       if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr)
+               return false;
+
+       size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE;
+       if (gtt->userptr > end || gtt->userptr + size <= start)
+               return false;
+
+       return true;
+}
+
 bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm)
 {
        struct amdgpu_ttm_tt *gtt = (void *)ttm;
index 8b4731d4e10eabbd78f17f799c5fcd1156ba9862..474ca02b094935283c3548534a2502cd01412665 100644 (file)
@@ -31,6 +31,7 @@
 #include "ci_dpm.h"
 #include "gfx_v7_0.h"
 #include "atom.h"
+#include "amd_pcie.h"
 #include <linux/seq_file.h>
 
 #include "smu/smu_7_0_1_d.h"
@@ -5835,18 +5836,16 @@ static int ci_dpm_init(struct amdgpu_device *adev)
        u8 frev, crev;
        struct ci_power_info *pi;
        int ret;
-       u32 mask;
 
        pi = kzalloc(sizeof(struct ci_power_info), GFP_KERNEL);
        if (pi == NULL)
                return -ENOMEM;
        adev->pm.dpm.priv = pi;
 
-       ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask);
-       if (ret)
-               pi->sys_pcie_mask = 0;
-       else
-               pi->sys_pcie_mask = mask;
+       pi->sys_pcie_mask =
+               (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK) >>
+               CAIL_PCIE_LINK_SPEED_SUPPORT_SHIFT;
+
        pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID;
 
        pi->pcie_gen_performance.max = AMDGPU_PCIE_GEN1;
index fd9c9588ef46335d7a154e664bce8275d62f3ae9..155965ed14a3bee05d745b5e25fccf03546dc4ae 100644 (file)
@@ -1762,6 +1762,9 @@ static void cik_program_aspm(struct amdgpu_device *adev)
        if (amdgpu_aspm == 0)
                return;
 
+       if (pci_is_root_bus(adev->pdev->bus))
+               return;
+
        /* XXX double check APUs */
        if (adev->flags & AMD_IS_APU)
                return;
@@ -2332,72 +2335,72 @@ static int cik_common_early_init(void *handle)
        switch (adev->asic_type) {
        case CHIP_BONAIRE:
                adev->cg_flags =
-                       AMDGPU_CG_SUPPORT_GFX_MGCG |
-                       AMDGPU_CG_SUPPORT_GFX_MGLS |
-                       /*AMDGPU_CG_SUPPORT_GFX_CGCG |*/
-                       AMDGPU_CG_SUPPORT_GFX_CGLS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS_LS |
-                       AMDGPU_CG_SUPPORT_GFX_CP_LS |
-                       AMDGPU_CG_SUPPORT_MC_LS |
-                       AMDGPU_CG_SUPPORT_MC_MGCG |
-                       AMDGPU_CG_SUPPORT_SDMA_MGCG |
-                       AMDGPU_CG_SUPPORT_SDMA_LS |
-                       AMDGPU_CG_SUPPORT_BIF_LS |
-                       AMDGPU_CG_SUPPORT_VCE_MGCG |
-                       AMDGPU_CG_SUPPORT_UVD_MGCG |
-                       AMDGPU_CG_SUPPORT_HDP_LS |
-                       AMDGPU_CG_SUPPORT_HDP_MGCG;
+                       AMD_CG_SUPPORT_GFX_MGCG |
+                       AMD_CG_SUPPORT_GFX_MGLS |
+                       /*AMD_CG_SUPPORT_GFX_CGCG |*/
+                       AMD_CG_SUPPORT_GFX_CGLS |
+                       AMD_CG_SUPPORT_GFX_CGTS |
+                       AMD_CG_SUPPORT_GFX_CGTS_LS |
+                       AMD_CG_SUPPORT_GFX_CP_LS |
+                       AMD_CG_SUPPORT_MC_LS |
+                       AMD_CG_SUPPORT_MC_MGCG |
+                       AMD_CG_SUPPORT_SDMA_MGCG |
+                       AMD_CG_SUPPORT_SDMA_LS |
+                       AMD_CG_SUPPORT_BIF_LS |
+                       AMD_CG_SUPPORT_VCE_MGCG |
+                       AMD_CG_SUPPORT_UVD_MGCG |
+                       AMD_CG_SUPPORT_HDP_LS |
+                       AMD_CG_SUPPORT_HDP_MGCG;
                adev->pg_flags = 0;
                adev->external_rev_id = adev->rev_id + 0x14;
                break;
        case CHIP_HAWAII:
                adev->cg_flags =
-                       AMDGPU_CG_SUPPORT_GFX_MGCG |
-                       AMDGPU_CG_SUPPORT_GFX_MGLS |
-                       /*AMDGPU_CG_SUPPORT_GFX_CGCG |*/
-                       AMDGPU_CG_SUPPORT_GFX_CGLS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS |
-                       AMDGPU_CG_SUPPORT_GFX_CP_LS |
-                       AMDGPU_CG_SUPPORT_MC_LS |
-                       AMDGPU_CG_SUPPORT_MC_MGCG |
-                       AMDGPU_CG_SUPPORT_SDMA_MGCG |
-                       AMDGPU_CG_SUPPORT_SDMA_LS |
-                       AMDGPU_CG_SUPPORT_BIF_LS |
-                       AMDGPU_CG_SUPPORT_VCE_MGCG |
-                       AMDGPU_CG_SUPPORT_UVD_MGCG |
-                       AMDGPU_CG_SUPPORT_HDP_LS |
-                       AMDGPU_CG_SUPPORT_HDP_MGCG;
+                       AMD_CG_SUPPORT_GFX_MGCG |
+                       AMD_CG_SUPPORT_GFX_MGLS |
+                       /*AMD_CG_SUPPORT_GFX_CGCG |*/
+                       AMD_CG_SUPPORT_GFX_CGLS |
+                       AMD_CG_SUPPORT_GFX_CGTS |
+                       AMD_CG_SUPPORT_GFX_CP_LS |
+                       AMD_CG_SUPPORT_MC_LS |
+                       AMD_CG_SUPPORT_MC_MGCG |
+                       AMD_CG_SUPPORT_SDMA_MGCG |
+                       AMD_CG_SUPPORT_SDMA_LS |
+                       AMD_CG_SUPPORT_BIF_LS |
+                       AMD_CG_SUPPORT_VCE_MGCG |
+                       AMD_CG_SUPPORT_UVD_MGCG |
+                       AMD_CG_SUPPORT_HDP_LS |
+                       AMD_CG_SUPPORT_HDP_MGCG;
                adev->pg_flags = 0;
                adev->external_rev_id = 0x28;
                break;
        case CHIP_KAVERI:
                adev->cg_flags =
-                       AMDGPU_CG_SUPPORT_GFX_MGCG |
-                       AMDGPU_CG_SUPPORT_GFX_MGLS |
-                       /*AMDGPU_CG_SUPPORT_GFX_CGCG |*/
-                       AMDGPU_CG_SUPPORT_GFX_CGLS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS_LS |
-                       AMDGPU_CG_SUPPORT_GFX_CP_LS |
-                       AMDGPU_CG_SUPPORT_SDMA_MGCG |
-                       AMDGPU_CG_SUPPORT_SDMA_LS |
-                       AMDGPU_CG_SUPPORT_BIF_LS |
-                       AMDGPU_CG_SUPPORT_VCE_MGCG |
-                       AMDGPU_CG_SUPPORT_UVD_MGCG |
-                       AMDGPU_CG_SUPPORT_HDP_LS |
-                       AMDGPU_CG_SUPPORT_HDP_MGCG;
+                       AMD_CG_SUPPORT_GFX_MGCG |
+                       AMD_CG_SUPPORT_GFX_MGLS |
+                       /*AMD_CG_SUPPORT_GFX_CGCG |*/
+                       AMD_CG_SUPPORT_GFX_CGLS |
+                       AMD_CG_SUPPORT_GFX_CGTS |
+                       AMD_CG_SUPPORT_GFX_CGTS_LS |
+                       AMD_CG_SUPPORT_GFX_CP_LS |
+                       AMD_CG_SUPPORT_SDMA_MGCG |
+                       AMD_CG_SUPPORT_SDMA_LS |
+                       AMD_CG_SUPPORT_BIF_LS |
+                       AMD_CG_SUPPORT_VCE_MGCG |
+                       AMD_CG_SUPPORT_UVD_MGCG |
+                       AMD_CG_SUPPORT_HDP_LS |
+                       AMD_CG_SUPPORT_HDP_MGCG;
                adev->pg_flags =
-                       /*AMDGPU_PG_SUPPORT_GFX_PG |
-                         AMDGPU_PG_SUPPORT_GFX_SMG |
-                         AMDGPU_PG_SUPPORT_GFX_DMG |*/
-                       AMDGPU_PG_SUPPORT_UVD |
-                       /*AMDGPU_PG_SUPPORT_VCE |
-                         AMDGPU_PG_SUPPORT_CP |
-                         AMDGPU_PG_SUPPORT_GDS |
-                         AMDGPU_PG_SUPPORT_RLC_SMU_HS |
-                         AMDGPU_PG_SUPPORT_ACP |
-                         AMDGPU_PG_SUPPORT_SAMU |*/
+                       /*AMD_PG_SUPPORT_GFX_PG |
+                         AMD_PG_SUPPORT_GFX_SMG |
+                         AMD_PG_SUPPORT_GFX_DMG |*/
+                       AMD_PG_SUPPORT_UVD |
+                       /*AMD_PG_SUPPORT_VCE |
+                         AMD_PG_SUPPORT_CP |
+                         AMD_PG_SUPPORT_GDS |
+                         AMD_PG_SUPPORT_RLC_SMU_HS |
+                         AMD_PG_SUPPORT_ACP |
+                         AMD_PG_SUPPORT_SAMU |*/
                        0;
                if (adev->pdev->device == 0x1312 ||
                        adev->pdev->device == 0x1316 ||
@@ -2409,29 +2412,29 @@ static int cik_common_early_init(void *handle)
        case CHIP_KABINI:
        case CHIP_MULLINS:
                adev->cg_flags =
-                       AMDGPU_CG_SUPPORT_GFX_MGCG |
-                       AMDGPU_CG_SUPPORT_GFX_MGLS |
-                       /*AMDGPU_CG_SUPPORT_GFX_CGCG |*/
-                       AMDGPU_CG_SUPPORT_GFX_CGLS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS |
-                       AMDGPU_CG_SUPPORT_GFX_CGTS_LS |
-                       AMDGPU_CG_SUPPORT_GFX_CP_LS |
-                       AMDGPU_CG_SUPPORT_SDMA_MGCG |
-                       AMDGPU_CG_SUPPORT_SDMA_LS |
-                       AMDGPU_CG_SUPPORT_BIF_LS |
-                       AMDGPU_CG_SUPPORT_VCE_MGCG |
-                       AMDGPU_CG_SUPPORT_UVD_MGCG |
-                       AMDGPU_CG_SUPPORT_HDP_LS |
-                       AMDGPU_CG_SUPPORT_HDP_MGCG;
+                       AMD_CG_SUPPORT_GFX_MGCG |
+                       AMD_CG_SUPPORT_GFX_MGLS |
+                       /*AMD_CG_SUPPORT_GFX_CGCG |*/
+                       AMD_CG_SUPPORT_GFX_CGLS |
+                       AMD_CG_SUPPORT_GFX_CGTS |
+                       AMD_CG_SUPPORT_GFX_CGTS_LS |
+                       AMD_CG_SUPPORT_GFX_CP_LS |
+                       AMD_CG_SUPPORT_SDMA_MGCG |
+                       AMD_CG_SUPPORT_SDMA_LS |
+                       AMD_CG_SUPPORT_BIF_LS |
+                       AMD_CG_SUPPORT_VCE_MGCG |
+                       AMD_CG_SUPPORT_UVD_MGCG |
+                       AMD_CG_SUPPORT_HDP_LS |
+                       AMD_CG_SUPPORT_HDP_MGCG;
                adev->pg_flags =
-                       /*AMDGPU_PG_SUPPORT_GFX_PG |
-                         AMDGPU_PG_SUPPORT_GFX_SMG | */
-                       AMDGPU_PG_SUPPORT_UVD |
-                       /*AMDGPU_PG_SUPPORT_VCE |
-                         AMDGPU_PG_SUPPORT_CP |
-                         AMDGPU_PG_SUPPORT_GDS |
-                         AMDGPU_PG_SUPPORT_RLC_SMU_HS |
-                         AMDGPU_PG_SUPPORT_SAMU |*/
+                       /*AMD_PG_SUPPORT_GFX_PG |
+                         AMD_PG_SUPPORT_GFX_SMG | */
+                       AMD_PG_SUPPORT_UVD |
+                       /*AMD_PG_SUPPORT_VCE |
+                         AMD_PG_SUPPORT_CP |
+                         AMD_PG_SUPPORT_GDS |
+                         AMD_PG_SUPPORT_RLC_SMU_HS |
+                         AMD_PG_SUPPORT_SAMU |*/
                        0;
                if (adev->asic_type == CHIP_KABINI) {
                        if (adev->rev_id == 0)
index 5f712ceddf08e4765fb544aff0cad26e6bbcd890..c55ecf0ea8454822a07711c3b85479a9e51e214d 100644 (file)
@@ -885,7 +885,7 @@ static void cik_enable_sdma_mgcg(struct amdgpu_device *adev,
 {
        u32 orig, data;
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_SDMA_MGCG)) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
                WREG32(mmSDMA0_CLK_CTRL + SDMA0_REGISTER_OFFSET, 0x00000100);
                WREG32(mmSDMA0_CLK_CTRL + SDMA1_REGISTER_OFFSET, 0x00000100);
        } else {
@@ -906,7 +906,7 @@ static void cik_enable_sdma_mgls(struct amdgpu_device *adev,
 {
        u32 orig, data;
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_SDMA_LS)) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
                orig = data = RREG32(mmSDMA0_POWER_CNTL + SDMA0_REGISTER_OFFSET);
                data |= 0x100;
                if (orig != data)
index 4dd17f2dd9059125eace5ffd5fc2a8cf2eb46802..e7ef2261ff4a70821a318e0377a33f7383607314 100644 (file)
@@ -445,13 +445,13 @@ static int cz_dpm_init(struct amdgpu_device *adev)
        pi->gfx_pg_threshold = 500;
        pi->caps_fps = true;
        /* uvd */
-       pi->caps_uvd_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_UVD) ? true : false;
+       pi->caps_uvd_pg = (adev->pg_flags & AMD_PG_SUPPORT_UVD) ? true : false;
        pi->caps_uvd_dpm = true;
        /* vce */
-       pi->caps_vce_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_VCE) ? true : false;
+       pi->caps_vce_pg = (adev->pg_flags & AMD_PG_SUPPORT_VCE) ? true : false;
        pi->caps_vce_dpm = true;
        /* acp */
-       pi->caps_acp_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_ACP) ? true : false;
+       pi->caps_acp_pg = (adev->pg_flags & AMD_PG_SUPPORT_ACP) ? true : false;
        pi->caps_acp_dpm = true;
 
        pi->caps_stable_power_state = false;
@@ -2202,8 +2202,7 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
                                                            AMD_PG_STATE_GATE);
 
                                cz_enable_vce_dpm(adev, false);
-                               /* TODO: to figure out why vce can't be poweroff. */
-                               /* cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF); */
+                               cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF);
                                pi->vce_power_gated = true;
                        } else {
                                cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerON);
@@ -2226,10 +2225,8 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
                }
        } else { /*pi->caps_vce_pg*/
                cz_update_vce_dpm(adev);
-               cz_enable_vce_dpm(adev, true);
+               cz_enable_vce_dpm(adev, !gate);
        }
-
-       return;
 }
 
 const struct amd_ip_funcs cz_dpm_ip_funcs = {
index 6c76139de1c9c5992579a7eb44d1f6f4eff9da9a..06602df707f86375d8db781db550d6db160e06e0 100644 (file)
@@ -3628,6 +3628,19 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                                        unsigned vm_id, uint64_t pd_addr)
 {
        int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+       uint32_t seq = ring->fence_drv.sync_seq;
+       uint64_t addr = ring->fence_drv.gpu_addr;
+
+       amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+       amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+                                WAIT_REG_MEM_FUNCTION(3) | /* equal */
+                                WAIT_REG_MEM_ENGINE(usepfp)));   /* pfp or me */
+       amdgpu_ring_write(ring, addr & 0xfffffffc);
+       amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
+       amdgpu_ring_write(ring, seq);
+       amdgpu_ring_write(ring, 0xffffffff);
+       amdgpu_ring_write(ring, 4); /* poll interval */
+
        if (usepfp) {
                /* synce CE with ME to prevent CE fetch CEIB before context switch done */
                amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
@@ -4109,7 +4122,7 @@ static void gfx_v7_0_enable_cgcg(struct amdgpu_device *adev, bool enable)
 
        orig = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_CGCG)) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
                gfx_v7_0_enable_gui_idle_interrupt(adev, true);
 
                tmp = gfx_v7_0_halt_rlc(adev);
@@ -4147,9 +4160,9 @@ static void gfx_v7_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
 {
        u32 data, orig, tmp = 0;
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_MGCG)) {
-               if (adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_MGLS) {
-                       if (adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_CP_LS) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
+               if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
+                       if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
                                orig = data = RREG32(mmCP_MEM_SLP_CNTL);
                                data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
                                if (orig != data)
@@ -4176,14 +4189,14 @@ static void gfx_v7_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
 
                gfx_v7_0_update_rlc(adev, tmp);
 
-               if (adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_CGTS) {
+               if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGTS) {
                        orig = data = RREG32(mmCGTS_SM_CTRL_REG);
                        data &= ~CGTS_SM_CTRL_REG__SM_MODE_MASK;
                        data |= (0x2 << CGTS_SM_CTRL_REG__SM_MODE__SHIFT);
                        data |= CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK;
                        data &= ~CGTS_SM_CTRL_REG__OVERRIDE_MASK;
-                       if ((adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_MGLS) &&
-                           (adev->cg_flags & AMDGPU_CG_SUPPORT_GFX_CGTS_LS))
+                       if ((adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) &&
+                           (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGTS_LS))
                                data &= ~CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK;
                        data &= ~CGTS_SM_CTRL_REG__ON_MONITOR_ADD_MASK;
                        data |= CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK;
@@ -4249,7 +4262,7 @@ static void gfx_v7_0_enable_sclk_slowdown_on_pu(struct amdgpu_device *adev,
        u32 data, orig;
 
        orig = data = RREG32(mmRLC_PG_CNTL);
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_RLC_SMU_HS))
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS))
                data |= RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK;
        else
                data &= ~RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK;
@@ -4263,7 +4276,7 @@ static void gfx_v7_0_enable_sclk_slowdown_on_pd(struct amdgpu_device *adev,
        u32 data, orig;
 
        orig = data = RREG32(mmRLC_PG_CNTL);
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_RLC_SMU_HS))
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS))
                data |= RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK;
        else
                data &= ~RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK;
@@ -4276,7 +4289,7 @@ static void gfx_v7_0_enable_cp_pg(struct amdgpu_device *adev, bool enable)
        u32 data, orig;
 
        orig = data = RREG32(mmRLC_PG_CNTL);
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_CP))
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_CP))
                data &= ~0x8000;
        else
                data |= 0x8000;
@@ -4289,7 +4302,7 @@ static void gfx_v7_0_enable_gds_pg(struct amdgpu_device *adev, bool enable)
        u32 data, orig;
 
        orig = data = RREG32(mmRLC_PG_CNTL);
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_GDS))
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GDS))
                data &= ~0x2000;
        else
                data |= 0x2000;
@@ -4370,7 +4383,7 @@ static void gfx_v7_0_enable_gfx_cgpg(struct amdgpu_device *adev,
 {
        u32 data, orig;
 
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_GFX_PG)) {
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
                orig = data = RREG32(mmRLC_PG_CNTL);
                data |= RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK;
                if (orig != data)
@@ -4442,7 +4455,7 @@ static void gfx_v7_0_enable_gfx_static_mgpg(struct amdgpu_device *adev,
        u32 data, orig;
 
        orig = data = RREG32(mmRLC_PG_CNTL);
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_GFX_SMG))
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG))
                data |= RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
        else
                data &= ~RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
@@ -4456,7 +4469,7 @@ static void gfx_v7_0_enable_gfx_dynamic_mgpg(struct amdgpu_device *adev,
        u32 data, orig;
 
        orig = data = RREG32(mmRLC_PG_CNTL);
-       if (enable && (adev->pg_flags & AMDGPU_PG_SUPPORT_GFX_DMG))
+       if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_DMG))
                data |= RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
        else
                data &= ~RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
@@ -4623,15 +4636,15 @@ static void gfx_v7_0_get_csb_buffer(struct amdgpu_device *adev,
 
 static void gfx_v7_0_init_pg(struct amdgpu_device *adev)
 {
-       if (adev->pg_flags & (AMDGPU_PG_SUPPORT_GFX_PG |
-                             AMDGPU_PG_SUPPORT_GFX_SMG |
-                             AMDGPU_PG_SUPPORT_GFX_DMG |
-                             AMDGPU_PG_SUPPORT_CP |
-                             AMDGPU_PG_SUPPORT_GDS |
-                             AMDGPU_PG_SUPPORT_RLC_SMU_HS)) {
+       if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
+                             AMD_PG_SUPPORT_GFX_SMG |
+                             AMD_PG_SUPPORT_GFX_DMG |
+                             AMD_PG_SUPPORT_CP |
+                             AMD_PG_SUPPORT_GDS |
+                             AMD_PG_SUPPORT_RLC_SMU_HS)) {
                gfx_v7_0_enable_sclk_slowdown_on_pu(adev, true);
                gfx_v7_0_enable_sclk_slowdown_on_pd(adev, true);
-               if (adev->pg_flags & AMDGPU_PG_SUPPORT_GFX_PG) {
+               if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) {
                        gfx_v7_0_init_gfx_cgpg(adev);
                        gfx_v7_0_enable_cp_pg(adev, true);
                        gfx_v7_0_enable_gds_pg(adev, true);
@@ -4643,14 +4656,14 @@ static void gfx_v7_0_init_pg(struct amdgpu_device *adev)
 
 static void gfx_v7_0_fini_pg(struct amdgpu_device *adev)
 {
-       if (adev->pg_flags & (AMDGPU_PG_SUPPORT_GFX_PG |
-                             AMDGPU_PG_SUPPORT_GFX_SMG |
-                             AMDGPU_PG_SUPPORT_GFX_DMG |
-                             AMDGPU_PG_SUPPORT_CP |
-                             AMDGPU_PG_SUPPORT_GDS |
-                             AMDGPU_PG_SUPPORT_RLC_SMU_HS)) {
+       if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
+                             AMD_PG_SUPPORT_GFX_SMG |
+                             AMD_PG_SUPPORT_GFX_DMG |
+                             AMD_PG_SUPPORT_CP |
+                             AMD_PG_SUPPORT_GDS |
+                             AMD_PG_SUPPORT_RLC_SMU_HS)) {
                gfx_v7_0_update_gfx_pg(adev, false);
-               if (adev->pg_flags & AMDGPU_PG_SUPPORT_GFX_PG) {
+               if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) {
                        gfx_v7_0_enable_cp_pg(adev, false);
                        gfx_v7_0_enable_gds_pg(adev, false);
                }
@@ -5527,14 +5540,14 @@ static int gfx_v7_0_set_powergating_state(void *handle,
        if (state == AMD_PG_STATE_GATE)
                gate = true;
 
-       if (adev->pg_flags & (AMDGPU_PG_SUPPORT_GFX_PG |
-                             AMDGPU_PG_SUPPORT_GFX_SMG |
-                             AMDGPU_PG_SUPPORT_GFX_DMG |
-                             AMDGPU_PG_SUPPORT_CP |
-                             AMDGPU_PG_SUPPORT_GDS |
-                             AMDGPU_PG_SUPPORT_RLC_SMU_HS)) {
+       if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
+                             AMD_PG_SUPPORT_GFX_SMG |
+                             AMD_PG_SUPPORT_GFX_DMG |
+                             AMD_PG_SUPPORT_CP |
+                             AMD_PG_SUPPORT_GDS |
+                             AMD_PG_SUPPORT_RLC_SMU_HS)) {
                gfx_v7_0_update_gfx_pg(adev, gate);
-               if (adev->pg_flags & AMDGPU_PG_SUPPORT_GFX_PG) {
+               if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) {
                        gfx_v7_0_enable_cp_pg(adev, gate);
                        gfx_v7_0_enable_gds_pg(adev, gate);
                }
index 8f8ec37ecd883599b416773a0a6a579da6131515..7086ac17abee11aa68e6a863099c73b273db1717 100644 (file)
@@ -4809,7 +4809,8 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 
        amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
        amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
-                WAIT_REG_MEM_FUNCTION(3))); /* equal */
+                                WAIT_REG_MEM_FUNCTION(3) | /* equal */
+                                WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */
        amdgpu_ring_write(ring, addr & 0xfffffffc);
        amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
        amdgpu_ring_write(ring, seq);
@@ -4995,7 +4996,7 @@ static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
        case AMDGPU_IRQ_STATE_ENABLE:
                cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
                cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
-                                           PRIV_REG_INT_ENABLE, 0);
+                                           PRIV_REG_INT_ENABLE, 1);
                WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
                break;
        default:
index 8aa2991ab379af7c6d981c1e01734f6b83da3692..b8060795b27b96409a37ce213a3f6076127c7d71 100644 (file)
@@ -792,7 +792,7 @@ static void gmc_v7_0_enable_mc_ls(struct amdgpu_device *adev,
 
        for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) {
                orig = data = RREG32(mc_cg_registers[i]);
-               if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_MC_LS))
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
                        data |= mc_cg_ls_en[i];
                else
                        data &= ~mc_cg_ls_en[i];
@@ -809,7 +809,7 @@ static void gmc_v7_0_enable_mc_mgcg(struct amdgpu_device *adev,
 
        for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) {
                orig = data = RREG32(mc_cg_registers[i]);
-               if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_MC_MGCG))
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
                        data |= mc_cg_en[i];
                else
                        data &= ~mc_cg_en[i];
@@ -825,7 +825,7 @@ static void gmc_v7_0_enable_bif_mgls(struct amdgpu_device *adev,
 
        orig = data = RREG32_PCIE(ixPCIE_CNTL2);
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_BIF_LS)) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) {
                data = REG_SET_FIELD(data, PCIE_CNTL2, SLV_MEM_LS_EN, 1);
                data = REG_SET_FIELD(data, PCIE_CNTL2, MST_MEM_LS_EN, 1);
                data = REG_SET_FIELD(data, PCIE_CNTL2, REPLAY_MEM_LS_EN, 1);
@@ -848,7 +848,7 @@ static void gmc_v7_0_enable_hdp_mgcg(struct amdgpu_device *adev,
 
        orig = data = RREG32(mmHDP_HOST_PATH_CNTL);
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_MGCG))
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG))
                data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 0);
        else
                data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 1);
@@ -864,7 +864,7 @@ static void gmc_v7_0_enable_hdp_ls(struct amdgpu_device *adev,
 
        orig = data = RREG32(mmHDP_MEM_POWER_LS);
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_LS))
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
                data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 1);
        else
                data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 0);
index 7e9154c7f1dbbb7f9d3eee6791c0e4fcc835ea8d..654d76723bc39d8004b461c7c51d401384d2ee20 100644 (file)
@@ -2859,11 +2859,11 @@ static int kv_dpm_init(struct amdgpu_device *adev)
        pi->voltage_drop_t = 0;
        pi->caps_sclk_throttle_low_notification = false;
        pi->caps_fps = false; /* true? */
-       pi->caps_uvd_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_UVD) ? true : false;
+       pi->caps_uvd_pg = (adev->pg_flags & AMD_PG_SUPPORT_UVD) ? true : false;
        pi->caps_uvd_dpm = true;
-       pi->caps_vce_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_VCE) ? true : false;
-       pi->caps_samu_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_SAMU) ? true : false;
-       pi->caps_acp_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_ACP) ? true : false;
+       pi->caps_vce_pg = (adev->pg_flags & AMD_PG_SUPPORT_VCE) ? true : false;
+       pi->caps_samu_pg = (adev->pg_flags & AMD_PG_SUPPORT_SAMU) ? true : false;
+       pi->caps_acp_pg = (adev->pg_flags & AMD_PG_SUPPORT_ACP) ? true : false;
        pi->caps_stable_p_state = false;
 
        ret = kv_parse_sys_info_table(adev);
index 5e9f73af83a8431b25d6d153132df3a22ce31e31..fbd3767671bb9266d68ac6229a41194aa5a184ac 100644 (file)
@@ -611,7 +611,7 @@ static void uvd_v4_2_enable_mgcg(struct amdgpu_device *adev,
 {
        u32 orig, data;
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG)) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
                data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
                data = 0xfff;
                WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
@@ -830,6 +830,9 @@ static int uvd_v4_2_set_clockgating_state(void *handle,
        bool gate = false;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
+               return 0;
+
        if (state == AMD_CG_STATE_GATE)
                gate = true;
 
@@ -848,7 +851,10 @@ static int uvd_v4_2_set_powergating_state(void *handle,
         * revisit this when there is a cleaner line between
         * the smc and the hw blocks
         */
-        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
+               return 0;
 
        if (state == AMD_PG_STATE_GATE) {
                uvd_v4_2_stop(adev);
index 38864f5629814c7782682b4b8436b67e30aede3a..57f1c5bf3bf19a107c2c35d1b9fb653e2d37ac8d 100644 (file)
@@ -774,6 +774,11 @@ static int uvd_v5_0_process_interrupt(struct amdgpu_device *adev,
 static int uvd_v5_0_set_clockgating_state(void *handle,
                                          enum amd_clockgating_state state)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
+               return 0;
+
        return 0;
 }
 
@@ -789,6 +794,9 @@ static int uvd_v5_0_set_powergating_state(void *handle,
         */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
+               return 0;
+
        if (state == AMD_PG_STATE_GATE) {
                uvd_v5_0_stop(adev);
                return 0;
index 3d5913926436b6b759169575b9e235bc38f0d0df..0b365b7651ffbac65324701a13da702306e27467 100644 (file)
@@ -532,7 +532,7 @@ static int uvd_v6_0_start(struct amdgpu_device *adev)
        uvd_v6_0_mc_resume(adev);
 
        /* Set dynamic clock gating in S/W control mode */
-       if (adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG) {
+       if (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG) {
                if (adev->flags & AMD_IS_APU)
                        cz_set_uvd_clock_gating_branches(adev, false);
                else
@@ -1000,7 +1000,7 @@ static int uvd_v6_0_set_clockgating_state(void *handle,
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
 
-       if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG))
+       if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
                return 0;
 
        if (enable) {
@@ -1030,6 +1030,9 @@ static int uvd_v6_0_set_powergating_state(void *handle,
         */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
+               return 0;
+
        if (state == AMD_PG_STATE_GATE) {
                uvd_v6_0_stop(adev);
                return 0;
index 52ac7a8f1e58b91f3ad0c441b6a175062bddad29..a822edacfa95c979a60cb49eb6e4bb51239e05f0 100644 (file)
@@ -373,7 +373,7 @@ static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
 {
        bool sw_cg = false;
 
-       if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG)) {
+       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) {
                if (sw_cg)
                        vce_v2_0_set_sw_cg(adev, true);
                else
@@ -608,6 +608,9 @@ static int vce_v2_0_set_powergating_state(void *handle,
         */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
+               return 0;
+
        if (state == AMD_PG_STATE_GATE)
                /* XXX do we need a vce_v2_0_stop()? */
                return 0;
index e99af81e4aec3543278c681418138b12feae4c94..d662fa9f9091a33c51eefa8b0ae5d753229e195b 100644 (file)
@@ -277,7 +277,7 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
                WREG32_P(mmVCE_STATUS, 0, ~1);
 
                /* Set Clock-Gating off */
-               if (adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG)
+               if (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)
                        vce_v3_0_set_vce_sw_clock_gating(adev, false);
 
                if (r) {
@@ -676,7 +676,7 @@ static int vce_v3_0_set_clockgating_state(void *handle,
        bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
        int i;
 
-       if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG))
+       if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG))
                return 0;
 
        mutex_lock(&adev->grbm_idx_mutex);
@@ -728,6 +728,9 @@ static int vce_v3_0_set_powergating_state(void *handle,
         */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
+               return 0;
+
        if (state == AMD_PG_STATE_GATE)
                /* XXX do we need a vce_v3_0_stop()? */
                return 0;
index 89f5a1ff6f43aba335945d4f7a2643c0310623f8..0d14d108a6c4adf7a152edcff56cafa4b219cf1a 100644 (file)
@@ -1457,8 +1457,7 @@ static int vi_common_early_init(void *handle)
        case CHIP_STONEY:
                adev->has_uvd = true;
                adev->cg_flags = 0;
-               /* Disable UVD pg */
-               adev->pg_flags = /* AMDGPU_PG_SUPPORT_UVD | */AMDGPU_PG_SUPPORT_VCE;
+               adev->pg_flags = 0;
                adev->external_rev_id = adev->rev_id + 0x1;
                break;
        default:
index 1195d06f55bc491930f434684324a6618f22d087..dbf7e6413cab4207940659b81ceb02095b4ae515 100644 (file)
@@ -85,6 +85,38 @@ enum amd_powergating_state {
        AMD_PG_STATE_UNGATE,
 };
 
+/* CG flags */
+#define AMD_CG_SUPPORT_GFX_MGCG                        (1 << 0)
+#define AMD_CG_SUPPORT_GFX_MGLS                        (1 << 1)
+#define AMD_CG_SUPPORT_GFX_CGCG                        (1 << 2)
+#define AMD_CG_SUPPORT_GFX_CGLS                        (1 << 3)
+#define AMD_CG_SUPPORT_GFX_CGTS                        (1 << 4)
+#define AMD_CG_SUPPORT_GFX_CGTS_LS             (1 << 5)
+#define AMD_CG_SUPPORT_GFX_CP_LS               (1 << 6)
+#define AMD_CG_SUPPORT_GFX_RLC_LS              (1 << 7)
+#define AMD_CG_SUPPORT_MC_LS                   (1 << 8)
+#define AMD_CG_SUPPORT_MC_MGCG                 (1 << 9)
+#define AMD_CG_SUPPORT_SDMA_LS                 (1 << 10)
+#define AMD_CG_SUPPORT_SDMA_MGCG               (1 << 11)
+#define AMD_CG_SUPPORT_BIF_LS                  (1 << 12)
+#define AMD_CG_SUPPORT_UVD_MGCG                        (1 << 13)
+#define AMD_CG_SUPPORT_VCE_MGCG                        (1 << 14)
+#define AMD_CG_SUPPORT_HDP_LS                  (1 << 15)
+#define AMD_CG_SUPPORT_HDP_MGCG                        (1 << 16)
+
+/* PG flags */
+#define AMD_PG_SUPPORT_GFX_PG                  (1 << 0)
+#define AMD_PG_SUPPORT_GFX_SMG                 (1 << 1)
+#define AMD_PG_SUPPORT_GFX_DMG                 (1 << 2)
+#define AMD_PG_SUPPORT_UVD                     (1 << 3)
+#define AMD_PG_SUPPORT_VCE                     (1 << 4)
+#define AMD_PG_SUPPORT_CP                      (1 << 5)
+#define AMD_PG_SUPPORT_GDS                     (1 << 6)
+#define AMD_PG_SUPPORT_RLC_SMU_HS              (1 << 7)
+#define AMD_PG_SUPPORT_SDMA                    (1 << 8)
+#define AMD_PG_SUPPORT_ACP                     (1 << 9)
+#define AMD_PG_SUPPORT_SAMU                    (1 << 10)
+
 enum amd_pm_state_type {
        /* not used for dpm */
        POWER_STATE_TYPE_DEFAULT,
index 713aec95469271e7a678b73ab917f9a49258455e..aec38fc3834f9d867b4477c2f1d1d1166285f1fe 100644 (file)
@@ -109,6 +109,8 @@ enum cgs_system_info_id {
        CGS_SYSTEM_INFO_ADAPTER_BDF_ID = 1,
        CGS_SYSTEM_INFO_PCIE_GEN_INFO,
        CGS_SYSTEM_INFO_PCIE_MLW,
+       CGS_SYSTEM_INFO_CG_FLAGS,
+       CGS_SYSTEM_INFO_PG_FLAGS,
        CGS_SYSTEM_INFO_ID_MAXIMUM,
 };
 
index aa67244a77ae38cf69761bc964c5f1d4400874c5..589599f66fcce851e9ce5b94b2c5617544165022 100644 (file)
@@ -402,8 +402,11 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input,
 
                data.requested_ui_label = power_state_convert(ps);
                ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+               break;
        }
-       break;
+       case AMD_PP_EVENT_COMPLETE_INIT:
+               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+               break;
        default:
                break;
        }
index 83be3cf210e01439c224e78a5681606472d40bfa..6b52c78cb404870ae019b3cd262f7d9711b590b3 100644 (file)
@@ -165,6 +165,7 @@ const struct action_chain resume_action_chain = {
 };
 
 static const pem_event_action *complete_init_event[] = {
+       unblock_adjust_power_state_tasks,
        adjust_power_state_tasks,
        enable_gfx_clock_gating_tasks,
        enable_gfx_voltage_island_power_gating_tasks,
index 52a3efc97f05651bfb0daeaf475d5a4bfadbd43f..46410e3c73493acce741f955f60790fc9745256e 100644 (file)
@@ -31,7 +31,7 @@
 static int pem_init(struct pp_eventmgr *eventmgr)
 {
        int result = 0;
-       struct pem_event_data event_data;
+       struct pem_event_data event_data = { {0} };
 
        /* Initialize PowerPlay feature info */
        pem_init_feature_info(eventmgr);
@@ -52,7 +52,7 @@ static int pem_init(struct pp_eventmgr *eventmgr)
 
 static void pem_fini(struct pp_eventmgr *eventmgr)
 {
-       struct pem_event_data event_data;
+       struct pem_event_data event_data = { {0} };
 
        pem_uninit_featureInfo(eventmgr);
        pem_unregister_interrupts(eventmgr);
index ad7700822a1cb2ee26235bf6bbba9541480ff88e..ff08ce41bde92f82596894ee178a545916d288df 100644 (file)
@@ -226,7 +226,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
                }
        } else {
                cz_dpm_update_vce_dpm(hwmgr);
-               cz_enable_disable_vce_dpm(hwmgr, true);
+               cz_enable_disable_vce_dpm(hwmgr, !bgate);
                return 0;
        }
 
index 0874ab42ee95e7e83d4a027639b97a1a45a35890..cf01177ca3b5e36eb845fe187f13b7135cde03b6 100644 (file)
@@ -174,6 +174,8 @@ static int cz_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
 {
        struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
        uint32_t i;
+       struct cgs_system_info sys_info = {0};
+       int result;
 
        cz_hwmgr->gfx_ramp_step = 256*25/100;
 
@@ -247,6 +249,22 @@ static int cz_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                   PHM_PlatformCaps_DisableVoltageIsland);
 
+       phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+                     PHM_PlatformCaps_UVDPowerGating);
+       phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+                     PHM_PlatformCaps_VCEPowerGating);
+       sys_info.size = sizeof(struct cgs_system_info);
+       sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
+       result = cgs_query_system_info(hwmgr->device, &sys_info);
+       if (!result) {
+               if (sys_info.value & AMD_PG_SUPPORT_UVD)
+                       phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                                     PHM_PlatformCaps_UVDPowerGating);
+               if (sys_info.value & AMD_PG_SUPPORT_VCE)
+                       phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                                     PHM_PlatformCaps_VCEPowerGating);
+       }
+
        return 0;
 }
 
index 44a925006479176617c54a5fa3c33a1eb6b92bad..980d3bf8ea768e161ffbba4cde1b960ea46e7819 100644 (file)
@@ -4451,6 +4451,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
        struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
        phw_tonga_ulv_parm *ulv;
+       struct cgs_system_info sys_info = {0};
 
        PP_ASSERT_WITH_CODE((NULL != hwmgr),
                "Invalid Parameter!", return -1;);
@@ -4615,9 +4616,23 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        data->vddc_phase_shed_control = 0;
 
-       if (0 == result) {
-               struct cgs_system_info sys_info = {0};
+       phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+                     PHM_PlatformCaps_UVDPowerGating);
+       phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+                     PHM_PlatformCaps_VCEPowerGating);
+       sys_info.size = sizeof(struct cgs_system_info);
+       sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
+       result = cgs_query_system_info(hwmgr->device, &sys_info);
+       if (!result) {
+               if (sys_info.value & AMD_PG_SUPPORT_UVD)
+                       phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                                     PHM_PlatformCaps_UVDPowerGating);
+               if (sys_info.value & AMD_PG_SUPPORT_VCE)
+                       phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                                     PHM_PlatformCaps_VCEPowerGating);
+       }
 
+       if (0 == result) {
                data->is_tlu_enabled = 0;
                hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
                        TONGA_MAX_HARDWARE_POWERLEVELS;
index 9759009d1da367cd8b3f264671ea7942aa3ab79a..b1480acbb3c3587c720570031eae9c41498d1d93 100644 (file)
@@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_device *dev)
        } while (ast_read32(ast, 0x10000) != 0x01);
        data = ast_read32(ast, 0x10004);
 
-       if (data & 0x400)
+       if (data & 0x40)
                ast->dram_bus_width = 16;
        else
                ast->dram_bus_width = 32;
index 3f74193885f1ff1df95db09fa76e01174f6353b4..9a7b44616b552920b6ef8f62553bd791d36af935 100644 (file)
@@ -65,8 +65,6 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
         */
        state->allow_modeset = true;
 
-       state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector);
-
        state->crtcs = kcalloc(dev->mode_config.num_crtc,
                               sizeof(*state->crtcs), GFP_KERNEL);
        if (!state->crtcs)
@@ -83,16 +81,6 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
                                      sizeof(*state->plane_states), GFP_KERNEL);
        if (!state->plane_states)
                goto fail;
-       state->connectors = kcalloc(state->num_connector,
-                                   sizeof(*state->connectors),
-                                   GFP_KERNEL);
-       if (!state->connectors)
-               goto fail;
-       state->connector_states = kcalloc(state->num_connector,
-                                         sizeof(*state->connector_states),
-                                         GFP_KERNEL);
-       if (!state->connector_states)
-               goto fail;
 
        state->dev = dev;
 
@@ -823,19 +811,27 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
 
        index = drm_connector_index(connector);
 
-       /*
-        * Construction of atomic state updates can race with a connector
-        * hot-add which might overflow. In this case flip the table and just
-        * restart the entire ioctl - no one is fast enough to livelock a cpu
-        * with physical hotplug events anyway.
-        *
-        * Note that we only grab the indexes once we have the right lock to
-        * prevent hotplug/unplugging of connectors. So removal is no problem,
-        * at most the array is a bit too large.
-        */
        if (index >= state->num_connector) {
-               DRM_DEBUG_ATOMIC("Hot-added connector would overflow state array, restarting\n");
-               return ERR_PTR(-EAGAIN);
+               struct drm_connector **c;
+               struct drm_connector_state **cs;
+               int alloc = max(index + 1, config->num_connector);
+
+               c = krealloc(state->connectors, alloc * sizeof(*state->connectors), GFP_KERNEL);
+               if (!c)
+                       return ERR_PTR(-ENOMEM);
+
+               state->connectors = c;
+               memset(&state->connectors[state->num_connector], 0,
+                      sizeof(*state->connectors) * (alloc - state->num_connector));
+
+               cs = krealloc(state->connector_states, alloc * sizeof(*state->connector_states), GFP_KERNEL);
+               if (!cs)
+                       return ERR_PTR(-ENOMEM);
+
+               state->connector_states = cs;
+               memset(&state->connector_states[state->num_connector], 0,
+                      sizeof(*state->connector_states) * (alloc - state->num_connector));
+               state->num_connector = alloc;
        }
 
        if (state->connector_states[index])
index 7c523060a076f715746829004657b227a9308640..4f2d3e161593057bfff2b046c1b1f30a3cc90d41 100644 (file)
@@ -1493,7 +1493,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev,
 {
        int i;
 
-       for (i = 0; i < dev->mode_config.num_connector; i++) {
+       for (i = 0; i < state->num_connector; i++) {
                struct drm_connector *connector = state->connectors[i];
 
                if (!connector)
index d40bab29747edb0ea989afd81b0e5b5102dfb555..f6191215b2cbc97c11fbfda5eeadb9f61b2387e8 100644 (file)
@@ -918,12 +918,19 @@ int drm_connector_init(struct drm_device *dev,
        connector->base.properties = &connector->properties;
        connector->dev = dev;
        connector->funcs = funcs;
+
+       connector->connector_id = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL);
+       if (connector->connector_id < 0) {
+               ret = connector->connector_id;
+               goto out_put;
+       }
+
        connector->connector_type = connector_type;
        connector->connector_type_id =
                ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
        if (connector->connector_type_id < 0) {
                ret = connector->connector_type_id;
-               goto out_put;
+               goto out_put_id;
        }
        connector->name =
                kasprintf(GFP_KERNEL, "%s-%d",
@@ -931,7 +938,7 @@ int drm_connector_init(struct drm_device *dev,
                          connector->connector_type_id);
        if (!connector->name) {
                ret = -ENOMEM;
-               goto out_put;
+               goto out_put_type_id;
        }
 
        INIT_LIST_HEAD(&connector->probed_modes);
@@ -959,7 +966,12 @@ int drm_connector_init(struct drm_device *dev,
        }
 
        connector->debugfs_entry = NULL;
-
+out_put_type_id:
+       if (ret)
+               ida_remove(connector_ida, connector->connector_type_id);
+out_put_id:
+       if (ret)
+               ida_remove(&config->connector_ida, connector->connector_id);
 out_put:
        if (ret)
                drm_mode_object_put(dev, &connector->base);
@@ -996,6 +1008,9 @@ void drm_connector_cleanup(struct drm_connector *connector)
        ida_remove(&drm_connector_enum_list[connector->connector_type].ida,
                   connector->connector_type_id);
 
+       ida_remove(&dev->mode_config.connector_ida,
+                  connector->connector_id);
+
        kfree(connector->display_info.bus_formats);
        drm_mode_object_put(dev, &connector->base);
        kfree(connector->name);
@@ -1012,32 +1027,6 @@ void drm_connector_cleanup(struct drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
 
-/**
- * drm_connector_index - find the index of a registered connector
- * @connector: connector to find index for
- *
- * Given a registered connector, return the index of that connector within a DRM
- * device's list of connectors.
- */
-unsigned int drm_connector_index(struct drm_connector *connector)
-{
-       unsigned int index = 0;
-       struct drm_connector *tmp;
-       struct drm_mode_config *config = &connector->dev->mode_config;
-
-       WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
-
-       drm_for_each_connector(tmp, connector->dev) {
-               if (tmp == connector)
-                       return index;
-
-               index++;
-       }
-
-       BUG();
-}
-EXPORT_SYMBOL(drm_connector_index);
-
 /**
  * drm_connector_register - register a connector
  * @connector: the connector to register
@@ -5789,6 +5778,7 @@ void drm_mode_config_init(struct drm_device *dev)
        INIT_LIST_HEAD(&dev->mode_config.plane_list);
        idr_init(&dev->mode_config.crtc_idr);
        idr_init(&dev->mode_config.tile_idr);
+       ida_init(&dev->mode_config.connector_ida);
 
        drm_modeset_lock_all(dev);
        drm_mode_create_standard_properties(dev);
@@ -5869,6 +5859,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
                crtc->funcs->destroy(crtc);
        }
 
+       ida_destroy(&dev->mode_config.connector_ida);
        idr_destroy(&dev->mode_config.tile_idr);
        idr_destroy(&dev->mode_config.crtc_idr);
        drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
index 8ae13de272c43a7f79822098318a5c5317b54483..27fbd79d0daf0003be2014cee00c9dcdb49fdb43 100644 (file)
@@ -1159,11 +1159,13 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                        drm_dp_put_port(port);
                        goto out;
                }
-
-               drm_mode_connector_set_tile_property(port->connector);
-
+               if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
+                       port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+                       drm_mode_connector_set_tile_property(port->connector);
+               }
                (*mstb->mgr->cbs->register_connector)(port->connector);
        }
+
 out:
        /* put reference to this port */
        drm_dp_put_port(port);
@@ -1188,8 +1190,8 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
        port->ddps = conn_stat->displayport_device_plug_status;
 
        if (old_ddps != port->ddps) {
-               dowork = true;
                if (port->ddps) {
+                       dowork = true;
                } else {
                        port->available_pbn = 0;
                }
@@ -1294,13 +1296,8 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
                if (port->input)
                        continue;
 
-               if (!port->ddps) {
-                       if (port->cached_edid) {
-                               kfree(port->cached_edid);
-                               port->cached_edid = NULL;
-                       }
+               if (!port->ddps)
                        continue;
-               }
 
                if (!port->available_pbn)
                        drm_dp_send_enum_path_resources(mgr, mstb, port);
@@ -1311,12 +1308,6 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
                                drm_dp_check_and_send_link_address(mgr, mstb_child);
                                drm_dp_put_mst_branch_device(mstb_child);
                        }
-               } else if (port->pdt == DP_PEER_DEVICE_SST_SINK ||
-                       port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) {
-                       if (!port->cached_edid) {
-                               port->cached_edid =
-                                       drm_get_edid(port->connector, &port->aux.ddc);
-                       }
                }
        }
 }
@@ -1336,8 +1327,6 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work)
                drm_dp_check_and_send_link_address(mgr, mstb);
                drm_dp_put_mst_branch_device(mstb);
        }
-
-       (*mgr->cbs->hotplug)(mgr);
 }
 
 static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
@@ -1597,6 +1586,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
                        for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
                                drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
                        }
+                       (*mgr->cbs->hotplug)(mgr);
                }
        } else {
                mstb->link_address_sent = false;
@@ -2293,6 +2283,8 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
                        drm_dp_update_port(mstb, &msg.u.conn_stat);
 
                        DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
+                       (*mgr->cbs->hotplug)(mgr);
+
                } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
                        drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
                        if (!mstb)
@@ -2379,6 +2371,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector
 
        case DP_PEER_DEVICE_SST_SINK:
                status = connector_status_connected;
+               /* for logical ports - cache the EDID */
+               if (port->port_num >= 8 && !port->cached_edid) {
+                       port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
+               }
                break;
        case DP_PEER_DEVICE_DP_LEGACY_CONV:
                if (port->ldps)
@@ -2433,7 +2429,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
 
        if (port->cached_edid)
                edid = drm_edid_duplicate(port->cached_edid);
-
+       else {
+               edid = drm_get_edid(connector, &port->aux.ddc);
+               drm_mode_connector_set_tile_property(connector);
+       }
        port->has_audio = drm_detect_monitor_audio(edid);
        drm_dp_put_port(port);
        return edid;
index d12a4efa651b015179f776e1fc056da96dc1faf0..1fe14579e8c941b002c5362f7c69936c85cf855b 100644 (file)
@@ -224,6 +224,64 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
                diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0;
        }
 
+       /*
+        * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
+        * interval? If so then vblank irqs keep running and it will likely
+        * happen that the hardware vblank counter is not trustworthy as it
+        * might reset at some point in that interval and vblank timestamps
+        * are not trustworthy either in that interval. Iow. this can result
+        * in a bogus diff >> 1 which must be avoided as it would cause
+        * random large forward jumps of the software vblank counter.
+        */
+       if (diff > 1 && (vblank->inmodeset & 0x2)) {
+               DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u"
+                             " due to pre-modeset.\n", pipe, diff);
+               diff = 1;
+       }
+
+       /*
+        * FIMXE: Need to replace this hack with proper seqlocks.
+        *
+        * Restrict the bump of the software vblank counter to a safe maximum
+        * value of +1 whenever there is the possibility that concurrent readers
+        * of vblank timestamps could be active at the moment, as the current
+        * implementation of the timestamp caching and updating is not safe
+        * against concurrent readers for calls to store_vblank() with a bump
+        * of anything but +1. A bump != 1 would very likely return corrupted
+        * timestamps to userspace, because the same slot in the cache could
+        * be concurrently written by store_vblank() and read by one of those
+        * readers without the read-retry logic detecting the collision.
+        *
+        * Concurrent readers can exist when we are called from the
+        * drm_vblank_off() or drm_vblank_on() functions and other non-vblank-
+        * irq callers. However, all those calls to us are happening with the
+        * vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount
+        * can't increase while we are executing. Therefore a zero refcount at
+        * this point is safe for arbitrary counter bumps if we are called
+        * outside vblank irq, a non-zero count is not 100% safe. Unfortunately
+        * we must also accept a refcount of 1, as whenever we are called from
+        * drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and
+        * we must let that one pass through in order to not lose vblank counts
+        * during vblank irq off - which would completely defeat the whole
+        * point of this routine.
+        *
+        * Whenever we are called from vblank irq, we have to assume concurrent
+        * readers exist or can show up any time during our execution, even if
+        * the refcount is currently zero, as vblank irqs are usually only
+        * enabled due to the presence of readers, and because when we are called
+        * from vblank irq we can't hold the vbl_lock to protect us from sudden
+        * bumps in vblank refcount. Therefore also restrict bumps to +1 when
+        * called from vblank irq.
+        */
+       if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 ||
+           (flags & DRM_CALLED_FROM_VBLIRQ))) {
+               DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u "
+                             "refcount %u, vblirq %u\n", pipe, diff,
+                             atomic_read(&vblank->refcount),
+                             (flags & DRM_CALLED_FROM_VBLIRQ) != 0);
+               diff = 1;
+       }
+
        DRM_DEBUG_VBL("updating vblank count on crtc %u:"
                      " current=%u, diff=%u, hw=%u hw_last=%u\n",
                      pipe, vblank->count, diff, cur_vblank, vblank->last);
@@ -1316,7 +1374,13 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
        spin_lock_irqsave(&dev->event_lock, irqflags);
 
        spin_lock(&dev->vbl_lock);
-       vblank_disable_and_save(dev, pipe);
+       DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
+                     pipe, vblank->enabled, vblank->inmodeset);
+
+       /* Avoid redundant vblank disables without previous drm_vblank_on(). */
+       if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
+               vblank_disable_and_save(dev, pipe);
+
        wake_up(&vblank->queue);
 
        /*
@@ -1418,6 +1482,9 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
                return;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
+                     pipe, vblank->enabled, vblank->inmodeset);
+
        /* Drop our private "prevent drm_vblank_get" refcount */
        if (vblank->inmodeset) {
                atomic_dec(&vblank->refcount);
@@ -1430,8 +1497,7 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
         * re-enable interrupts if there are users left, or the
         * user wishes vblank interrupts to be enabled all the time.
         */
-       if (atomic_read(&vblank->refcount) != 0 ||
-           (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
+       if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
                WARN_ON(drm_vblank_enable(dev, pipe));
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
@@ -1526,6 +1592,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
        if (vblank->inmodeset) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                dev->vblank_disable_allowed = true;
+               drm_reset_vblank_timestamp(dev, pipe);
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
                if (vblank->inmodeset & 0x2)
index 83efca941388a73874a8da10412c77d9bc3801e4..f17d3927959604301e9e53c7614fcb1e4982e80c 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC EXYNOS Series"
-       depends on OF && DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
+       depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
        select DRM_KMS_HELPER
        select DRM_KMS_FB_HELPER
        select FB_CFB_FILLRECT
index 1bf6a21130c7cbde6088dbb70e2a2b650f244b06..162ab93e99cb519e20963066c2285d50b6f08b88 100644 (file)
@@ -93,7 +93,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)
        if (test_bit(BIT_SUSPENDED, &ctx->flags))
                return -EPERM;
 
-       if (test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
+       if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
                val = VIDINTCON0_INTEN;
                if (ctx->out_type == IFTYPE_I80)
                        val |= VIDINTCON0_FRAMEDONE;
@@ -402,8 +402,6 @@ static void decon_enable(struct exynos_drm_crtc *crtc)
                decon_enable_vblank(ctx->crtc);
 
        decon_commit(ctx->crtc);
-
-       set_bit(BIT_SUSPENDED, &ctx->flags);
 }
 
 static void decon_disable(struct exynos_drm_crtc *crtc)
@@ -582,9 +580,9 @@ out:
 static int exynos5433_decon_suspend(struct device *dev)
 {
        struct decon_context *ctx = dev_get_drvdata(dev);
-       int i;
+       int i = ARRAY_SIZE(decon_clks_name);
 
-       for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++)
+       while (--i >= 0)
                clk_disable_unprepare(ctx->clks[i]);
 
        return 0;
index e977a81af2e67d91101e644b393d8ce1393b3fc8..26e81d191f56eaa8b63f9755f9542dac034c9096 100644 (file)
@@ -1782,6 +1782,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 
        bridge = of_drm_find_bridge(dsi->bridge_node);
        if (bridge) {
+               encoder->bridge = bridge;
                drm_bridge_attach(drm_dev, bridge);
        }
 
index f6118baa8e3efad8732f8297ab6f6529d763171e..8baabd813ff55a1d713b0bdbf11386c135878d9a 100644 (file)
@@ -50,7 +50,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
        if (vm_size > exynos_gem->size)
                return -EINVAL;
 
-       ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->pages,
+       ret = dma_mmap_attrs(helper->dev->dev, vma, exynos_gem->cookie,
                             exynos_gem->dma_addr, exynos_gem->size,
                             &exynos_gem->dma_attrs);
        if (ret < 0) {
index c747824f3c98551bf2883a7659249a840359de62..8a4f4a0211d0dd57001f2605a4815dae06686b9f 100644 (file)
@@ -1723,7 +1723,7 @@ static int fimc_probe(struct platform_device *pdev)
                goto err_put_clk;
        }
 
-       DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
+       DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
 
        spin_lock_init(&ctx->lock);
        platform_set_drvdata(pdev, ctx);
index c17efdb238a6e24f6fcecac58c395b8964b12703..8dfe6e113a883b315419755b75c5b01159c60373 100644 (file)
@@ -1166,7 +1166,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
                goto err_free_event;
        }
 
-       cmd = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd;
+       cmd = (struct drm_exynos_g2d_cmd *)(unsigned long)req->cmd;
 
        if (copy_from_user(cmdlist->data + cmdlist->last,
                                (void __user *)cmd,
@@ -1184,7 +1184,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
        if (req->cmd_buf_nr) {
                struct drm_exynos_g2d_cmd *cmd_buf;
 
-               cmd_buf = (struct drm_exynos_g2d_cmd *)(uint32_t)req->cmd_buf;
+               cmd_buf = (struct drm_exynos_g2d_cmd *)
+                               (unsigned long)req->cmd_buf;
 
                if (copy_from_user(cmdlist->data + cmdlist->last,
                                        (void __user *)cmd_buf,
index 32358c5e3db4be25e7127225fa86e343b97757c7..26b5e4bd55b6afd8f1cb042da863e90a5ee6ef8c 100644 (file)
@@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
                return ERR_PTR(ret);
        }
 
-       DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
+       DRM_DEBUG_KMS("created file object = %p\n", obj->filp);
 
        return exynos_gem;
 }
@@ -335,7 +335,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
        if (vm_size > exynos_gem->size)
                return -EINVAL;
 
-       ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->pages,
+       ret = dma_mmap_attrs(drm_dev->dev, vma, exynos_gem->cookie,
                             exynos_gem->dma_addr, exynos_gem->size,
                             &exynos_gem->dma_attrs);
        if (ret < 0) {
index 7aecd23cfa11a6638d783366b890fd33a9c0ea2e..5d20da8f957e2eac724331bb866f7c1b96244087 100644 (file)
@@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
+       DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
 
        mutex_init(&ctx->lock);
        platform_set_drvdata(pdev, ctx);
index 67d24236e745c4dd1cc014ba0c5386784d3441f8..95eeb9116f102a931313eaea212e1e0aa4f89a18 100644 (file)
@@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
         * e.g PAUSE state, queue buf, command control.
         */
        list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
-               DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", count++, (int)ippdrv);
+               DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", count++, ippdrv);
 
                mutex_lock(&ippdrv->cmd_lock);
                list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
@@ -388,8 +388,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
        }
        property->prop_id = ret;
 
-       DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
-               property->prop_id, property->cmd, (int)ippdrv);
+       DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%p]\n",
+               property->prop_id, property->cmd, ippdrv);
 
        /* stored property information and ippdrv in private data */
        c_node->property = *property;
@@ -518,7 +518,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
 {
        int i;
 
-       DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
+       DRM_DEBUG_KMS("node[%p]\n", m_node);
 
        if (!m_node) {
                DRM_ERROR("invalid dequeue node.\n");
@@ -562,7 +562,7 @@ static struct drm_exynos_ipp_mem_node
        m_node->buf_id = qbuf->buf_id;
        INIT_LIST_HEAD(&m_node->list);
 
-       DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id);
+       DRM_DEBUG_KMS("m_node[%p]ops_id[%d]\n", m_node, qbuf->ops_id);
        DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);
 
        for_each_ipp_planar(i) {
@@ -582,8 +582,8 @@ static struct drm_exynos_ipp_mem_node
 
                        buf_info->handles[i] = qbuf->handle[i];
                        buf_info->base[i] = *addr;
-                       DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i,
-                                     buf_info->base[i], buf_info->handles[i]);
+                       DRM_DEBUG_KMS("i[%d]base[%pad]hd[0x%lx]\n", i,
+                                     &buf_info->base[i], buf_info->handles[i]);
                }
        }
 
@@ -664,7 +664,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
 
        mutex_lock(&c_node->event_lock);
        list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
-               DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e);
+               DRM_DEBUG_KMS("count[%d]e[%p]\n", count++, e);
 
                /*
                 * qbuf == NULL condition means all event deletion.
@@ -755,7 +755,7 @@ static struct drm_exynos_ipp_mem_node
 
        /* find memory node from memory list */
        list_for_each_entry(m_node, head, list) {
-               DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node);
+               DRM_DEBUG_KMS("count[%d]m_node[%p]\n", count++, m_node);
 
                /* compare buffer id */
                if (m_node->buf_id == qbuf->buf_id)
@@ -772,7 +772,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
        struct exynos_drm_ipp_ops *ops = NULL;
        int ret = 0;
 
-       DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
+       DRM_DEBUG_KMS("node[%p]\n", m_node);
 
        if (!m_node) {
                DRM_ERROR("invalid queue node.\n");
@@ -1237,7 +1237,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
                        m_node = list_first_entry(head,
                                struct drm_exynos_ipp_mem_node, list);
 
-                       DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node);
+                       DRM_DEBUG_KMS("m_node[%p]\n", m_node);
 
                        ret = ipp_set_mem_node(ippdrv, c_node, m_node);
                        if (ret) {
@@ -1610,8 +1610,8 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
                }
                ippdrv->prop_list.ipp_id = ret;
 
-               DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n",
-                       count++, (int)ippdrv, ret);
+               DRM_DEBUG_KMS("count[%d]ippdrv[%p]ipp_id[%d]\n",
+                       count++, ippdrv, ret);
 
                /* store parent device for node */
                ippdrv->parent_dev = dev;
@@ -1668,7 +1668,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
 
        file_priv->ipp_dev = dev;
 
-       DRM_DEBUG_KMS("done priv[0x%x]\n", (int)dev);
+       DRM_DEBUG_KMS("done priv[%p]\n", dev);
 
        return 0;
 }
@@ -1685,8 +1685,8 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
                mutex_lock(&ippdrv->cmd_lock);
                list_for_each_entry_safe(c_node, tc_node,
                        &ippdrv->cmd_list, list) {
-                       DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n",
-                               count++, (int)ippdrv);
+                       DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n",
+                               count++, ippdrv);
 
                        if (c_node->filp == file) {
                                /*
index 4eaef36aec5a42d9d1ccd70ff4f15f39d707648c..9869d70e9e54af32abb775dc0e17f0c1da83999b 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/of_graph.h>
 #include <linux/clk.h>
+#include <linux/component.h>
 #include <drm/drmP.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
@@ -306,9 +307,9 @@ exit:
        return ret;
 }
 
-void mic_disable(struct drm_bridge *bridge) { }
+static void mic_disable(struct drm_bridge *bridge) { }
 
-void mic_post_disable(struct drm_bridge *bridge)
+static void mic_post_disable(struct drm_bridge *bridge)
 {
        struct exynos_mic *mic = bridge->driver_private;
        int i;
@@ -328,7 +329,7 @@ already_disabled:
        mutex_unlock(&mic_mutex);
 }
 
-void mic_pre_enable(struct drm_bridge *bridge)
+static void mic_pre_enable(struct drm_bridge *bridge)
 {
        struct exynos_mic *mic = bridge->driver_private;
        int ret, i;
@@ -371,11 +372,35 @@ already_enabled:
        mutex_unlock(&mic_mutex);
 }
 
-void mic_enable(struct drm_bridge *bridge) { }
+static void mic_enable(struct drm_bridge *bridge) { }
 
-void mic_destroy(struct drm_bridge *bridge)
+static const struct drm_bridge_funcs mic_bridge_funcs = {
+       .disable = mic_disable,
+       .post_disable = mic_post_disable,
+       .pre_enable = mic_pre_enable,
+       .enable = mic_enable,
+};
+
+static int exynos_mic_bind(struct device *dev, struct device *master,
+                          void *data)
 {
-       struct exynos_mic *mic = bridge->driver_private;
+       struct exynos_mic *mic = dev_get_drvdata(dev);
+       int ret;
+
+       mic->bridge.funcs = &mic_bridge_funcs;
+       mic->bridge.of_node = dev->of_node;
+       mic->bridge.driver_private = mic;
+       ret = drm_bridge_add(&mic->bridge);
+       if (ret)
+               DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
+
+       return ret;
+}
+
+static void exynos_mic_unbind(struct device *dev, struct device *master,
+                             void *data)
+{
+       struct exynos_mic *mic = dev_get_drvdata(dev);
        int i;
 
        mutex_lock(&mic_mutex);
@@ -387,16 +412,16 @@ void mic_destroy(struct drm_bridge *bridge)
 
 already_disabled:
        mutex_unlock(&mic_mutex);
+
+       drm_bridge_remove(&mic->bridge);
 }
 
-static const struct drm_bridge_funcs mic_bridge_funcs = {
-       .disable = mic_disable,
-       .post_disable = mic_post_disable,
-       .pre_enable = mic_pre_enable,
-       .enable = mic_enable,
+static const struct component_ops exynos_mic_component_ops = {
+       .bind   = exynos_mic_bind,
+       .unbind = exynos_mic_unbind,
 };
 
-int exynos_mic_probe(struct platform_device *pdev)
+static int exynos_mic_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct exynos_mic *mic;
@@ -435,17 +460,8 @@ int exynos_mic_probe(struct platform_device *pdev)
                goto err;
        }
 
-       mic->bridge.funcs = &mic_bridge_funcs;
-       mic->bridge.of_node = dev->of_node;
-       mic->bridge.driver_private = mic;
-       ret = drm_bridge_add(&mic->bridge);
-       if (ret) {
-               DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
-               goto err;
-       }
-
        for (i = 0; i < NUM_CLKS; i++) {
-               mic->clks[i] = of_clk_get_by_name(dev->of_node, clk_names[i]);
+               mic->clks[i] = devm_clk_get(dev, clk_names[i]);
                if (IS_ERR(mic->clks[i])) {
                        DRM_ERROR("mic: Failed to get clock (%s)\n",
                                                                clk_names[i]);
@@ -454,7 +470,10 @@ int exynos_mic_probe(struct platform_device *pdev)
                }
        }
 
+       platform_set_drvdata(pdev, mic);
+
        DRM_DEBUG_KMS("MIC has been probed\n");
+       return component_add(dev, &exynos_mic_component_ops);
 
 err:
        return ret;
@@ -462,14 +481,7 @@ err:
 
 static int exynos_mic_remove(struct platform_device *pdev)
 {
-       struct exynos_mic *mic = platform_get_drvdata(pdev);
-       int i;
-
-       drm_bridge_remove(&mic->bridge);
-
-       for (i = NUM_CLKS - 1; i > -1; i--)
-               clk_put(mic->clks[i]);
-
+       component_del(&pdev->dev, &exynos_mic_component_ops);
        return 0;
 }
 
index bea0f7826d30a168022c79598c9cea6f4641afcd..ce59f4443394f5394c85956e2e261dc62eaedf43 100644 (file)
@@ -754,7 +754,7 @@ static int rotator_probe(struct platform_device *pdev)
                goto err_ippdrv_register;
        }
 
-       DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv);
+       DRM_DEBUG_KMS("ippdrv[%p]\n", ippdrv);
 
        platform_set_drvdata(pdev, rot);
 
index 62ac4e5fa51dbb00cda1f02d50f630b48b6d44bc..b605bd7395eccf2e3a6fb8264c37bd31774b1634 100644 (file)
@@ -223,7 +223,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
        }
 }
 
-static int vidi_show_connection(struct device *dev,
+static ssize_t vidi_show_connection(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        struct vidi_context *ctx = dev_get_drvdata(dev);
@@ -238,7 +238,7 @@ static int vidi_show_connection(struct device *dev,
        return rc;
 }
 
-static int vidi_store_connection(struct device *dev,
+static ssize_t vidi_store_connection(struct device *dev,
                                struct device_attribute *attr,
                                const char *buf, size_t len)
 {
@@ -294,7 +294,9 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
        }
 
        if (vidi->connection) {
-               struct edid *raw_edid  = (struct edid *)(uint32_t)vidi->edid;
+               struct edid *raw_edid;
+
+               raw_edid = (struct edid *)(unsigned long)vidi->edid;
                if (!drm_edid_is_valid(raw_edid)) {
                        DRM_DEBUG_KMS("edid data is invalid.\n");
                        return -EINVAL;
index 0fc38bb7276c26920b372ca52c053eba504aa722..cf39ed3133d63aaa434120dc085bd6ea0811b2ee 100644 (file)
@@ -825,8 +825,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                }
 
                for_each_pipe(dev_priv, pipe) {
-                       if (!intel_display_power_is_enabled(dev_priv,
-                                               POWER_DOMAIN_PIPE(pipe))) {
+                       enum intel_display_power_domain power_domain;
+
+                       power_domain = POWER_DOMAIN_PIPE(pipe);
+                       if (!intel_display_power_get_if_enabled(dev_priv,
+                                                               power_domain)) {
                                seq_printf(m, "Pipe %c power disabled\n",
                                           pipe_name(pipe));
                                continue;
@@ -840,6 +843,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                        seq_printf(m, "Pipe %c IER:\t%08x\n",
                                   pipe_name(pipe),
                                   I915_READ(GEN8_DE_PIPE_IER(pipe)));
+
+                       intel_display_power_put(dev_priv, power_domain);
                }
 
                seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
@@ -3985,6 +3990,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
        struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev,
                                                                        pipe));
+       enum intel_display_power_domain power_domain;
        u32 val = 0; /* shut up gcc */
        int ret;
 
@@ -3995,7 +4001,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
        if (pipe_crc->source && source)
                return -EINVAL;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) {
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
                DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
                return -EIO;
        }
@@ -4012,7 +4019,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
                ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
 
        if (ret != 0)
-               return ret;
+               goto out;
 
        /* none -> real source transition */
        if (source) {
@@ -4024,8 +4031,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
                entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR,
                                  sizeof(pipe_crc->entries[0]),
                                  GFP_KERNEL);
-               if (!entries)
-                       return -ENOMEM;
+               if (!entries) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
 
                /*
                 * When IPS gets enabled, the pipe CRC changes. Since IPS gets
@@ -4081,7 +4090,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
                hsw_enable_ips(crtc);
        }
 
-       return 0;
+       ret = 0;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 /*
index f0f75d7c0d94263f86ccfdd7d8b84af831462be0..b0847b9155452366569a4676c9da62bc6c2bc94d 100644 (file)
@@ -751,6 +751,7 @@ struct intel_csr {
        uint32_t mmio_count;
        i915_reg_t mmioaddr[8];
        uint32_t mmiodata[8];
+       uint32_t dc_state;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -1988,6 +1989,9 @@ enum hdmi_force_audio {
 #define I915_GTT_OFFSET_NONE ((u32)-1)
 
 struct drm_i915_gem_object_ops {
+       unsigned int flags;
+#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
+
        /* Interface between the GEM object and its backing storage.
         * get_pages() is called once prior to the use of the associated set
         * of pages before to binding them into the GTT, and put_pages() is
@@ -2003,6 +2007,7 @@ struct drm_i915_gem_object_ops {
         */
        int (*get_pages)(struct drm_i915_gem_object *);
        void (*put_pages)(struct drm_i915_gem_object *);
+
        int (*dmabuf_export)(struct drm_i915_gem_object *);
        void (*release)(struct drm_i915_gem_object *);
 };
index ddc21d4b388d2419a63fbd4f4a5745deea80957b..bb44bad15403556fb443998852864d8e0fb83472 100644 (file)
@@ -4425,6 +4425,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 }
 
 static const struct drm_i915_gem_object_ops i915_gem_object_ops = {
+       .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE,
        .get_pages = i915_gem_object_get_pages_gtt,
        .put_pages = i915_gem_object_put_pages_gtt,
 };
@@ -5261,7 +5262,7 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
        struct page *page;
 
        /* Only default objects have per-page dirty tracking */
-       if (WARN_ON(obj->ops != &i915_gem_object_ops))
+       if (WARN_ON((obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE) == 0))
                return NULL;
 
        page = i915_gem_object_get_page(obj, n);
index 19fb0bddc1cddfce0804e459319dc11ba96c5ab7..59e45b3a69379a0e892fbd85d7a17ba3f85913eb 100644 (file)
@@ -789,9 +789,10 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj)
 }
 
 static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
-       .dmabuf_export = i915_gem_userptr_dmabuf_export,
+       .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE,
        .get_pages = i915_gem_userptr_get_pages,
        .put_pages = i915_gem_userptr_put_pages,
+       .dmabuf_export = i915_gem_userptr_dmabuf_export,
        .release = i915_gem_userptr_release,
 };
 
index 007ae83a4086d65ff7e4d3862f2ad2a035c74540..4897728713f698d1b3fdbbd31cbf473524c4ecd1 100644 (file)
@@ -3287,19 +3287,20 @@ enum skl_disp_power_wells {
 
 #define PORT_HOTPLUG_STAT      _MMIO(dev_priv->info.display_mmio_offset + 0x61114)
 /*
- * HDMI/DP bits are gen4+
+ * HDMI/DP bits are g4x+
  *
  * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused.
  * Please check the detailed lore in the commit message for for experimental
  * evidence.
  */
-#define   PORTD_HOTPLUG_LIVE_STATUS_G4X                (1 << 29)
+/* Bspec says GM45 should match G4X/VLV/CHV, but reality disagrees */
+#define   PORTD_HOTPLUG_LIVE_STATUS_GM45       (1 << 29)
+#define   PORTC_HOTPLUG_LIVE_STATUS_GM45       (1 << 28)
+#define   PORTB_HOTPLUG_LIVE_STATUS_GM45       (1 << 27)
+/* G4X/VLV/CHV DP/HDMI bits again match Bspec */
+#define   PORTD_HOTPLUG_LIVE_STATUS_G4X                (1 << 27)
 #define   PORTC_HOTPLUG_LIVE_STATUS_G4X                (1 << 28)
-#define   PORTB_HOTPLUG_LIVE_STATUS_G4X                (1 << 27)
-/* VLV DP/HDMI bits again match Bspec */
-#define   PORTD_HOTPLUG_LIVE_STATUS_VLV                (1 << 27)
-#define   PORTC_HOTPLUG_LIVE_STATUS_VLV                (1 << 28)
-#define   PORTB_HOTPLUG_LIVE_STATUS_VLV                (1 << 29)
+#define   PORTB_HOTPLUG_LIVE_STATUS_G4X                (1 << 29)
 #define   PORTD_HOTPLUG_INT_STATUS             (3 << 21)
 #define   PORTD_HOTPLUG_INT_LONG_PULSE         (2 << 21)
 #define   PORTD_HOTPLUG_INT_SHORT_PULSE                (1 << 21)
@@ -7514,7 +7515,7 @@ enum skl_disp_power_wells {
 #define  DPLL_CFGCR2_PDIV_7 (4<<2)
 #define  DPLL_CFGCR2_CENTRAL_FREQ_MASK (3)
 
-#define DPLL_CFGCR1(id)        _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR2)
+#define DPLL_CFGCR1(id)        _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR1, _DPLL2_CFGCR1)
 #define DPLL_CFGCR2(id)        _MMIO_PIPE((id) - SKL_DPLL1, _DPLL1_CFGCR2, _DPLL2_CFGCR2)
 
 /* BXT display engine PLL */
index a2aa09ce3202f3ca72e64f550244e2a2c8e8a29f..a8af594fbd0097ba066071710a4832c3b731474e 100644 (file)
@@ -49,7 +49,7 @@ static void i915_save_display(struct drm_device *dev)
                dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
                dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
                dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
-       } else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+       } else if (INTEL_INFO(dev)->gen <= 4) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
                dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
@@ -84,7 +84,7 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
                I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
                I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
-       } else if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+       } else if (INTEL_INFO(dev)->gen <= 4) {
                I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
                I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
index 9c89df1af036de613d71a5e8fccc83050722a088..a7b4a524faddc8a80c6693c89eee98efa3fc4450 100644 (file)
@@ -71,22 +71,29 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
        struct intel_crt *crt = intel_encoder_to_crt(encoder);
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(crt->adpa_reg);
 
        if (!(tmp & ADPA_DAC_ENABLE))
-               return false;
+               goto out;
 
        if (HAS_PCH_CPT(dev))
                *pipe = PORT_TO_PIPE_CPT(tmp);
        else
                *pipe = PORT_TO_PIPE(tmp);
 
-       return true;
+       ret = true;
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
index 9bb63a85997a4ffbf31da0e8dbd211786f2e626c..647d85e77c2f4700e84bc275efb711f9b2dc2363 100644 (file)
@@ -240,6 +240,8 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv)
                I915_WRITE(dev_priv->csr.mmioaddr[i],
                           dev_priv->csr.mmiodata[i]);
        }
+
+       dev_priv->csr.dc_state = 0;
 }
 
 static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
index e6408e5583d7a88af4511c6ec2334db2b7922555..0f3df2c39f7cdd3a69d8f0044cbd725e3b9bac6d 100644 (file)
@@ -1589,7 +1589,8 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
                         DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
                         DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
                         wrpll_params.central_freq;
-       } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
+       } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+                  intel_encoder->type == INTEL_OUTPUT_DP_MST) {
                switch (crtc_state->port_clock / 2) {
                case 81000:
                        ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
@@ -1968,13 +1969,16 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
        enum transcoder cpu_transcoder;
        enum intel_display_power_domain power_domain;
        uint32_t tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(intel_encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
-       if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
-               return false;
+       if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) {
+               ret = false;
+               goto out;
+       }
 
        if (port == PORT_A)
                cpu_transcoder = TRANSCODER_EDP;
@@ -1986,23 +1990,33 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
        switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
        case TRANS_DDI_MODE_SELECT_HDMI:
        case TRANS_DDI_MODE_SELECT_DVI:
-               return (type == DRM_MODE_CONNECTOR_HDMIA);
+               ret = type == DRM_MODE_CONNECTOR_HDMIA;
+               break;
 
        case TRANS_DDI_MODE_SELECT_DP_SST:
-               if (type == DRM_MODE_CONNECTOR_eDP)
-                       return true;
-               return (type == DRM_MODE_CONNECTOR_DisplayPort);
+               ret = type == DRM_MODE_CONNECTOR_eDP ||
+                     type == DRM_MODE_CONNECTOR_DisplayPort;
+               break;
+
        case TRANS_DDI_MODE_SELECT_DP_MST:
                /* if the transcoder is in MST state then
                 * connector isn't connected */
-               return false;
+               ret = false;
+               break;
 
        case TRANS_DDI_MODE_SELECT_FDI:
-               return (type == DRM_MODE_CONNECTOR_VGA);
+               ret = type == DRM_MODE_CONNECTOR_VGA;
+               break;
 
        default:
-               return false;
+               ret = false;
+               break;
        }
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
@@ -2014,15 +2028,18 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
        enum intel_display_power_domain power_domain;
        u32 tmp;
        int i;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(DDI_BUF_CTL(port));
 
        if (!(tmp & DDI_BUF_CTL_ENABLE))
-               return false;
+               goto out;
 
        if (port == PORT_A) {
                tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
@@ -2040,25 +2057,32 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
                        break;
                }
 
-               return true;
-       } else {
-               for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
-                       tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
+               ret = true;
 
-                       if ((tmp & TRANS_DDI_PORT_MASK)
-                           == TRANS_DDI_SELECT_PORT(port)) {
-                               if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST)
-                                       return false;
+               goto out;
+       }
 
-                               *pipe = i;
-                               return true;
-                       }
+       for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
+               tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
+
+               if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(port)) {
+                       if ((tmp & TRANS_DDI_MODE_SELECT_MASK) ==
+                           TRANS_DDI_MODE_SELECT_DP_MST)
+                               goto out;
+
+                       *pipe = i;
+                       ret = true;
+
+                       goto out;
                }
        }
 
        DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port));
 
-       return false;
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
@@ -2507,12 +2531,14 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(WRPLL_CTL(pll->id));
        hw_state->wrpll = val;
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
        return val & WRPLL_PLL_ENABLE;
 }
 
@@ -2522,12 +2548,14 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(SPLL_CTL);
        hw_state->spll = val;
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
        return val & SPLL_PLL_ENABLE;
 }
 
@@ -2644,16 +2672,19 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        uint32_t val;
        unsigned int dpll;
        const struct skl_dpll_regs *regs = skl_dpll_regs;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
+       ret = false;
+
        /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
        dpll = pll->id + 1;
 
        val = I915_READ(regs[pll->id].ctl);
        if (!(val & LCPLL_PLL_ENABLE))
-               return false;
+               goto out;
 
        val = I915_READ(DPLL_CTRL1);
        hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
@@ -2663,8 +2694,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
                hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
        }
+       ret = true;
 
-       return true;
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
 }
 
 static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)
@@ -2931,13 +2966,16 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
        uint32_t val;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
+       ret = false;
+
        val = I915_READ(BXT_PORT_PLL_ENABLE(port));
        if (!(val & PORT_PLL_ENABLE))
-               return false;
+               goto out;
 
        hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
        hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
@@ -2984,7 +3022,12 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                                 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
        hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
 }
 
 static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv)
@@ -3119,11 +3162,15 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
 {
        u32 temp;
 
-       if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
+       if (intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
                temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+
+               intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+
                if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
                        return true;
        }
+
        return false;
 }
 
index 5feb65725c04e350c09d33b8969a53770d3d6049..46947fffd5998074555c95ce8d373343aac20bd6 100644 (file)
@@ -1351,18 +1351,21 @@ void assert_pipe(struct drm_i915_private *dev_priv,
        bool cur_state;
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
+       enum intel_display_power_domain power_domain;
 
        /* if we need the pipe quirk it must be always on */
        if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
            (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
                state = true;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                               POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
-               cur_state = false;
-       } else {
+       power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
                u32 val = I915_READ(PIPECONF(cpu_transcoder));
                cur_state = !!(val & PIPECONF_ENABLE);
+
+               intel_display_power_put(dev_priv, power_domain);
+       } else {
+               cur_state = false;
        }
 
        I915_STATE_WARN(cur_state != state,
@@ -8171,18 +8174,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
        uint32_t tmp;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                                           POWER_DOMAIN_PIPE(crtc->pipe)))
+       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
+       ret = false;
+
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
-               return false;
+               goto out;
 
        if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                switch (tmp & PIPECONF_BPC_MASK) {
@@ -8262,7 +8269,12 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        pipe_config->base.adjusted_mode.crtc_clock =
                pipe_config->port_clock / pipe_config->pixel_multiplier;
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void ironlake_init_pch_refclk(struct drm_device *dev)
@@ -9366,18 +9378,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
        uint32_t tmp;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                                           POWER_DOMAIN_PIPE(crtc->pipe)))
+       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
+       ret = false;
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
-               return false;
+               goto out;
 
        switch (tmp & PIPECONF_BPC_MASK) {
        case PIPECONF_6BPC:
@@ -9440,7 +9455,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 
        ironlake_get_pfit_config(crtc, pipe_config);
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
@@ -9950,12 +9970,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum intel_display_power_domain pfit_domain;
+       enum intel_display_power_domain power_domain;
+       unsigned long power_domain_mask;
        uint32_t tmp;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                                        POWER_DOMAIN_PIPE(crtc->pipe)))
+       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
+       power_domain_mask = BIT(power_domain);
+
+       ret = false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
@@ -9982,13 +10007,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                        pipe_config->cpu_transcoder = TRANSCODER_EDP;
        }
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                       POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
-               return false;
+       power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               goto out;
+       power_domain_mask |= BIT(power_domain);
 
        tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
        if (!(tmp & PIPECONF_ENABLE))
-               return false;
+               goto out;
 
        haswell_get_ddi_port_state(crtc, pipe_config);
 
@@ -9998,14 +10024,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                skl_init_scalers(dev, crtc, pipe_config);
        }
 
-       pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-
        if (INTEL_INFO(dev)->gen >= 9) {
                pipe_config->scaler_state.scaler_id = -1;
                pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
        }
 
-       if (intel_display_power_is_enabled(dev_priv, pfit_domain)) {
+       power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
+       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+               power_domain_mask |= BIT(power_domain);
                if (INTEL_INFO(dev)->gen >= 9)
                        skylake_get_pfit_config(crtc, pipe_config);
                else
@@ -10023,7 +10049,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
 
-       return true;
+       ret = true;
+
+out:
+       for_each_power_domain(power_domain, power_domain_mask)
+               intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
@@ -13630,7 +13662,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(PCH_DPLL(pll->id));
@@ -13638,6 +13670,8 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
        hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
        hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
        return val & DPLL_VCO_ENABLE;
 }
 
@@ -15568,10 +15602,12 @@ void i915_redisable_vga(struct drm_device *dev)
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
                return;
 
        i915_redisable_vga_power_on(dev);
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 }
 
 static bool primary_get_hw_state(struct intel_plane *plane)
index 796e3d313cb975efc3797a39b15beb8e55ab7f92..1d8de43bed56839fd1fee3a75b6d61b6221c7c0a 100644 (file)
@@ -2362,15 +2362,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(intel_dp->output_reg);
 
        if (!(tmp & DP_PORT_EN))
-               return false;
+               goto out;
 
        if (IS_GEN7(dev) && port == PORT_A) {
                *pipe = PORT_TO_PIPE_CPT(tmp);
@@ -2381,7 +2384,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
                        u32 trans_dp = I915_READ(TRANS_DP_CTL(p));
                        if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) {
                                *pipe = p;
-                               return true;
+                               ret = true;
+
+                               goto out;
                        }
                }
 
@@ -2393,7 +2398,12 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
                *pipe = PORT_TO_PIPE(tmp);
        }
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void intel_dp_get_config(struct intel_encoder *encoder,
@@ -4493,20 +4503,20 @@ static bool g4x_digital_port_connected(struct drm_i915_private *dev_priv,
        return I915_READ(PORT_HOTPLUG_STAT) & bit;
 }
 
-static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv,
-                                      struct intel_digital_port *port)
+static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv,
+                                       struct intel_digital_port *port)
 {
        u32 bit;
 
        switch (port->port) {
        case PORT_B:
-               bit = PORTB_HOTPLUG_LIVE_STATUS_VLV;
+               bit = PORTB_HOTPLUG_LIVE_STATUS_GM45;
                break;
        case PORT_C:
-               bit = PORTC_HOTPLUG_LIVE_STATUS_VLV;
+               bit = PORTC_HOTPLUG_LIVE_STATUS_GM45;
                break;
        case PORT_D:
-               bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
+               bit = PORTD_HOTPLUG_LIVE_STATUS_GM45;
                break;
        default:
                MISSING_CASE(port->port);
@@ -4558,8 +4568,8 @@ bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
                return cpt_digital_port_connected(dev_priv, port);
        else if (IS_BROXTON(dev_priv))
                return bxt_digital_port_connected(dev_priv, port);
-       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               return vlv_digital_port_connected(dev_priv, port);
+       else if (IS_GM45(dev_priv))
+               return gm45_digital_port_connected(dev_priv, port);
        else
                return g4x_digital_port_connected(dev_priv, port);
 }
index 88887938e0bfd3e0cf3e7bdebd66a145f7e036a7..0b8eefc2acc5d93088b960e4714bce55944df82e 100644 (file)
@@ -215,27 +215,46 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
        }
 }
 
-static void
-intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
+/*
+ * Pick training pattern for channel equalization. Training Pattern 3 for HBR2
+ * or 1.2 devices that support it, Training Pattern 2 otherwise.
+ */
+static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
 {
-       bool channel_eq = false;
-       int tries, cr_tries;
-       uint32_t training_pattern = DP_TRAINING_PATTERN_2;
+       u32 training_pattern = DP_TRAINING_PATTERN_2;
+       bool source_tps3, sink_tps3;
 
        /*
-        * Training Pattern 3 for HBR2 or 1.2 devices that support it.
-        *
         * Intel platforms that support HBR2 also support TPS3. TPS3 support is
-        * also mandatory for downstream devices that support HBR2.
+        * also mandatory for downstream devices that support HBR2. However, not
+        * all sinks follow the spec.
         *
         * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
-        * supported but still not enabled.
+        * supported in source but still not enabled.
         */
-       if (intel_dp_source_supports_hbr2(intel_dp) &&
-           drm_dp_tps3_supported(intel_dp->dpcd))
+       source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
+       sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
+
+       if (source_tps3 && sink_tps3) {
                training_pattern = DP_TRAINING_PATTERN_3;
-       else if (intel_dp->link_rate == 540000)
-               DRM_ERROR("5.4 Gbps link rate without HBR2/TPS3 support\n");
+       } else if (intel_dp->link_rate == 540000) {
+               if (!source_tps3)
+                       DRM_DEBUG_KMS("5.4 Gbps link rate without source HBR2/TPS3 support\n");
+               if (!sink_tps3)
+                       DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n");
+       }
+
+       return training_pattern;
+}
+
+static void
+intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
+{
+       bool channel_eq = false;
+       int tries, cr_tries;
+       u32 training_pattern;
+
+       training_pattern = intel_dp_training_pattern(intel_dp);
 
        /* channel equalization */
        if (!intel_dp_set_link_train(intel_dp,
index ea5415851c6e2cc36d4c6790db473fab637fd46d..df7f3cb66056e754c3c8f596583cae343fc2d5a9 100644 (file)
@@ -1428,6 +1428,8 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
                                      enum intel_display_power_domain domain);
 void intel_display_power_get(struct drm_i915_private *dev_priv,
                             enum intel_display_power_domain domain);
+bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+                                       enum intel_display_power_domain domain);
 void intel_display_power_put(struct drm_i915_private *dev_priv,
                             enum intel_display_power_domain domain);
 
@@ -1514,6 +1516,7 @@ enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
        enable_rpm_wakeref_asserts(dev_priv)
 
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
 
index 44742fa2f616dd22fc25847b0f4ddb5730e550de..0193c62a53ef34f8e2027fb39e3172d44703bfba 100644 (file)
@@ -664,13 +664,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        enum intel_display_power_domain power_domain;
        enum port port;
+       bool ret;
 
        DRM_DEBUG_KMS("\n");
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        /* XXX: this only works for one DSI output */
        for_each_dsi_port(port, intel_dsi->ports) {
                i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
@@ -691,12 +694,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
                if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) {
                        if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) {
                                *pipe = port == PORT_A ? PIPE_A : PIPE_B;
-                               return true;
+                               ret = true;
+
+                               goto out;
                        }
                }
        }
+out:
+       intel_display_power_put(dev_priv, power_domain);
 
-       return false;
+       return ret;
 }
 
 static void intel_dsi_get_config(struct intel_encoder *encoder,
index a5e99ac305daab3ef69471d37b0ec9a97a27425c..e8113ad6547782ff5836839f1354a860aea5e464 100644 (file)
@@ -204,10 +204,28 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
        struct drm_device *dev = intel_dsi->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (dev_priv->vbt.dsi.seq_version >= 3)
+               data++;
+
        gpio = *data++;
 
        /* pull up/down */
-       action = *data++;
+       action = *data++ & 1;
+
+       if (gpio >= ARRAY_SIZE(gtable)) {
+               DRM_DEBUG_KMS("unknown gpio %u\n", gpio);
+               goto out;
+       }
+
+       if (!IS_VALLEYVIEW(dev_priv)) {
+               DRM_DEBUG_KMS("GPIO element not supported on this platform\n");
+               goto out;
+       }
+
+       if (dev_priv->vbt.dsi.seq_version >= 3) {
+               DRM_DEBUG_KMS("GPIO element v3 not supported\n");
+               goto out;
+       }
 
        function = gtable[gpio].function_reg;
        pad = gtable[gpio].pad_reg;
@@ -226,6 +244,7 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
        vlv_gpio_nc_write(dev_priv, pad, val);
        mutex_unlock(&dev_priv->sb_lock);
 
+out:
        return data;
 }
 
index 4a77639a489dfcd67ff0937e6e3fa4da61fed461..cb5d1b15755c3b19a496105c7a8df99982e83cb9 100644 (file)
@@ -880,15 +880,18 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(intel_hdmi->hdmi_reg);
 
        if (!(tmp & SDVO_ENABLE))
-               return false;
+               goto out;
 
        if (HAS_PCH_CPT(dev))
                *pipe = PORT_TO_PIPE_CPT(tmp);
@@ -897,7 +900,12 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
        else
                *pipe = PORT_TO_PIPE(tmp);
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void intel_hdmi_get_config(struct intel_encoder *encoder,
index 25254b5c1ac5c95173d0d5b4fa101f35a1131cb7..deb8282c26d83f952473ae145c4fef0b3112b9f1 100644 (file)
@@ -683,7 +683,7 @@ int intel_setup_gmbus(struct drm_device *dev)
        return 0;
 
 err:
-       while (--pin) {
+       while (pin--) {
                if (!intel_gmbus_is_valid_pin(dev_priv, pin))
                        continue;
 
index 0da0240caf815089447d4614b200ac818fd85250..bc04d8d29acb0bcc8112b39741f7614db6615625 100644 (file)
@@ -75,22 +75,30 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
        struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(lvds_encoder->reg);
 
        if (!(tmp & LVDS_PORT_EN))
-               return false;
+               goto out;
 
        if (HAS_PCH_CPT(dev))
                *pipe = PORT_TO_PIPE_CPT(tmp);
        else
                *pipe = PORT_TO_PIPE(tmp);
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void intel_lvds_get_config(struct intel_encoder *encoder,
index eb5fa05cf476e465ab2c0df6ee52f6870ec568f8..b28c29f20e754ec740e5aacd101bbe07867f65a6 100644 (file)
@@ -1783,16 +1783,20 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
                                   const struct intel_plane_state *pstate,
                                   uint32_t mem_value)
 {
-       int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+       /*
+        * We treat the cursor plane as always-on for the purposes of watermark
+        * calculation.  Until we have two-stage watermark programming merged,
+        * this is necessary to avoid flickering.
+        */
+       int cpp = 4;
+       int width = pstate->visible ? pstate->base.crtc_w : 64;
 
-       if (!cstate->base.active || !pstate->visible)
+       if (!cstate->base.active)
                return 0;
 
        return ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
                              cstate->base.adjusted_mode.crtc_htotal,
-                             drm_rect_width(&pstate->dst),
-                             bpp,
-                             mem_value);
+                             width, cpp, mem_value);
 }
 
 /* Only for WM_LP. */
@@ -2825,7 +2829,10 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
        memset(ddb, 0, sizeof(*ddb));
 
        for_each_pipe(dev_priv, pipe) {
-               if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe)))
+               enum intel_display_power_domain power_domain;
+
+               power_domain = POWER_DOMAIN_PIPE(pipe);
+               if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                        continue;
 
                for_each_plane(dev_priv, pipe, plane) {
@@ -2837,6 +2844,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
                val = I915_READ(CUR_BUF_CFG(pipe));
                skl_ddb_entry_init_from_hw(&ddb->plane[pipe][PLANE_CURSOR],
                                           val);
+
+               intel_display_power_put(dev_priv, power_domain);
        }
 }
 
index ddbdbffe829a684eff8c2ef42a3cf29ccbf112d8..4f43d9b32e6639a9f12db67ba0da213ae440f982 100644 (file)
@@ -470,6 +470,43 @@ static void gen9_set_dc_state_debugmask_memory_up(
        }
 }
 
+static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
+                               u32 state)
+{
+       int rewrites = 0;
+       int rereads = 0;
+       u32 v;
+
+       I915_WRITE(DC_STATE_EN, state);
+
+       /* It has been observed that disabling the dc6 state sometimes
+        * doesn't stick and dmc keeps returning old value. Make sure
+        * the write really sticks enough times and also force rewrite until
+        * we are confident that state is exactly what we want.
+        */
+       do  {
+               v = I915_READ(DC_STATE_EN);
+
+               if (v != state) {
+                       I915_WRITE(DC_STATE_EN, state);
+                       rewrites++;
+                       rereads = 0;
+               } else if (rereads++ > 5) {
+                       break;
+               }
+
+       } while (rewrites < 100);
+
+       if (v != state)
+               DRM_ERROR("Writing dc state to 0x%x failed, now 0x%x\n",
+                         state, v);
+
+       /* Most of the times we need one retry, avoid spam */
+       if (rewrites > 1)
+               DRM_DEBUG_KMS("Rewrote dc state to 0x%x %d times\n",
+                             state, rewrites);
+}
+
 static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
 {
        uint32_t val;
@@ -494,10 +531,18 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
        val = I915_READ(DC_STATE_EN);
        DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
                      val & mask, state);
+
+       /* Check if DMC is ignoring our DC state requests */
+       if ((val & mask) != dev_priv->csr.dc_state)
+               DRM_ERROR("DC state mismatch (0x%x -> 0x%x)\n",
+                         dev_priv->csr.dc_state, val & mask);
+
        val &= ~mask;
        val |= state;
-       I915_WRITE(DC_STATE_EN, val);
-       POSTING_READ(DC_STATE_EN);
+
+       gen9_write_dc_state(dev_priv, val);
+
+       dev_priv->csr.dc_state = val & mask;
 }
 
 void bxt_enable_dc9(struct drm_i915_private *dev_priv)
@@ -1442,6 +1487,22 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
        chv_set_pipe_power_well(dev_priv, power_well, false);
 }
 
+static void
+__intel_display_power_get_domain(struct drm_i915_private *dev_priv,
+                                enum intel_display_power_domain domain)
+{
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_well *power_well;
+       int i;
+
+       for_each_power_well(i, power_well, BIT(domain), power_domains) {
+               if (!power_well->count++)
+                       intel_power_well_enable(dev_priv, power_well);
+       }
+
+       power_domains->domain_use_count[domain]++;
+}
+
 /**
  * intel_display_power_get - grab a power domain reference
  * @dev_priv: i915 device instance
@@ -1457,24 +1518,53 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
 void intel_display_power_get(struct drm_i915_private *dev_priv,
                             enum intel_display_power_domain domain)
 {
-       struct i915_power_domains *power_domains;
-       struct i915_power_well *power_well;
-       int i;
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
        intel_runtime_pm_get(dev_priv);
 
-       power_domains = &dev_priv->power_domains;
+       mutex_lock(&power_domains->lock);
+
+       __intel_display_power_get_domain(dev_priv, domain);
+
+       mutex_unlock(&power_domains->lock);
+}
+
+/**
+ * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain
+ * @dev_priv: i915 device instance
+ * @domain: power domain to reference
+ *
+ * This function grabs a power domain reference for @domain and ensures that the
+ * power domain and all its parents are powered up. Therefore users should only
+ * grab a reference to the innermost power domain they need.
+ *
+ * Any power domain reference obtained by this function must have a symmetric
+ * call to intel_display_power_put() to release the reference again.
+ */
+bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+                                       enum intel_display_power_domain domain)
+{
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       bool is_enabled;
+
+       if (!intel_runtime_pm_get_if_in_use(dev_priv))
+               return false;
 
        mutex_lock(&power_domains->lock);
 
-       for_each_power_well(i, power_well, BIT(domain), power_domains) {
-               if (!power_well->count++)
-                       intel_power_well_enable(dev_priv, power_well);
+       if (__intel_display_power_is_enabled(dev_priv, domain)) {
+               __intel_display_power_get_domain(dev_priv, domain);
+               is_enabled = true;
+       } else {
+               is_enabled = false;
        }
 
-       power_domains->domain_use_count[domain]++;
-
        mutex_unlock(&power_domains->lock);
+
+       if (!is_enabled)
+               intel_runtime_pm_put(dev_priv);
+
+       return is_enabled;
 }
 
 /**
@@ -2213,15 +2303,15 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
  */
 void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
 {
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-               skl_display_core_uninit(dev_priv);
-
        /*
         * Even if power well support was disabled we still want to disable
         * power wells while we are system suspended.
         */
        if (!i915.disable_power_well)
                intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+               skl_display_core_uninit(dev_priv);
 }
 
 /**
@@ -2245,6 +2335,41 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
        assert_rpm_wakelock_held(dev_priv);
 }
 
+/**
+ * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
+ * @dev_priv: i915 device instance
+ *
+ * This function grabs a device-level runtime pm reference if the device is
+ * already in use and ensures that it is powered up.
+ *
+ * Any runtime pm reference obtained by this function must have a symmetric
+ * call to intel_runtime_pm_put() to release the reference again.
+ */
+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (IS_ENABLED(CONFIG_PM)) {
+               int ret = pm_runtime_get_if_in_use(device);
+
+               /*
+                * In cases runtime PM is disabled by the RPM core and we get
+                * an -EINVAL return value we are not supposed to call this
+                * function, since the power state is undefined. This applies
+                * atm to the late/early system suspend/resume handlers.
+                */
+               WARN_ON_ONCE(ret < 0);
+               if (ret <= 0)
+                       return false;
+       }
+
+       atomic_inc(&dev_priv->pm.wakeref_count);
+       assert_rpm_wakelock_held(dev_priv);
+
+       return true;
+}
+
 /**
  * intel_runtime_pm_get_noresume - grab a runtime pm reference
  * @dev_priv: i915 device instance
index 78f520d05de92ea627980c5e8f2bb8388715e6fe..e3acc35e3805e58b09fa47fe8dc70223aff175dc 100644 (file)
@@ -1520,7 +1520,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
                                    DMA_BIDIRECTIONAL);
 
                if (dma_mapping_error(pdev, addr)) {
-                       while (--i) {
+                       while (i--) {
                                dma_unmap_page(pdev, ttm_dma->dma_address[i],
                                               PAGE_SIZE, DMA_BIDIRECTIONAL);
                                ttm_dma->dma_address[i] = 0;
index 24be27d3cd18cfb35821b00fe9531c5d0337c284..20935eb2a09e9600e68d37edec8dcb3404a0db60 100644 (file)
@@ -635,10 +635,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
                nv_crtc->lut.depth = 0;
        }
 
-       /* Make sure that drm and hw vblank irqs get resumed if needed. */
-       for (head = 0; head < dev->mode_config.num_crtc; head++)
-               drm_vblank_on(dev, head);
-
        /* This should ensure we don't hit a locking problem when someone
         * wakes us up via a connector.  We should never go into suspend
         * while the display is on anyways.
@@ -648,6 +644,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
 
        drm_helper_resume_force_mode(dev);
 
+       /* Make sure that drm and hw vblank irqs get resumed if needed. */
+       for (head = 0; head < dev->mode_config.num_crtc; head++)
+               drm_vblank_on(dev, head);
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
index 8a70cec59bcd3f58b43d2d8119afa14c44190bce..2dfe58af12e4ee05103d14946dc4a0d001f7f9c6 100644 (file)
@@ -24,7 +24,7 @@
 static int nouveau_platform_probe(struct platform_device *pdev)
 {
        const struct nvkm_device_tegra_func *func;
-       struct nvkm_device *device;
+       struct nvkm_device *device = NULL;
        struct drm_device *drm;
        int ret;
 
index 7f8a42721eb20ccafe19fcaefe3d972f432a6c7f..e7e581d6a8ff24d256b6526d2b93c41b7a00daa3 100644 (file)
@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
 
        if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
                return -ENOMEM;
-       *pdevice = &tdev->device;
+
        tdev->func = func;
        tdev->pdev = pdev;
        tdev->irq = -1;
 
        tdev->vdd = devm_regulator_get(&pdev->dev, "vdd");
-       if (IS_ERR(tdev->vdd))
-               return PTR_ERR(tdev->vdd);
+       if (IS_ERR(tdev->vdd)) {
+               ret = PTR_ERR(tdev->vdd);
+               goto free;
+       }
 
        tdev->rst = devm_reset_control_get(&pdev->dev, "gpu");
-       if (IS_ERR(tdev->rst))
-               return PTR_ERR(tdev->rst);
+       if (IS_ERR(tdev->rst)) {
+               ret = PTR_ERR(tdev->rst);
+               goto free;
+       }
 
        tdev->clk = devm_clk_get(&pdev->dev, "gpu");
-       if (IS_ERR(tdev->clk))
-               return PTR_ERR(tdev->clk);
+       if (IS_ERR(tdev->clk)) {
+               ret = PTR_ERR(tdev->clk);
+               goto free;
+       }
 
        tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
-       if (IS_ERR(tdev->clk_pwr))
-               return PTR_ERR(tdev->clk_pwr);
+       if (IS_ERR(tdev->clk_pwr)) {
+               ret = PTR_ERR(tdev->clk_pwr);
+               goto free;
+       }
 
        nvkm_device_tegra_probe_iommu(tdev);
 
        ret = nvkm_device_tegra_power_up(tdev);
        if (ret)
-               return ret;
+               goto remove;
 
        tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value;
        ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
                               cfg, dbg, detect, mmio, subdev_mask,
                               &tdev->device);
        if (ret)
-               return ret;
+               goto powerdown;
+
+       *pdevice = &tdev->device;
 
        return 0;
+
+powerdown:
+       nvkm_device_tegra_power_down(tdev);
+remove:
+       nvkm_device_tegra_remove_iommu(tdev);
+free:
+       kfree(tdev);
+       return ret;
 }
 #else
 int
index 74e2f7c6c07e4a583d9e3f6d62016b92c5694d28..9688970eca47dbe4ccea5b2e700b0cfdb40b02e0 100644 (file)
@@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w)
                .outp = outp,
        }, *dp = &_dp;
        u32 datarate = 0;
+       u8  pwr;
        int ret;
 
        if (!outp->base.info.location && disp->func->sor.magic)
@@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w)
        /* disable link interrupt handling during link training */
        nvkm_notify_put(&outp->irq);
 
+       /* ensure sink is not in a low-power state */
+       if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
+               if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
+                       pwr &= ~DPCD_SC00_SET_POWER;
+                       pwr |=  DPCD_SC00_SET_POWER_D0;
+                       nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1);
+               }
+       }
+
        /* enable down-spreading and execute pre-train script from vbios */
        dp_link_train_init(dp, outp->dpcd[3] & 0x01);
 
index 9596290329c70e0cbe34259fbf5db39e12a9cbcb..6e10c5e0ef1162232253b29a248ad2c15e801f21 100644 (file)
 #define DPCD_LS0C_LANE1_POST_CURSOR2                                       0x0c
 #define DPCD_LS0C_LANE0_POST_CURSOR2                                       0x03
 
+/* DPCD Sink Control */
+#define DPCD_SC00                                                       0x00600
+#define DPCD_SC00_SET_POWER                                                0x03
+#define DPCD_SC00_SET_POWER_D0                                             0x01
+#define DPCD_SC00_SET_POWER_D3                                             0x03
+
 void nvkm_dp_train(struct work_struct *);
 #endif
index 2ae8577497ca6e1c9cc87b265ff7ca92ee5375ec..7c2e78201ead9d475c3ba97d083c523026c21a47 100644 (file)
@@ -168,7 +168,8 @@ static int qxl_process_single_command(struct qxl_device *qdev,
                       cmd->command_size))
                return -EFAULT;
 
-       reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL);
+       reloc_info = kmalloc_array(cmd->relocs_num,
+                                  sizeof(struct qxl_reloc_info), GFP_KERNEL);
        if (!reloc_info)
                return -ENOMEM;
 
index 3d031b50a8fd13dd8203f4de284ecedbb95ecbcc..9f029dda1f071431a9d90894096ab4a3f89bbe0a 100644 (file)
@@ -68,5 +68,5 @@ int qxl_gem_prime_mmap(struct drm_gem_object *obj,
                       struct vm_area_struct *area)
 {
        WARN_ONCE(1, "not implemented");
-       return ENOSYS;
+       return -ENOSYS;
 }
index 298ea1c453c3638fecdf6cef5afce1a48fdefa82..2b9ba03a7c1a84bc00564fe0f6391771977c2e7b 100644 (file)
@@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
        struct drm_crtc *crtc = &radeon_crtc->base;
        unsigned long flags;
        int r;
-       int vpos, hpos, stat, min_udelay;
+       int vpos, hpos, stat, min_udelay = 0;
+       unsigned repcnt = 4;
        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
 
         down_read(&rdev->exclusive_lock);
@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
         * In practice this won't execute very often unless on very fast
         * machines because the time window for this to happen is very small.
         */
-       for (;;) {
+       while (radeon_crtc->enabled && repcnt--) {
                /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
                 * start in hpos, and to the "fudged earlier" vblank start in
                 * vpos.
@@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct work_struct *__work)
                /* Sleep at least until estimated real start of hw vblank */
                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
+               if (min_udelay > vblank->framedur_ns / 2000) {
+                       /* Don't wait ridiculously long - something is wrong */
+                       repcnt = 0;
+                       break;
+               }
                usleep_range(min_udelay, 2 * min_udelay);
                spin_lock_irqsave(&crtc->dev->event_lock, flags);
        };
 
+       if (!repcnt)
+               DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
+                                "framedur %d, linedur %d, stat %d, vpos %d, "
+                                "hpos %d\n", work->crtc_id, min_udelay,
+                                vblank->framedur_ns / 1000,
+                                vblank->linedur_ns / 1000, stat, vpos, hpos);
+
        /* do the flip (mmio) */
        radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
 
index 460c8f2989daca1ba9af3b7ba59d724c27182c1c..0f14d897baf9b32974a97eaa59153363e3d8c97b 100644 (file)
@@ -276,8 +276,12 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
        if (rdev->irq.installed) {
                for (i = 0; i < rdev->num_crtc; i++) {
                        if (rdev->pm.active_crtcs & (1 << i)) {
-                               rdev->pm.req_vblank |= (1 << i);
-                               drm_vblank_get(rdev->ddev, i);
+                               /* This can fail if a modeset is in progress */
+                               if (drm_vblank_get(rdev->ddev, i) == 0)
+                                       rdev->pm.req_vblank |= (1 << i);
+                               else
+                                       DRM_DEBUG_DRIVER("crtc %d no vblank, can glitch\n",
+                                                        i);
                        }
                }
        }
@@ -1075,12 +1079,6 @@ force:
 
        /* update display watermarks based on new power state */
        radeon_bandwidth_update(rdev);
-       /* update displays */
-       radeon_dpm_display_configuration_changed(rdev);
-
-       rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
-       rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
-       rdev->pm.dpm.single_display = single_display;
 
        /* wait for the rings to drain */
        for (i = 0; i < RADEON_NUM_RINGS; i++) {
@@ -1097,6 +1095,13 @@ force:
 
        radeon_dpm_post_set_power_state(rdev);
 
+       /* update displays */
+       radeon_dpm_display_configuration_changed(rdev);
+
+       rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
+       rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
+       rdev->pm.dpm.single_display = single_display;
+
        if (rdev->asic->dpm.force_performance_level) {
                if (rdev->pm.dpm.thermal_active) {
                        enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
index c507896aca45a43a3fe271b79b84e7db61bfb85a..197b157b73d09b96f7ced03c6703b6696c210793 100644 (file)
@@ -349,8 +349,13 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
                        /* see if we can skip over some allocations */
                } while (radeon_sa_bo_next_hole(sa_manager, fences, tries));
 
+               for (i = 0; i < RADEON_NUM_RINGS; ++i)
+                       radeon_fence_ref(fences[i]);
+
                spin_unlock(&sa_manager->wq.lock);
                r = radeon_fence_wait_any(rdev, fences, false);
+               for (i = 0; i < RADEON_NUM_RINGS; ++i)
+                       radeon_fence_unref(&fences[i]);
                spin_lock(&sa_manager->wq.lock);
                /* if we have nothing to wait for block */
                if (r == -ENOENT) {
index e34307459e501f60895ca4a0abe156995706f921..e06ac546a90ff185a31f64b4ce6e9fd76d071adc 100644 (file)
@@ -758,7 +758,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm)
                                                       0, PAGE_SIZE,
                                                       PCI_DMA_BIDIRECTIONAL);
                if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) {
-                       while (--i) {
+                       while (i--) {
                                pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i],
                                               PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
                                gtt->ttm.dma_address[i] = 0;
index 18dfe3ec9a6274a57e8b311d5c62c82cb50c124f..22278bcfc60eac4ed40fac0e31dda840aa4b703e 100644 (file)
@@ -215,7 +215,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
        struct drm_gem_cma_object *cma_obj;
 
        if (size == 0)
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        /* First, try to get a vc4_bo from the kernel BO cache. */
        if (from_cache) {
@@ -237,7 +237,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
                if (IS_ERR(cma_obj)) {
                        DRM_ERROR("Failed to allocate from CMA:\n");
                        vc4_bo_stats_dump(vc4);
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                }
        }
 
@@ -259,8 +259,8 @@ int vc4_dumb_create(struct drm_file *file_priv,
                args->size = args->pitch * args->height;
 
        bo = vc4_bo_create(dev, args->size, false);
-       if (!bo)
-               return -ENOMEM;
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
 
        ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);
        drm_gem_object_unreference_unlocked(&bo->base.base);
@@ -443,8 +443,8 @@ int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
         * get zeroed, and that might leak data between users.
         */
        bo = vc4_bo_create(dev, args->size, false);
-       if (!bo)
-               return -ENOMEM;
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
 
        ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle);
        drm_gem_object_unreference_unlocked(&bo->base.base);
@@ -496,8 +496,8 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
        }
 
        bo = vc4_bo_create(dev, args->size, true);
-       if (!bo)
-               return -ENOMEM;
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
 
        ret = copy_from_user(bo->base.vaddr,
                             (void __user *)(uintptr_t)args->data,
index 080865ec2bae67c7ff7b04a97fdb5956096cc156..51a63330d4f8bd3bef1946224aafba621eaa26a5 100644 (file)
@@ -91,8 +91,12 @@ struct vc4_dev {
        struct vc4_bo *overflow_mem;
        struct work_struct overflow_mem_work;
 
+       int power_refcount;
+
+       /* Mutex controlling the power refcount. */
+       struct mutex power_lock;
+
        struct {
-               uint32_t last_ct0ca, last_ct1ca;
                struct timer_list timer;
                struct work_struct reset_work;
        } hangcheck;
@@ -142,6 +146,7 @@ struct vc4_seqno_cb {
 };
 
 struct vc4_v3d {
+       struct vc4_dev *vc4;
        struct platform_device *pdev;
        void __iomem *regs;
 };
@@ -192,6 +197,11 @@ struct vc4_exec_info {
        /* Sequence number for this bin/render job. */
        uint64_t seqno;
 
+       /* Last current addresses the hardware was processing when the
+        * hangcheck timer checked on us.
+        */
+       uint32_t last_ct0ca, last_ct1ca;
+
        /* Kernel-space copy of the ioctl arguments */
        struct drm_vc4_submit_cl *args;
 
@@ -434,7 +444,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane,
 extern struct platform_driver vc4_v3d_driver;
 int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
 int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
-int vc4_v3d_set_power(struct vc4_dev *vc4, bool on);
 
 /* vc4_validate.c */
 int
index 48ce30a6f4b5cebb21348c1148d85a8c2450e45f..202aa1544acc7df6b669781764f387daa99dd871 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/device.h>
 #include <linux/io.h>
 
@@ -228,8 +229,16 @@ vc4_reset(struct drm_device *dev)
        struct vc4_dev *vc4 = to_vc4_dev(dev);
 
        DRM_INFO("Resetting GPU.\n");
-       vc4_v3d_set_power(vc4, false);
-       vc4_v3d_set_power(vc4, true);
+
+       mutex_lock(&vc4->power_lock);
+       if (vc4->power_refcount) {
+               /* Power the device off and back on the by dropping the
+                * reference on runtime PM.
+                */
+               pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev);
+               pm_runtime_get_sync(&vc4->v3d->pdev->dev);
+       }
+       mutex_unlock(&vc4->power_lock);
 
        vc4_irq_reset(dev);
 
@@ -257,10 +266,17 @@ vc4_hangcheck_elapsed(unsigned long data)
        struct drm_device *dev = (struct drm_device *)data;
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        uint32_t ct0ca, ct1ca;
+       unsigned long irqflags;
+       struct vc4_exec_info *exec;
+
+       spin_lock_irqsave(&vc4->job_lock, irqflags);
+       exec = vc4_first_job(vc4);
 
        /* If idle, we can stop watching for hangs. */
-       if (list_empty(&vc4->job_list))
+       if (!exec) {
+               spin_unlock_irqrestore(&vc4->job_lock, irqflags);
                return;
+       }
 
        ct0ca = V3D_READ(V3D_CTNCA(0));
        ct1ca = V3D_READ(V3D_CTNCA(1));
@@ -268,14 +284,16 @@ vc4_hangcheck_elapsed(unsigned long data)
        /* If we've made any progress in execution, rearm the timer
         * and wait.
         */
-       if (ct0ca != vc4->hangcheck.last_ct0ca ||
-           ct1ca != vc4->hangcheck.last_ct1ca) {
-               vc4->hangcheck.last_ct0ca = ct0ca;
-               vc4->hangcheck.last_ct1ca = ct1ca;
+       if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) {
+               exec->last_ct0ca = ct0ca;
+               exec->last_ct1ca = ct1ca;
+               spin_unlock_irqrestore(&vc4->job_lock, irqflags);
                vc4_queue_hangcheck(dev);
                return;
        }
 
+       spin_unlock_irqrestore(&vc4->job_lock, irqflags);
+
        /* We've gone too long with no progress, reset.  This has to
         * be done from a work struct, since resetting can sleep and
         * this timer hook isn't allowed to.
@@ -340,12 +358,7 @@ vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns,
        finish_wait(&vc4->job_wait_queue, &wait);
        trace_vc4_wait_for_seqno_end(dev, seqno);
 
-       if (ret && ret != -ERESTARTSYS) {
-               DRM_ERROR("timeout waiting for render thread idle\n");
-               return ret;
-       }
-
-       return 0;
+       return ret;
 }
 
 static void
@@ -578,9 +591,9 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
        }
 
        bo = vc4_bo_create(dev, exec_size, true);
-       if (!bo) {
+       if (IS_ERR(bo)) {
                DRM_ERROR("Couldn't allocate BO for binning\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(bo);
                goto fail;
        }
        exec->exec_bo = &bo->base;
@@ -617,6 +630,7 @@ fail:
 static void
 vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
 {
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
        unsigned i;
 
        /* Need the struct lock for drm_gem_object_unreference(). */
@@ -635,6 +649,11 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
        }
        mutex_unlock(&dev->struct_mutex);
 
+       mutex_lock(&vc4->power_lock);
+       if (--vc4->power_refcount == 0)
+               pm_runtime_put(&vc4->v3d->pdev->dev);
+       mutex_unlock(&vc4->power_lock);
+
        kfree(exec);
 }
 
@@ -746,6 +765,9 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data,
        struct drm_gem_object *gem_obj;
        struct vc4_bo *bo;
 
+       if (args->pad != 0)
+               return -EINVAL;
+
        gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (!gem_obj) {
                DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
@@ -772,7 +794,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct drm_vc4_submit_cl *args = data;
        struct vc4_exec_info *exec;
-       int ret;
+       int ret = 0;
 
        if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) {
                DRM_ERROR("Unknown flags: 0x%02x\n", args->flags);
@@ -785,6 +807,15 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
                return -ENOMEM;
        }
 
+       mutex_lock(&vc4->power_lock);
+       if (vc4->power_refcount++ == 0)
+               ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
+       mutex_unlock(&vc4->power_lock);
+       if (ret < 0) {
+               kfree(exec);
+               return ret;
+       }
+
        exec->args = args;
        INIT_LIST_HEAD(&exec->unref_list);
 
@@ -839,6 +870,8 @@ vc4_gem_init(struct drm_device *dev)
                    (unsigned long)dev);
 
        INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
+
+       mutex_init(&vc4->power_lock);
 }
 
 void
index b68060e758dbd26e1dccd17beeba4c09bbb1441e..78a21357fb2de9fe88d50a26f20f0634d97dbd88 100644 (file)
@@ -57,7 +57,7 @@ vc4_overflow_mem_work(struct work_struct *work)
        struct vc4_bo *bo;
 
        bo = vc4_bo_create(dev, 256 * 1024, true);
-       if (!bo) {
+       if (IS_ERR(bo)) {
                DRM_ERROR("Couldn't allocate binner overflow mem\n");
                return;
        }
index 8a2a312e2c1bb618ea414ed3f0dd87e82ed7e09a..0f12418725e552f7378dada1d5af1244f52599ad 100644 (file)
@@ -316,20 +316,11 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
        size += xtiles * ytiles * loop_body_size;
 
        setup->rcl = &vc4_bo_create(dev, size, true)->base;
-       if (!setup->rcl)
-               return -ENOMEM;
+       if (IS_ERR(setup->rcl))
+               return PTR_ERR(setup->rcl);
        list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head,
                      &exec->unref_list);
 
-       rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
-       rcl_u32(setup,
-               (setup->color_write ? (setup->color_write->paddr +
-                                      args->color_write.offset) :
-                0));
-       rcl_u16(setup, args->width);
-       rcl_u16(setup, args->height);
-       rcl_u16(setup, args->color_write.bits);
-
        /* The tile buffer gets cleared when the previous tile is stored.  If
         * the clear values changed between frames, then the tile buffer has
         * stale clear values in it, so we have to do a store in None mode (no
@@ -349,6 +340,15 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
                rcl_u32(setup, 0); /* no address, since we're in None mode */
        }
 
+       rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
+       rcl_u32(setup,
+               (setup->color_write ? (setup->color_write->paddr +
+                                      args->color_write.offset) :
+                0));
+       rcl_u16(setup, args->width);
+       rcl_u16(setup, args->height);
+       rcl_u16(setup, args->color_write.bits);
+
        for (y = min_y_tile; y <= max_y_tile; y++) {
                for (x = min_x_tile; x <= max_x_tile; x++) {
                        bool first = (x == min_x_tile && y == min_y_tile);
index 314ff71db978dedfd8272ea0afe0087f1903ca4a..31de5d17bc856a0c152f9d9b4ebaae4c48880ce9 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "linux/component.h"
+#include "linux/pm_runtime.h"
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
@@ -144,18 +145,6 @@ int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
 }
 #endif /* CONFIG_DEBUG_FS */
 
-int
-vc4_v3d_set_power(struct vc4_dev *vc4, bool on)
-{
-       /* XXX: This interface is needed for GPU reset, and the way to
-        * do it is to turn our power domain off and back on.  We
-        * can't just reset from within the driver, because the reset
-        * bits are in the power domain's register area, and get set
-        * during the poweron process.
-        */
-       return 0;
-}
-
 static void vc4_v3d_init_hw(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -167,6 +156,29 @@ static void vc4_v3d_init_hw(struct drm_device *dev)
        V3D_WRITE(V3D_VPMBASE, 0);
 }
 
+#ifdef CONFIG_PM
+static int vc4_v3d_runtime_suspend(struct device *dev)
+{
+       struct vc4_v3d *v3d = dev_get_drvdata(dev);
+       struct vc4_dev *vc4 = v3d->vc4;
+
+       vc4_irq_uninstall(vc4->dev);
+
+       return 0;
+}
+
+static int vc4_v3d_runtime_resume(struct device *dev)
+{
+       struct vc4_v3d *v3d = dev_get_drvdata(dev);
+       struct vc4_dev *vc4 = v3d->vc4;
+
+       vc4_v3d_init_hw(vc4->dev);
+       vc4_irq_postinstall(vc4->dev);
+
+       return 0;
+}
+#endif
+
 static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -179,6 +191,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
        if (!v3d)
                return -ENOMEM;
 
+       dev_set_drvdata(dev, v3d);
+
        v3d->pdev = pdev;
 
        v3d->regs = vc4_ioremap_regs(pdev, 0);
@@ -186,6 +200,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
                return PTR_ERR(v3d->regs);
 
        vc4->v3d = v3d;
+       v3d->vc4 = vc4;
 
        if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
                DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
@@ -207,6 +222,8 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
+       pm_runtime_enable(dev);
+
        return 0;
 }
 
@@ -216,6 +233,8 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
        struct drm_device *drm = dev_get_drvdata(master);
        struct vc4_dev *vc4 = to_vc4_dev(drm);
 
+       pm_runtime_disable(dev);
+
        drm_irq_uninstall(drm);
 
        /* Disable the binner's overflow memory address, so the next
@@ -228,6 +247,10 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
        vc4->v3d = NULL;
 }
 
+static const struct dev_pm_ops vc4_v3d_pm_ops = {
+       SET_RUNTIME_PM_OPS(vc4_v3d_runtime_suspend, vc4_v3d_runtime_resume, NULL)
+};
+
 static const struct component_ops vc4_v3d_ops = {
        .bind   = vc4_v3d_bind,
        .unbind = vc4_v3d_unbind,
@@ -255,5 +278,6 @@ struct platform_driver vc4_v3d_driver = {
        .driver = {
                .name = "vc4_v3d",
                .of_match_table = vc4_v3d_dt_match,
+               .pm = &vc4_v3d_pm_ops,
        },
 };
index e26d9f6face3c498a4ddb5278e7d9f043cd2de2c..24c2c746e8f397aafd0285323508bd2ee351d3a2 100644 (file)
@@ -401,8 +401,8 @@ validate_tile_binning_config(VALIDATE_ARGS)
        tile_bo = vc4_bo_create(dev, exec->tile_alloc_offset + tile_alloc_size,
                                true);
        exec->tile_bo = &tile_bo->base;
-       if (!exec->tile_bo)
-               return -ENOMEM;
+       if (IS_ERR(exec->tile_bo))
+               return PTR_ERR(exec->tile_bo);
        list_add_tail(&tile_bo->unref_head, &exec->unref_list);
 
        /* tile alloc address. */
index da462afcb225ea6958918b3d8ff52a0ee928cca3..dd2dbb9746cebc337b17733eb41c4cf4536d75c6 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/host1x.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include "bus.h"
 #include "dev.h"
@@ -394,6 +395,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;
        dev_set_name(&device->dev, "%s", driver->driver.name);
+       of_dma_configure(&device->dev, host1x->dev->of_node);
        device->dev.release = host1x_device_release;
        device->dev.bus = &host1x_bus_type;
        device->dev.parent = host1x->dev;
index 314bf3718cc799b01462dd2cee678dcec604632e..ff348690df94a0eebcddaadedfbf440cb05cac4a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/host1x.h>
@@ -68,6 +69,7 @@ static const struct host1x_info host1x01_info = {
        .nb_bases       = 8,
        .init           = host1x01_init,
        .sync_offset    = 0x3000,
+       .dma_mask       = DMA_BIT_MASK(32),
 };
 
 static const struct host1x_info host1x02_info = {
@@ -77,6 +79,7 @@ static const struct host1x_info host1x02_info = {
        .nb_bases = 12,
        .init = host1x02_init,
        .sync_offset = 0x3000,
+       .dma_mask = DMA_BIT_MASK(32),
 };
 
 static const struct host1x_info host1x04_info = {
@@ -86,6 +89,7 @@ static const struct host1x_info host1x04_info = {
        .nb_bases = 64,
        .init = host1x04_init,
        .sync_offset = 0x2100,
+       .dma_mask = DMA_BIT_MASK(34),
 };
 
 static const struct host1x_info host1x05_info = {
@@ -95,6 +99,7 @@ static const struct host1x_info host1x05_info = {
        .nb_bases = 64,
        .init = host1x05_init,
        .sync_offset = 0x2100,
+       .dma_mask = DMA_BIT_MASK(34),
 };
 
 static struct of_device_id host1x_of_match[] = {
@@ -148,6 +153,8 @@ static int host1x_probe(struct platform_device *pdev)
        if (IS_ERR(host->regs))
                return PTR_ERR(host->regs);
 
+       dma_set_mask_and_coherent(host->dev, host->info->dma_mask);
+
        if (host->info->init) {
                err = host->info->init(host);
                if (err)
index 0b6e8e9629c5330fbc7fadba1a1ae318ae07da12..dace124994bb2683cc0c66218dcd5cdd15902d2b 100644 (file)
@@ -96,6 +96,7 @@ struct host1x_info {
        int     nb_mlocks;              /* host1x: number of mlocks */
        int     (*init)(struct host1x *); /* initialize per SoC ops */
        int     sync_offset;
+       u64     dma_mask;               /* mask of addressable memory */
 };
 
 struct host1x {
index f155b83804819ff97455ba5312f62de7f14991e2..2b3105c8aed399f8ce9cd3df03d6a265378131fc 100644 (file)
@@ -126,7 +126,7 @@ static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel,
        struct ads1015_data *data = i2c_get_clientdata(client);
        unsigned int pga = data->channel_data[channel].pga;
        int fullscale = fullscale_table[pga];
-       const unsigned mask = data->id == ads1115 ? 0x7fff : 0x7ff0;
+       const int mask = data->id == ads1115 ? 0x7fff : 0x7ff0;
 
        return DIV_ROUND_CLOSEST(reg * fullscale, mask);
 }
index 82de3deeb18a7ddf5e041e695b35cc8b1500abea..685568b1236d4a26db2d685ce36dcb9729e9f3ab 100644 (file)
@@ -406,16 +406,11 @@ static int gpio_fan_get_cur_state(struct thermal_cooling_device *cdev,
                                  unsigned long *state)
 {
        struct gpio_fan_data *fan_data = cdev->devdata;
-       int r;
 
        if (!fan_data)
                return -EINVAL;
 
-       r = get_fan_speed_index(fan_data);
-       if (r < 0)
-               return r;
-
-       *state = r;
+       *state = fan_data->speed_index;
        return 0;
 }
 
index 3711df1d452622edd57fb805f2ffcbbab236d9b4..4a45408dd82060fc56b9e8e10c2e8534e8ebba5d 100644 (file)
@@ -586,8 +586,7 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
        if (!dev)
                return -ENOMEM;
 
-       dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(struct bsc_regs *),
-                                      GFP_KERNEL);
+       dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(*dev->bsc_regmap), GFP_KERNEL);
        if (!dev->bsc_regmap)
                return -ENOMEM;
 
index f62d69799a9c55b0f79e2de5e29ec9a09b257c98..27fa0cb09538cebfd0f9388112cfe30abb773edd 100644 (file)
@@ -1271,6 +1271,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        switch (dev->device) {
        case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS:
        case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS:
+       case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS:
+       case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS:
        case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
                priv->features |= FEATURE_I2C_BLOCK_READ;
                priv->features |= FEATURE_IRQ;
index 08d26ba61ed3326a8905c99cdb6ee8caaef45727..13c45296ce5bfc5390a1bbffcca9960b3b1b90b6 100644 (file)
@@ -1450,7 +1450,8 @@ omap_i2c_probe(struct platform_device *pdev)
 
 err_unuse_clocks:
        omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0);
-       pm_runtime_put(omap->dev);
+       pm_runtime_dont_use_autosuspend(omap->dev);
+       pm_runtime_put_sync(omap->dev);
        pm_runtime_disable(&pdev->dev);
 err_free_mem:
 
@@ -1468,6 +1469,7 @@ static int omap_i2c_remove(struct platform_device *pdev)
                return ret;
 
        omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        return 0;
index f3e5ff8522f0af6ef77af252f3269114fe4b803e..213ba55e17c3a35bfe9faacc9155a3f8072b2899 100644 (file)
@@ -467,7 +467,7 @@ static int uniphier_fi2c_clk_init(struct device *dev,
                bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;
 
        if (!bus_speed) {
-               dev_err(dev, "clock-freqyency should not be zero\n");
+               dev_err(dev, "clock-frequency should not be zero\n");
                return -EINVAL;
        }
 
index 1f4f3f53819c7a88516dad5eab11d773fceb89f9..89eaa8a7e1e01578a4ee27f322a8cbfe75abf5e8 100644 (file)
@@ -328,7 +328,7 @@ static int uniphier_i2c_clk_init(struct device *dev,
                bus_speed = UNIPHIER_I2C_DEFAULT_SPEED;
 
        if (!bus_speed) {
-               dev_err(dev, "clock-freqyency should not be zero\n");
+               dev_err(dev, "clock-frequency should not be zero\n");
                return -EINVAL;
        }
 
index 00da80e02154205c428ca00702f4b7c10fa5a829..94b80a51ab68e7e15c327778122f54351254b9a6 100644 (file)
@@ -358,6 +358,7 @@ int ib_register_device(struct ib_device *device,
        ret = device->query_device(device, &device->attrs, &uhw);
        if (ret) {
                printk(KERN_WARNING "Couldn't query the device attributes\n");
+               ib_cache_cleanup_one(device);
                goto out;
        }
 
index f334090bb6129bf7f3cfe788e5cff7bc762752c3..1e37f3515d98a7fba49a7cbd57975ba2b8492bd5 100644 (file)
@@ -1071,7 +1071,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
                }
        }
 
-       if (rec->hop_limit > 1 || use_roce) {
+       if (rec->hop_limit > 0 || use_roce) {
                ah_attr->ah_flags = IB_AH_GRH;
                ah_attr->grh.dgid = rec->dgid;
 
index 3de93517efe43b097d7f58e37cfbe36bd8ab0f65..14606afbfaa8d6c865d28a545c292146ffc1b4bc 100644 (file)
@@ -336,7 +336,6 @@ static ssize_t _show_port_gid_attr(struct ib_port *p,
        union ib_gid gid;
        struct ib_gid_attr gid_attr = {};
        ssize_t ret;
-       va_list args;
 
        ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid,
                           &gid_attr);
@@ -348,7 +347,6 @@ static ssize_t _show_port_gid_attr(struct ib_port *p,
 err:
        if (gid_attr.ndev)
                dev_put(gid_attr.ndev);
-       va_end(args);
        return ret;
 }
 
@@ -722,12 +720,11 @@ static struct attribute_group *get_counter_table(struct ib_device *dev,
 
        if (get_perf_mad(dev, port_num, IB_PMA_CLASS_PORT_INFO,
                                &cpi, 40, sizeof(cpi)) >= 0) {
-
-               if (cpi.capability_mask && IB_PMA_CLASS_CAP_EXT_WIDTH)
+               if (cpi.capability_mask & IB_PMA_CLASS_CAP_EXT_WIDTH)
                        /* We have extended counters */
                        return &pma_group_ext;
 
-               if (cpi.capability_mask && IB_PMA_CLASS_CAP_EXT_WIDTH_NOIETF)
+               if (cpi.capability_mask & IB_PMA_CLASS_CAP_EXT_WIDTH_NOIETF)
                        /* But not the IETF ones */
                        return &pma_group_noietf;
        }
index 6ffc9c4e93afb4efa27fe6f3c17fc3cdf41d8c21..6c6fbff19752ecbcf2d4822965ff6bb09d7ee656 100644 (file)
@@ -1970,7 +1970,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
                   resp_size);
        INIT_UDATA(&uhw, buf + sizeof(cmd),
                   (unsigned long)cmd.response + resp_size,
-                  in_len - sizeof(cmd), out_len - resp_size);
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - resp_size);
 
        memset(&cmd_ex, 0, sizeof(cmd_ex));
        cmd_ex.user_handle = cmd.user_handle;
@@ -3413,7 +3414,8 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
 
        INIT_UDATA(&udata, buf + sizeof cmd,
                   (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+                  in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof resp);
 
        ret = __uverbs_create_xsrq(file, ib_dev, &xcmd, &udata);
        if (ret)
@@ -3439,7 +3441,8 @@ ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
 
        INIT_UDATA(&udata, buf + sizeof cmd,
                   (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+                  in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof resp);
 
        ret = __uverbs_create_xsrq(file, ib_dev, &cmd, &udata);
        if (ret)
index 26833bfa639bb61fb9658187bfa5cd45497340ed..d68f506c1922e8d18af269a4fcde33fd0e3ae5d5 100644 (file)
@@ -817,17 +817,48 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
        return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
 }
 
-static void edit_counter(struct mlx4_counter *cnt,
-                                       struct ib_pma_portcounters *pma_cnt)
+static void edit_counter(struct mlx4_counter *cnt, void *counters,
+                        __be16 attr_id)
 {
-       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data,
-                            (be64_to_cpu(cnt->tx_bytes) >> 2));
-       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data,
-                            (be64_to_cpu(cnt->rx_bytes) >> 2));
-       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets,
-                            be64_to_cpu(cnt->tx_frames));
-       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets,
-                            be64_to_cpu(cnt->rx_frames));
+       switch (attr_id) {
+       case IB_PMA_PORT_COUNTERS:
+       {
+               struct ib_pma_portcounters *pma_cnt =
+                       (struct ib_pma_portcounters *)counters;
+
+               ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data,
+                                    (be64_to_cpu(cnt->tx_bytes) >> 2));
+               ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data,
+                                    (be64_to_cpu(cnt->rx_bytes) >> 2));
+               ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets,
+                                    be64_to_cpu(cnt->tx_frames));
+               ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets,
+                                    be64_to_cpu(cnt->rx_frames));
+               break;
+       }
+       case IB_PMA_PORT_COUNTERS_EXT:
+       {
+               struct ib_pma_portcounters_ext *pma_cnt_ext =
+                       (struct ib_pma_portcounters_ext *)counters;
+
+               pma_cnt_ext->port_xmit_data =
+                       cpu_to_be64(be64_to_cpu(cnt->tx_bytes) >> 2);
+               pma_cnt_ext->port_rcv_data =
+                       cpu_to_be64(be64_to_cpu(cnt->rx_bytes) >> 2);
+               pma_cnt_ext->port_xmit_packets = cnt->tx_frames;
+               pma_cnt_ext->port_rcv_packets = cnt->rx_frames;
+               break;
+       }
+       }
+}
+
+static int iboe_process_mad_port_info(void *out_mad)
+{
+       struct ib_class_port_info cpi = {};
+
+       cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
+       memcpy(out_mad, &cpi, sizeof(cpi));
+       return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
 }
 
 static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
@@ -842,6 +873,9 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
        if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
                return -EINVAL;
 
+       if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO)
+               return iboe_process_mad_port_info((void *)(out_mad->data + 40));
+
        memset(&counter_stats, 0, sizeof(counter_stats));
        mutex_lock(&dev->counters_table[port_num - 1].mutex);
        list_for_each_entry(tmp_counter,
@@ -863,7 +897,8 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
                switch (counter_stats.counter_mode & 0xf) {
                case 0:
                        edit_counter(&counter_stats,
-                                    (void *)(out_mad->data + 40));
+                                    (void *)(out_mad->data + 40),
+                                    in_mad->mad_hdr.attr_id);
                        err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
                        break;
                default:
@@ -894,8 +929,10 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
         */
        if (link == IB_LINK_LAYER_INFINIBAND) {
                if (mlx4_is_slave(dev->dev) &&
-                   in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT &&
-                   in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS)
+                   (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT &&
+                    (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS ||
+                     in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT ||
+                     in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO)))
                        return iboe_process_mad(ibdev, mad_flags, port_num, in_wc,
                                                in_grh, in_mad, out_mad);
 
index bc5536f00b6cd4cc148f65b2c6131d7e627544eb..fd97534762b8dc7f83651a52e9398a3aa6e4944e 100644 (file)
@@ -1681,9 +1681,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
        }
 
        if (qp->ibqp.uobject)
-               context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
+               context->usr_page = cpu_to_be32(
+                       mlx4_to_hw_uar_index(dev->dev,
+                                            to_mucontext(ibqp->uobject->context)->uar.index));
        else
-               context->usr_page = cpu_to_be32(dev->priv_uar.index);
+               context->usr_page = cpu_to_be32(
+                       mlx4_to_hw_uar_index(dev->dev, dev->priv_uar.index));
 
        if (attr_mask & IB_QP_DEST_QPN)
                context->remote_qpn = cpu_to_be32(attr->dest_qp_num);
index 9116bc3988a6f9338709f6120a4597794d2cf36d..34cb8e87c7b8b673493285f807206c437ac42a84 100644 (file)
@@ -270,8 +270,10 @@ static int sq_overhead(enum ib_qp_type qp_type)
                /* fall through */
        case IB_QPT_RC:
                size += sizeof(struct mlx5_wqe_ctrl_seg) +
-                       sizeof(struct mlx5_wqe_atomic_seg) +
-                       sizeof(struct mlx5_wqe_raddr_seg);
+                       max(sizeof(struct mlx5_wqe_atomic_seg) +
+                           sizeof(struct mlx5_wqe_raddr_seg),
+                           sizeof(struct mlx5_wqe_umr_ctrl_seg) +
+                           sizeof(struct mlx5_mkey_seg));
                break;
 
        case IB_QPT_XRC_TGT:
@@ -279,9 +281,9 @@ static int sq_overhead(enum ib_qp_type qp_type)
 
        case IB_QPT_UC:
                size += sizeof(struct mlx5_wqe_ctrl_seg) +
-                       sizeof(struct mlx5_wqe_raddr_seg) +
-                       sizeof(struct mlx5_wqe_umr_ctrl_seg) +
-                       sizeof(struct mlx5_mkey_seg);
+                       max(sizeof(struct mlx5_wqe_raddr_seg),
+                           sizeof(struct mlx5_wqe_umr_ctrl_seg) +
+                           sizeof(struct mlx5_mkey_seg));
                break;
 
        case IB_QPT_UD:
index 4659256cd95e698c3a9dad3c69407276e2117f29..3b2ddd64a371689e1533cb08c23007a4d6016b03 100644 (file)
@@ -75,7 +75,8 @@ static void mlx5_ib_srq_event(struct mlx5_core_srq *srq, enum mlx5_event type)
 
 static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
                           struct mlx5_create_srq_mbox_in **in,
-                          struct ib_udata *udata, int buf_size, int *inlen)
+                          struct ib_udata *udata, int buf_size, int *inlen,
+                          int is_xrc)
 {
        struct mlx5_ib_dev *dev = to_mdev(pd->device);
        struct mlx5_ib_create_srq ucmd = {};
@@ -87,13 +88,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
        int ncont;
        u32 offset;
        u32 uidx = MLX5_IB_DEFAULT_UIDX;
-       int drv_data = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr);
 
-       if (drv_data < 0)
-               return -EINVAL;
-
-       ucmdlen = (drv_data < sizeof(ucmd)) ?
-                 drv_data : sizeof(ucmd);
+       ucmdlen = min(udata->inlen, sizeof(ucmd));
 
        if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) {
                mlx5_ib_dbg(dev, "failed copy udata\n");
@@ -103,15 +99,17 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
        if (ucmd.reserved0 || ucmd.reserved1)
                return -EINVAL;
 
-       if (drv_data > sizeof(ucmd) &&
+       if (udata->inlen > sizeof(ucmd) &&
            !ib_is_udata_cleared(udata, sizeof(ucmd),
-                                drv_data - sizeof(ucmd)))
+                                udata->inlen - sizeof(ucmd)))
                return -EINVAL;
 
-       err = get_srq_user_index(to_mucontext(pd->uobject->context),
-                                &ucmd, udata->inlen, &uidx);
-       if (err)
-               return err;
+       if (is_xrc) {
+               err = get_srq_user_index(to_mucontext(pd->uobject->context),
+                                        &ucmd, udata->inlen, &uidx);
+               if (err)
+                       return err;
+       }
 
        srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE);
 
@@ -151,7 +149,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
        (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
        (*in)->ctx.pgoff_cqn = cpu_to_be32(offset << 26);
 
-       if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) {
+       if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) &&
+            is_xrc){
                xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in,
                                     xrc_srq_context_entry);
                MLX5_SET(xrc_srqc, xsrqc, user_index, uidx);
@@ -170,7 +169,7 @@ err_umem:
 
 static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
                             struct mlx5_create_srq_mbox_in **in, int buf_size,
-                            int *inlen)
+                            int *inlen, int is_xrc)
 {
        int err;
        int i;
@@ -224,7 +223,8 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
 
        (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
 
-       if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) {
+       if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) &&
+            is_xrc){
                xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in,
                                     xrc_srq_context_entry);
                /* 0xffffff means we ask to work with cqe version 0 */
@@ -302,10 +302,14 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
                    desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs,
                    srq->msrq.max_avail_gather);
 
+       is_xrc = (init_attr->srq_type == IB_SRQT_XRC);
+
        if (pd->uobject)
-               err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen);
+               err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen,
+                                     is_xrc);
        else
-               err = create_srq_kernel(dev, srq, &in, buf_size, &inlen);
+               err = create_srq_kernel(dev, srq, &in, buf_size, &inlen,
+                                       is_xrc);
 
        if (err) {
                mlx5_ib_warn(dev, "create srq %s failed, err %d\n",
@@ -313,7 +317,6 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
                goto err_srq;
        }
 
-       is_xrc = (init_attr->srq_type == IB_SRQT_XRC);
        in->ctx.state_log_sz = ilog2(srq->msrq.max);
        flgs = ((srq->msrq.wqe_shift - 4) | (is_xrc << 5) | (srq->wq_sig << 7)) << 24;
        xrcdn = 0;
index 040bb8b5cb15a65c34b15ab67c3c5fe14e27524c..12503f15fbd6b29830dee04d81f8fd4082319be2 100644 (file)
@@ -323,9 +323,6 @@ struct ocrdma_cq {
                         */
        u32 max_hw_cqe;
        bool phase_change;
-       bool deferred_arm, deferred_sol;
-       bool first_arm;
-
        spinlock_t cq_lock ____cacheline_aligned; /* provide synchronization
                                                   * to cq polling
                                                   */
index 573849354cb94f4ef6f46397266518f9aaf7ef7b..f38743018cb454bca0e42440ebd27071e16a1ffe 100644 (file)
@@ -228,6 +228,11 @@ static int ocrdma_alloc_resources(struct ocrdma_dev *dev)
 
        ocrdma_alloc_pd_pool(dev);
 
+       if (!ocrdma_alloc_stats_resources(dev)) {
+               pr_err("%s: stats resource allocation failed\n", __func__);
+               goto alloc_err;
+       }
+
        spin_lock_init(&dev->av_tbl.lock);
        spin_lock_init(&dev->flush_q_lock);
        return 0;
@@ -238,6 +243,7 @@ alloc_err:
 
 static void ocrdma_free_resources(struct ocrdma_dev *dev)
 {
+       ocrdma_release_stats_resources(dev);
        kfree(dev->stag_arr);
        kfree(dev->qp_tbl);
        kfree(dev->cq_tbl);
index 86c303a620c1660625ebb94f1b54e578856b26ff..255f774080a4aae08952df0374cdcb5a4063c8d1 100644 (file)
@@ -64,10 +64,11 @@ static int ocrdma_add_stat(char *start, char *pcur,
        return cpy_len;
 }
 
-static bool ocrdma_alloc_stats_mem(struct ocrdma_dev *dev)
+bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev)
 {
        struct stats_mem *mem = &dev->stats_mem;
 
+       mutex_init(&dev->stats_lock);
        /* Alloc mbox command mem*/
        mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req),
                        sizeof(struct ocrdma_rdma_stats_resp));
@@ -91,13 +92,14 @@ static bool ocrdma_alloc_stats_mem(struct ocrdma_dev *dev)
        return true;
 }
 
-static void ocrdma_release_stats_mem(struct ocrdma_dev *dev)
+void ocrdma_release_stats_resources(struct ocrdma_dev *dev)
 {
        struct stats_mem *mem = &dev->stats_mem;
 
        if (mem->va)
                dma_free_coherent(&dev->nic_info.pdev->dev, mem->size,
                                  mem->va, mem->pa);
+       mem->va = NULL;
        kfree(mem->debugfs_mem);
 }
 
@@ -838,15 +840,9 @@ void ocrdma_add_port_stats(struct ocrdma_dev *dev)
                                &dev->reset_stats, &ocrdma_dbg_ops))
                goto err;
 
-       /* Now create dma_mem for stats mbx command */
-       if (!ocrdma_alloc_stats_mem(dev))
-               goto err;
-
-       mutex_init(&dev->stats_lock);
 
        return;
 err:
-       ocrdma_release_stats_mem(dev);
        debugfs_remove_recursive(dev->dir);
        dev->dir = NULL;
 }
@@ -855,9 +851,7 @@ void ocrdma_rem_port_stats(struct ocrdma_dev *dev)
 {
        if (!dev->dir)
                return;
-       debugfs_remove(dev->dir);
-       mutex_destroy(&dev->stats_lock);
-       ocrdma_release_stats_mem(dev);
+       debugfs_remove_recursive(dev->dir);
 }
 
 void ocrdma_init_debugfs(void)
index c9e58d04c7b8d15c15c5d8ae4205c87cc3be521c..bba1fec4f11f265bd88f376dde4c9474634063e6 100644 (file)
@@ -65,6 +65,8 @@ enum OCRDMA_STATS_TYPE {
 
 void ocrdma_rem_debugfs(void);
 void ocrdma_init_debugfs(void);
+bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev);
+void ocrdma_release_stats_resources(struct ocrdma_dev *dev);
 void ocrdma_rem_port_stats(struct ocrdma_dev *dev);
 void ocrdma_add_port_stats(struct ocrdma_dev *dev);
 int ocrdma_pma_counters(struct ocrdma_dev *dev,
index d4c687b548d8696e66752da16a28f03d2481cd60..12420e4ecf3da09d552ac117adcd85049ccd891b 100644 (file)
@@ -125,8 +125,8 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
                                        IB_DEVICE_SYS_IMAGE_GUID |
                                        IB_DEVICE_LOCAL_DMA_LKEY |
                                        IB_DEVICE_MEM_MGT_EXTENSIONS;
-       attr->max_sge = min(dev->attr.max_send_sge, dev->attr.max_srq_sge);
-       attr->max_sge_rd = 0;
+       attr->max_sge = dev->attr.max_send_sge;
+       attr->max_sge_rd = attr->max_sge;
        attr->max_cq = dev->attr.max_cq;
        attr->max_cqe = dev->attr.max_cqe;
        attr->max_mr = dev->attr.max_mr;
@@ -1094,7 +1094,6 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev,
        spin_lock_init(&cq->comp_handler_lock);
        INIT_LIST_HEAD(&cq->sq_head);
        INIT_LIST_HEAD(&cq->rq_head);
-       cq->first_arm = true;
 
        if (ib_ctx) {
                uctx = get_ocrdma_ucontext(ib_ctx);
@@ -2726,8 +2725,7 @@ static int ocrdma_update_ud_rcqe(struct ib_wc *ibwc, struct ocrdma_cqe *cqe)
                OCRDMA_CQE_UD_STATUS_MASK) >> OCRDMA_CQE_UD_STATUS_SHIFT;
        ibwc->src_qp = le32_to_cpu(cqe->flags_status_srcqpn) &
                                                OCRDMA_CQE_SRCQP_MASK;
-       ibwc->pkey_index = le32_to_cpu(cqe->ud.rxlen_pkey) &
-                                               OCRDMA_CQE_PKEY_MASK;
+       ibwc->pkey_index = 0;
        ibwc->wc_flags = IB_WC_GRH;
        ibwc->byte_len = (le32_to_cpu(cqe->ud.rxlen_pkey) >>
                                        OCRDMA_CQE_UD_XFER_LEN_SHIFT);
@@ -2911,12 +2909,9 @@ expand_cqe:
        }
 stop_cqe:
        cq->getp = cur_getp;
-       if (cq->deferred_arm || polled_hw_cqes) {
-               ocrdma_ring_cq_db(dev, cq->id, cq->deferred_arm,
-                                 cq->deferred_sol, polled_hw_cqes);
-               cq->deferred_arm = false;
-               cq->deferred_sol = false;
-       }
+
+       if (polled_hw_cqes)
+               ocrdma_ring_cq_db(dev, cq->id, false, false, polled_hw_cqes);
 
        return i;
 }
@@ -3000,13 +2995,7 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags)
        if (cq_flags & IB_CQ_SOLICITED)
                sol_needed = true;
 
-       if (cq->first_arm) {
-               ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0);
-               cq->first_arm = false;
-       }
-
-       cq->deferred_arm = true;
-       cq->deferred_sol = sol_needed;
+       ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0);
        spin_unlock_irqrestore(&cq->cq_lock, flags);
 
        return 0;
index 5ea0c14070d1f2d8af36a05c15206c63f406b97d..fa9c42ff1fb00963a47a71868ff96abb6e15189b 100644 (file)
@@ -245,8 +245,6 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        skb_reset_mac_header(skb);
        skb_pull(skb, IPOIB_ENCAP_LEN);
 
-       skb->truesize = SKB_TRUESIZE(skb->len);
-
        ++dev->stats.rx_packets;
        dev->stats.rx_bytes += skb->len;
 
index 050dfa175d169dd3f77ee83767f1988062989891..25889311b1e9c8db412f784a77de5aa8ef0a29cb 100644 (file)
@@ -456,7 +456,10 @@ out_locked:
        return status;
 }
 
-static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
+/*
+ * Caller must hold 'priv->lock'
+ */
+static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ib_sa_multicast *multicast;
@@ -466,6 +469,10 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
        ib_sa_comp_mask comp_mask;
        int ret = 0;
 
+       if (!priv->broadcast ||
+           !test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+               return -EINVAL;
+
        ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw);
 
        rec.mgid     = mcast->mcmember.mgid;
@@ -525,20 +532,23 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
                        rec.join_state = 4;
 #endif
        }
+       spin_unlock_irq(&priv->lock);
 
        multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
                                         &rec, comp_mask, GFP_KERNEL,
                                         ipoib_mcast_join_complete, mcast);
+       spin_lock_irq(&priv->lock);
        if (IS_ERR(multicast)) {
                ret = PTR_ERR(multicast);
                ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
-               spin_lock_irq(&priv->lock);
                /* Requeue this join task with a backoff delay */
                __ipoib_mcast_schedule_join_thread(priv, mcast, 1);
                clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
                spin_unlock_irq(&priv->lock);
                complete(&mcast->done);
+               spin_lock_irq(&priv->lock);
        }
+       return 0;
 }
 
 void ipoib_mcast_join_task(struct work_struct *work)
@@ -620,9 +630,10 @@ void ipoib_mcast_join_task(struct work_struct *work)
                                /* Found the next unjoined group */
                                init_completion(&mcast->done);
                                set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-                               spin_unlock_irq(&priv->lock);
-                               ipoib_mcast_join(dev, mcast);
-                               spin_lock_irq(&priv->lock);
+                               if (ipoib_mcast_join(dev, mcast)) {
+                                       spin_unlock_irq(&priv->lock);
+                                       return;
+                               }
                        } else if (!delay_until ||
                                 time_before(mcast->delay_until, delay_until))
                                delay_until = mcast->delay_until;
@@ -641,10 +652,9 @@ out:
        if (mcast) {
                init_completion(&mcast->done);
                set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               ipoib_mcast_join(dev, mcast);
        }
        spin_unlock_irq(&priv->lock);
-       if (mcast)
-               ipoib_mcast_join(dev, mcast);
 }
 
 int ipoib_mcast_start_thread(struct net_device *dev)
index 6727954ab74be9338e9c3d46e12a55fa3db7a6e7..e8a84d12b7fffe812cd329a88da26f6922c219af 100644 (file)
@@ -1207,7 +1207,6 @@ static void xpad_led_disconnect(struct usb_xpad *xpad)
 #else
 static int xpad_led_probe(struct usb_xpad *xpad) { return 0; }
 static void xpad_led_disconnect(struct usb_xpad *xpad) { }
-static void xpad_identify_controller(struct usb_xpad *xpad) { }
 #endif
 
 static int xpad_start_input(struct usb_xpad *xpad)
index 4d446d5085aad9b110ca7ecb05a3167f859ef12c..c01a1d648f9f087df57aafedf7eb3e56b4df2b8e 100644 (file)
@@ -235,7 +235,7 @@ struct adp5589_kpad {
        unsigned short gpimapsize;
        unsigned extend_cfg;
        bool is_adp5585;
-       bool adp5585_support_row5;
+       bool support_row5;
 #ifdef CONFIG_GPIOLIB
        unsigned char gpiomap[ADP5589_MAXGPIO];
        bool export_gpio;
@@ -485,7 +485,7 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad,
        if (kpad->extend_cfg & C4_EXTEND_CFG)
                pin_used[kpad->var->c4_extend_cfg] = true;
 
-       if (!kpad->adp5585_support_row5)
+       if (!kpad->support_row5)
                pin_used[5] = true;
 
        for (i = 0; i < kpad->var->maxgpio; i++)
@@ -884,12 +884,13 @@ static int adp5589_probe(struct i2c_client *client,
 
        switch (id->driver_data) {
        case ADP5585_02:
-               kpad->adp5585_support_row5 = true;
+               kpad->support_row5 = true;
        case ADP5585_01:
                kpad->is_adp5585 = true;
                kpad->var = &const_adp5585;
                break;
        case ADP5589:
+               kpad->support_row5 = true;
                kpad->var = &const_adp5589;
                break;
        }
index 378db10001df5067adcf4fe5bfc2b38e42098574..4401be225d64b28b8ffa798ba71cce07c8a81282 100644 (file)
@@ -304,8 +304,10 @@ static int cap11xx_init_leds(struct device *dev,
                led->cdev.brightness = LED_OFF;
 
                error = of_property_read_u32(child, "reg", &reg);
-               if (error != 0 || reg >= num_leds)
+               if (error != 0 || reg >= num_leds) {
+                       of_node_put(child);
                        return -EINVAL;
+               }
 
                led->reg = reg;
                led->priv = priv;
@@ -313,8 +315,10 @@ static int cap11xx_init_leds(struct device *dev,
                INIT_WORK(&led->work, cap11xx_led_work);
 
                error = devm_led_classdev_register(dev, &led->cdev);
-               if (error)
+               if (error) {
+                       of_node_put(child);
                        return error;
+               }
 
                priv->num_leds++;
                led++;
index d6d16fa782815481e04609771b09b32e862ce679..1f2337abcf2f333de7b10cc449aaad56aadd5369 100644 (file)
@@ -733,7 +733,7 @@ config INPUT_XEN_KBDDEV_FRONTEND
          module will be called xen-kbdfront.
 
 config INPUT_SIRFSOC_ONKEY
-       bool "CSR SiRFSoC power on/off/suspend key support"
+       tristate "CSR SiRFSoC power on/off/suspend key support"
        depends on ARCH_SIRF && OF
        default y
        help
index 9d5b89befe6fb059e593c6fe1e6265f0b3819199..ed7237f1953966c378c3822faa9a40f7c6a044dd 100644 (file)
@@ -101,7 +101,7 @@ static void sirfsoc_pwrc_close(struct input_dev *input)
 static const struct of_device_id sirfsoc_pwrc_of_match[] = {
        { .compatible = "sirf,prima2-pwrc" },
        {},
-}
+};
 MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match);
 
 static int sirfsoc_pwrc_probe(struct platform_device *pdev)
index e272f06258cefb3c2119058298ad10f2cb77b7ce..a3f0f5a47490e936e31b45594861d692503429b1 100644 (file)
@@ -458,8 +458,6 @@ int vmmouse_init(struct psmouse *psmouse)
        priv->abs_dev = abs_dev;
        psmouse->private = priv;
 
-       input_set_capability(rel_dev, EV_REL, REL_WHEEL);
-
        /* Set up and register absolute device */
        snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
                 psmouse->ps2dev.serio->phys);
@@ -475,10 +473,6 @@ int vmmouse_init(struct psmouse *psmouse)
        abs_dev->id.version = psmouse->model;
        abs_dev->dev.parent = &psmouse->ps2dev.serio->dev;
 
-       error = input_register_device(priv->abs_dev);
-       if (error)
-               goto init_fail;
-
        /* Set absolute device capabilities */
        input_set_capability(abs_dev, EV_KEY, BTN_LEFT);
        input_set_capability(abs_dev, EV_KEY, BTN_RIGHT);
@@ -488,6 +482,13 @@ int vmmouse_init(struct psmouse *psmouse)
        input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0);
        input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0);
 
+       error = input_register_device(priv->abs_dev);
+       if (error)
+               goto init_fail;
+
+       /* Add wheel capability to the relative device */
+       input_set_capability(rel_dev, EV_REL, REL_WHEEL);
+
        psmouse->protocol_handler = vmmouse_process_byte;
        psmouse->disconnect = vmmouse_disconnect;
        psmouse->reconnect = vmmouse_reconnect;
index 8f828975ab10b03746e700dd26dce1cb03d2c17e..1ca7f551e2dabe73896f780ec53e4c6735d13019 100644 (file)
@@ -134,7 +134,7 @@ static void serio_find_driver(struct serio *serio)
        int error;
 
        error = device_attach(&serio->dev);
-       if (error < 0)
+       if (error < 0 && error != -EPROBE_DEFER)
                dev_warn(&serio->dev,
                         "device_attach() failed for %s (%s), error: %d\n",
                         serio->phys, serio->name, error);
index 5d4903a402cc6a5f183010ded6e7af17c1136a49..69828d015d45ffa4747368e79f6fa5f47108c0c9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 0b0f8c17f3f7e0f4df1e69144d693b46741f4025..23fbe382da8b420791a1fec28962454132d4e7ef 100644 (file)
@@ -822,16 +822,22 @@ static void edt_ft5x06_ts_get_defaults(struct device *dev,
        int error;
 
        error = device_property_read_u32(dev, "threshold", &val);
-       if (!error)
-               reg_addr->reg_threshold = val;
+       if (!error) {
+               edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, val);
+               tsdata->threshold = val;
+       }
 
        error = device_property_read_u32(dev, "gain", &val);
-       if (!error)
-               reg_addr->reg_gain = val;
+       if (!error) {
+               edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, val);
+               tsdata->gain = val;
+       }
 
        error = device_property_read_u32(dev, "offset", &val);
-       if (!error)
-               reg_addr->reg_offset = val;
+       if (!error) {
+               edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, val);
+               tsdata->offset = val;
+       }
 }
 
 static void
index e5e223938eecc9f013e33977b1de50bbb3cfae3d..374c129219ef0c48c8ff3004662c413d78ad2b4c 100644 (file)
@@ -114,6 +114,7 @@ struct kmem_cache *amd_iommu_irq_cache;
 
 static void update_domain(struct protection_domain *domain);
 static int protection_domain_init(struct protection_domain *domain);
+static void detach_device(struct device *dev);
 
 /*
  * For dynamic growth the aperture size is split into ranges of 128MB of
@@ -384,6 +385,9 @@ static void iommu_uninit_device(struct device *dev)
        if (!dev_data)
                return;
 
+       if (dev_data->domain)
+               detach_device(dev);
+
        iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
                            dev);
 
index 013bdfff2d4d023c30a57baf4c833788bfd7dbee..bf4959f4225bd35c356c49172e0f978e0c81166f 100644 (file)
@@ -228,6 +228,10 @@ static int amd_iommu_enable_interrupts(void);
 static int __init iommu_go_to_state(enum iommu_init_state state);
 static void init_device_table_dma(void);
 
+static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
+                                   u8 bank, u8 cntr, u8 fxn,
+                                   u64 *value, bool is_write);
+
 static inline void update_last_devid(u16 devid)
 {
        if (devid > amd_iommu_last_bdf)
@@ -1015,6 +1019,34 @@ static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
        pci_write_config_dword(iommu->dev, 0xf0, 0x90);
 }
 
+/*
+ * Family15h Model 30h-3fh (IOMMU Mishandles ATS Write Permission)
+ * Workaround:
+ *     BIOS should enable ATS write permission check by setting
+ *     L2_DEBUG_3[AtsIgnoreIWDis](D0F2xF4_x47[0]) = 1b
+ */
+static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu)
+{
+       u32 value;
+
+       if ((boot_cpu_data.x86 != 0x15) ||
+           (boot_cpu_data.x86_model < 0x30) ||
+           (boot_cpu_data.x86_model > 0x3f))
+               return;
+
+       /* Test L2_DEBUG_3[AtsIgnoreIWDis] == 1 */
+       value = iommu_read_l2(iommu, 0x47);
+
+       if (value & BIT(0))
+               return;
+
+       /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */
+       iommu_write_l2(iommu, 0x47, value | BIT(0));
+
+       pr_info("AMD-Vi: Applying ATS write check workaround for IOMMU at %s\n",
+               dev_name(&iommu->dev->dev));
+}
+
 /*
  * This function clues the initialization function for one IOMMU
  * together and also allocates the command buffer and programs the
@@ -1142,8 +1174,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu)
        amd_iommu_pc_present = true;
 
        /* Check if the performance counters can be written to */
-       if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) ||
-           (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) ||
+       if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) ||
+           (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) ||
            (val != val2)) {
                pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
                amd_iommu_pc_present = false;
@@ -1284,6 +1316,7 @@ static int iommu_init_pci(struct amd_iommu *iommu)
        }
 
        amd_iommu_erratum_746_workaround(iommu);
+       amd_iommu_ats_write_check_workaround(iommu);
 
        iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
                                               amd_iommu_groups, "ivhd%d",
@@ -2283,22 +2316,15 @@ u8 amd_iommu_pc_get_max_counters(u16 devid)
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
 
-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
+static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
+                                   u8 bank, u8 cntr, u8 fxn,
                                    u64 *value, bool is_write)
 {
-       struct amd_iommu *iommu;
        u32 offset;
        u32 max_offset_lim;
 
-       /* Make sure the IOMMU PC resource is available */
-       if (!amd_iommu_pc_present)
-               return -ENODEV;
-
-       /* Locate the iommu associated with the device ID */
-       iommu = amd_iommu_rlookup_table[devid];
-
        /* Check for valid iommu and pc register indexing */
-       if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7)))
+       if (WARN_ON((fxn > 0x28) || (fxn & 7)))
                return -ENODEV;
 
        offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn);
@@ -2322,3 +2348,16 @@ int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
        return 0;
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
+
+int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
+                                   u64 *value, bool is_write)
+{
+       struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+       /* Make sure the IOMMU PC resource is available */
+       if (!amd_iommu_pc_present || iommu == NULL)
+               return -ENODEV;
+
+       return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn,
+                                       value, is_write);
+}
index 62a400c5ba0614fde00d18ad2207b430d99433ee..8ffd7568fc919e32b97354b2777db21be263d37f 100644 (file)
@@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        /* Only care about add/remove events for physical functions */
        if (pdev->is_virtfn)
                return NOTIFY_DONE;
-       if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE)
+       if (action != BUS_NOTIFY_ADD_DEVICE &&
+           action != BUS_NOTIFY_REMOVED_DEVICE)
                return NOTIFY_DONE;
 
        info = dmar_alloc_pci_notify_info(pdev, action);
@@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        down_write(&dmar_global_lock);
        if (action == BUS_NOTIFY_ADD_DEVICE)
                dmar_pci_bus_add_dev(info);
-       else if (action == BUS_NOTIFY_DEL_DEVICE)
+       else if (action == BUS_NOTIFY_REMOVED_DEVICE)
                dmar_pci_bus_del_dev(info);
        up_write(&dmar_global_lock);
 
@@ -1353,7 +1354,7 @@ void dmar_disable_qi(struct intel_iommu *iommu)
 
        raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
-       sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
+       sts =  readl(iommu->reg + DMAR_GSTS_REG);
        if (!(sts & DMA_GSTS_QIES))
                goto end;
 
index 986a53e3eb96b4bb56faedfdb36b4bd658aacb99..a2e1b7f14df29cc78b625ec88455438d0fa1fe07 100644 (file)
@@ -4367,7 +4367,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
                                rmrru->devices_cnt);
                        if(ret < 0)
                                return ret;
-               } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
+               } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
                        dmar_remove_dev_scope(info, rmrr->segment,
                                rmrru->devices, rmrru->devices_cnt);
                }
@@ -4387,7 +4387,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
                                break;
                        else if(ret < 0)
                                return ret;
-               } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
+               } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
                        if (dmar_remove_dev_scope(info, atsr->segment,
                                        atsru->devices, atsru->devices_cnt))
                                break;
index 50464833d0b84732a4d397cee8b73ed43a721712..d9939fa9b58887567d1fe8a7a94c7e5f1452cdf0 100644 (file)
@@ -249,12 +249,30 @@ static void intel_flush_pasid_dev(struct intel_svm *svm, struct intel_svm_dev *s
 static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
 {
        struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
+       struct intel_svm_dev *sdev;
 
+       /* This might end up being called from exit_mmap(), *before* the page
+        * tables are cleared. And __mmu_notifier_release() will delete us from
+        * the list of notifiers so that our invalidate_range() callback doesn't
+        * get called when the page tables are cleared. So we need to protect
+        * against hardware accessing those page tables.
+        *
+        * We do it by clearing the entry in the PASID table and then flushing
+        * the IOTLB and the PASID table caches. This might upset hardware;
+        * perhaps we'll want to point the PASID to a dummy PGD (like the zero
+        * page) so that we end up taking a fault that the hardware really
+        * *has* to handle gracefully without affecting other processes.
+        */
        svm->iommu->pasid_table[svm->pasid].val = 0;
+       wmb();
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdev, &svm->devs, list) {
+               intel_flush_pasid_dev(svm, sdev, svm->pasid);
+               intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+       }
+       rcu_read_unlock();
 
-       /* There's no need to do any flush because we can't get here if there
-        * are any devices left anyway. */
-       WARN_ON(!list_empty(&svm->devs));
 }
 
 static const struct mmu_notifier_ops intel_mmuops = {
@@ -379,7 +397,6 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
                                goto out;
                        }
                        iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1;
-                       mm = NULL;
                } else
                        iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11);
                wmb();
@@ -442,11 +459,11 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
                                kfree_rcu(sdev, rcu);
 
                                if (list_empty(&svm->devs)) {
-                                       mmu_notifier_unregister(&svm->notifier, svm->mm);
 
                                        idr_remove(&svm->iommu->pasid_idr, svm->pasid);
                                        if (svm->mm)
-                                               mmput(svm->mm);
+                                               mmu_notifier_unregister(&svm->notifier, svm->mm);
+
                                        /* We mandate that no page faults may be outstanding
                                         * for the PASID when intel_svm_unbind_mm() is called.
                                         * If that is not obeyed, subtle errors will happen.
@@ -507,6 +524,10 @@ static irqreturn_t prq_event_thread(int irq, void *d)
        struct intel_svm *svm = NULL;
        int head, tail, handled = 0;
 
+       /* Clear PPR bit before reading head/tail registers, to
+        * ensure that we get a new interrupt if needed. */
+       writel(DMA_PRS_PPR, iommu->reg + DMAR_PRS_REG);
+
        tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
        head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
        while (head != tail) {
@@ -551,6 +572,9 @@ static irqreturn_t prq_event_thread(int irq, void *d)
                 * any faults on kernel addresses. */
                if (!svm->mm)
                        goto bad_req;
+               /* If the mm is already defunct, don't handle faults. */
+               if (!atomic_inc_not_zero(&svm->mm->mm_users))
+                       goto bad_req;
                down_read(&svm->mm->mmap_sem);
                vma = find_extend_vma(svm->mm, address);
                if (!vma || address < vma->vm_start)
@@ -567,6 +591,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
                result = QI_RESP_SUCCESS;
        invalid:
                up_read(&svm->mm->mmap_sem);
+               mmput(svm->mm);
        bad_req:
                /* Accounting for major/minor faults? */
                rcu_read_lock();
index c12ba4516df25b7201731b44ef4a175c78f2d0e0..ac596928f6b40af32e9c44ecf388ebf7ed4b10ed 100644 (file)
@@ -629,7 +629,7 @@ static void iommu_disable_irq_remapping(struct intel_iommu *iommu)
 
        raw_spin_lock_irqsave(&iommu->register_lock, flags);
 
-       sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
+       sts = readl(iommu->reg + DMAR_GSTS_REG);
        if (!(sts & DMA_GSTS_IRES))
                goto end;
 
index 3447549fcc9306a37e7695d27e06589d45d3d0e4..43dfd15c1dd22e4e18b1dbb37e1b3da811b0ceaf 100644 (file)
@@ -66,7 +66,10 @@ struct its_node {
        unsigned long           phys_base;
        struct its_cmd_block    *cmd_base;
        struct its_cmd_block    *cmd_write;
-       void                    *tables[GITS_BASER_NR_REGS];
+       struct {
+               void            *base;
+               u32             order;
+       } tables[GITS_BASER_NR_REGS];
        struct its_collection   *collections;
        struct list_head        its_device_list;
        u64                     flags;
@@ -75,6 +78,9 @@ struct its_node {
 
 #define ITS_ITT_ALIGN          SZ_256
 
+/* Convert page order to size in bytes */
+#define PAGE_ORDER_TO_SIZE(o)  (PAGE_SIZE << (o))
+
 struct event_lpi_map {
        unsigned long           *lpi_map;
        u16                     *col_map;
@@ -597,11 +603,6 @@ static void its_unmask_irq(struct irq_data *d)
        lpi_set_config(d, true);
 }
 
-static void its_eoi_irq(struct irq_data *d)
-{
-       gic_write_eoir(d->hwirq);
-}
-
 static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
                            bool force)
 {
@@ -638,7 +639,7 @@ static struct irq_chip its_irq_chip = {
        .name                   = "ITS",
        .irq_mask               = its_mask_irq,
        .irq_unmask             = its_unmask_irq,
-       .irq_eoi                = its_eoi_irq,
+       .irq_eoi                = irq_chip_eoi_parent,
        .irq_set_affinity       = its_set_affinity,
        .irq_compose_msi_msg    = its_irq_compose_msi_msg,
 };
@@ -807,9 +808,10 @@ static void its_free_tables(struct its_node *its)
        int i;
 
        for (i = 0; i < GITS_BASER_NR_REGS; i++) {
-               if (its->tables[i]) {
-                       free_page((unsigned long)its->tables[i]);
-                       its->tables[i] = NULL;
+               if (its->tables[i].base) {
+                       free_pages((unsigned long)its->tables[i].base,
+                                  its->tables[i].order);
+                       its->tables[i].base = NULL;
                }
        }
 }
@@ -842,7 +844,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
                u64 type = GITS_BASER_TYPE(val);
                u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
                int order = get_order(psz);
-               int alloc_size;
                int alloc_pages;
                u64 tmp;
                void *base;
@@ -874,9 +875,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
                        }
                }
 
-               alloc_size = (1 << order) * PAGE_SIZE;
 retry_alloc_baser:
-               alloc_pages = (alloc_size / psz);
+               alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
                if (alloc_pages > GITS_BASER_PAGES_MAX) {
                        alloc_pages = GITS_BASER_PAGES_MAX;
                        order = get_order(GITS_BASER_PAGES_MAX * psz);
@@ -890,7 +890,8 @@ retry_alloc_baser:
                        goto out_free;
                }
 
-               its->tables[i] = base;
+               its->tables[i].base = base;
+               its->tables[i].order = order;
 
 retry_baser:
                val = (virt_to_phys(base)                                |
@@ -928,7 +929,7 @@ retry_baser:
                        shr = tmp & GITS_BASER_SHAREABILITY_MASK;
                        if (!shr) {
                                cache = GITS_BASER_nC;
-                               __flush_dcache_area(base, alloc_size);
+                               __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
                        }
                        goto retry_baser;
                }
@@ -940,7 +941,7 @@ retry_baser:
                         * something is horribly wrong...
                         */
                        free_pages((unsigned long)base, order);
-                       its->tables[i] = NULL;
+                       its->tables[i].base = NULL;
 
                        switch (psz) {
                        case SZ_16K:
@@ -961,7 +962,7 @@ retry_baser:
                }
 
                pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
-                       (int)(alloc_size / entry_size),
+                       (int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
                        its_base_type_string[type],
                        (unsigned long)virt_to_phys(base),
                        psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
index 911758c056c14152d5a248110c14f35bd48e9b78..8f9ebf714e2bbc154d7a045d27920f6c95f7cce6 100644 (file)
@@ -384,9 +384,6 @@ static struct irq_chip gic_chip = {
        .irq_unmask             = gic_unmask_irq,
        .irq_eoi                = gic_eoi_irq,
        .irq_set_type           = gic_set_type,
-#ifdef CONFIG_SMP
-       .irq_set_affinity       = gic_set_affinity,
-#endif
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
        .flags                  = IRQCHIP_SET_TYPE_MASKED |
@@ -400,9 +397,6 @@ static struct irq_chip gic_eoimode1_chip = {
        .irq_unmask             = gic_unmask_irq,
        .irq_eoi                = gic_eoimode1_eoi_irq,
        .irq_set_type           = gic_set_type,
-#ifdef CONFIG_SMP
-       .irq_set_affinity       = gic_set_affinity,
-#endif
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
        .irq_set_vcpu_affinity  = gic_irq_set_vcpu_affinity,
@@ -443,7 +437,7 @@ static void gic_cpu_if_up(struct gic_chip_data *gic)
        u32 bypass = 0;
        u32 mode = 0;
 
-       if (static_key_true(&supports_deactivate))
+       if (gic == &gic_data[0] && static_key_true(&supports_deactivate))
                mode = GIC_CPU_CTRL_EOImodeNS;
 
        /*
@@ -1039,6 +1033,11 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
                gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
        }
 
+#ifdef CONFIG_SMP
+       if (gic_nr == 0)
+               gic->chip.irq_set_affinity = gic_set_affinity;
+#endif
+
 #ifdef CONFIG_GIC_NON_BANKED
        if (percpu_offset) { /* Frankein-GIC without banked registers... */
                unsigned int cpu;
index 0704362f4c824c6ba2b87e42353f0481bcff36e5..376b28074e0d8937c43036b647de218ef45c14b7 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_irq.h>
 
 #include <asm/exception.h>
-#include <asm/mach/irq.h>
 
 #define SUN4I_IRQ_VECTOR_REG           0x00
 #define SUN4I_IRQ_PROTECTION_REG       0x08
index 2a506fe0c8a4500a16e83b1aba70a6ed2d192185..d1f8ab915b15cc69b5fc9564777d413dad0f8318 100644 (file)
@@ -373,13 +373,7 @@ static void gigaset_freecshw(struct cardstate *cs)
 
 static void gigaset_device_release(struct device *dev)
 {
-       struct cardstate *cs = dev_get_drvdata(dev);
-
-       if (!cs)
-               return;
-       dev_set_drvdata(dev, NULL);
-       kfree(cs->hw.ser);
-       cs->hw.ser = NULL;
+       kfree(container_of(dev, struct ser_cardstate, dev.dev));
 }
 
 /*
@@ -408,7 +402,6 @@ static int gigaset_initcshw(struct cardstate *cs)
                cs->hw.ser = NULL;
                return rc;
        }
-       dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
 
        tasklet_init(&cs->write_tasklet,
                     gigaset_modem_fill, (unsigned long) cs);
index 8e2944784e0004e4fc933d691607c4e822c3bf66..afde4edef9ae895fa009fb5ad7305cc13af2c22e 100644 (file)
@@ -392,7 +392,7 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
        }
        stat = bchannel_get_rxbuf(&bc->bch, cnt);
        /* only transparent use the count here, HDLC overun is detected later */
-       if (stat == ENOMEM) {
+       if (stat == -ENOMEM) {
                pr_warning("%s.B%d: No memory for %d bytes\n",
                           card->name, bc->bch.nr, cnt);
                return;
index 33224cb91c5bb98ac7e464b4202dacbac71671c9..9f6acd5d1d2e9359730ad595f92d3e902bc40d17 100644 (file)
@@ -572,11 +572,13 @@ int nvm_register(struct request_queue *q, char *disk_name,
                }
        }
 
-       ret = nvm_get_sysblock(dev, &dev->sb);
-       if (!ret)
-               pr_err("nvm: device not initialized.\n");
-       else if (ret < 0)
-               pr_err("nvm: err (%d) on device initialization\n", ret);
+       if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) {
+               ret = nvm_get_sysblock(dev, &dev->sb);
+               if (!ret)
+                       pr_err("nvm: device not initialized.\n");
+               else if (ret < 0)
+                       pr_err("nvm: err (%d) on device initialization\n", ret);
+       }
 
        /* register device with a supported media manager */
        down_write(&nvm_lock);
@@ -1055,9 +1057,11 @@ static long __nvm_ioctl_dev_init(struct nvm_ioctl_dev_init *init)
        strncpy(info.mmtype, init->mmtype, NVM_MMTYPE_LEN);
        info.fs_ppa.ppa = -1;
 
-       ret = nvm_init_sysblock(dev, &info);
-       if (ret)
-               return ret;
+       if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) {
+               ret = nvm_init_sysblock(dev, &info);
+               if (ret)
+                       return ret;
+       }
 
        memcpy(&dev->sb, &info, sizeof(struct nvm_sb_info));
 
@@ -1117,7 +1121,10 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg)
                dev->mt = NULL;
        }
 
-       return nvm_dev_factory(dev, fact.flags);
+       if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT)
+               return nvm_dev_factory(dev, fact.flags);
+
+       return 0;
 }
 
 static long nvm_ctl_ioctl(struct file *file, uint cmd, unsigned long arg)
index d8c75958ced346d5aede0398a8f4b50bd96fa749..307db1ea22defbcbddcfdc3d63cfe86bda43fa0c 100644 (file)
@@ -300,8 +300,10 @@ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk)
        }
 
        page = mempool_alloc(rrpc->page_pool, GFP_NOIO);
-       if (!page)
+       if (!page) {
+               bio_put(bio);
                return -ENOMEM;
+       }
 
        while ((slot = find_first_zero_bit(rblk->invalid_pages,
                                            nr_pgs_per_blk)) < nr_pgs_per_blk) {
index ef13ac7700c80e352b8db97fed8c1e38ba504cc9..f7b37336353fd56771f776ed420ff07521f2b6d5 100644 (file)
@@ -174,8 +174,7 @@ static inline sector_t rrpc_get_sector(sector_t laddr)
 static inline int request_intersects(struct rrpc_inflight_rq *r,
                                sector_t laddr_start, sector_t laddr_end)
 {
-       return (laddr_end >= r->l_start && laddr_end <= r->l_end) &&
-               (laddr_start >= r->l_start && laddr_start <= r->l_end);
+       return (laddr_end >= r->l_start) && (laddr_start <= r->l_end);
 }
 
 static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr,
@@ -184,6 +183,8 @@ static int __rrpc_lock_laddr(struct rrpc *rrpc, sector_t laddr,
        sector_t laddr_end = laddr + pages - 1;
        struct rrpc_inflight_rq *rtmp;
 
+       WARN_ON(irqs_disabled());
+
        spin_lock_irq(&rrpc->inflights.lock);
        list_for_each_entry(rtmp, &rrpc->inflights.reqs, list) {
                if (unlikely(request_intersects(rtmp, laddr, laddr_end))) {
index 5df40480228b7a26e3c73ac78e963ce47ed25448..dd834927bc66e87bf4ec433bc96889068d3bbb82 100644 (file)
@@ -1191,6 +1191,8 @@ static void dm_unprep_request(struct request *rq)
 
        if (clone)
                free_rq_clone(clone);
+       else if (!tio->md->queue->mq_ops)
+               free_rq_tio(tio);
 }
 
 /*
index 7e9cbf757e956b817e465249669b148cd9b38cb0..fb7ed730d9322fae3c8887f0db71bf16de50efa0 100644 (file)
@@ -497,7 +497,7 @@ static int adp1653_probe(struct i2c_client *client,
                if (!client->dev.platform_data) {
                        dev_err(&client->dev,
                                "Neither DT not platform data provided\n");
-                       return EINVAL;
+                       return -EINVAL;
                }
                flash->platform_data = client->dev.platform_data;
        }
index f8dd7505b5294ff167352a1d3ce8823605916db7..e1719ffdfb3db12a1dc724b189b2c4544729d785 100644 (file)
@@ -1960,10 +1960,9 @@ static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
        }
 
        /* tx 5v detect */
-       tx_5v = io_read(sd, 0x70) & info->cable_det_mask;
+       tx_5v = irq_reg_0x70 & info->cable_det_mask;
        if (tx_5v) {
                v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
-               io_write(sd, 0x71, tx_5v);
                adv76xx_s_detect_tx_5v_ctrl(sd);
                if (handled)
                        *handled = true;
index 8c54fd21022e443ee03e2f1b852208c4a03b938e..a1362572284822e7b39a009ab227137dbd8b8595 100644 (file)
@@ -1843,8 +1843,7 @@ static void au0828_analog_create_entities(struct au0828_dev *dev)
                        ent->function = MEDIA_ENT_F_CONN_RF;
                        break;
                default: /* AU0828_VMUX_DEBUG */
-                       ent->function = MEDIA_ENT_F_CONN_TEST;
-                       break;
+                       continue;
                }
 
                ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
index e6e4bacb09ee5d2636576c3363c97a1a5c5f72c8..12099b09a9a71ee5f49e61608b24734e42ca58db 100644 (file)
@@ -2048,6 +2048,7 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(db8500_prcmu_config_hotmon);
 
 static int config_hot_period(u16 val)
 {
@@ -2074,11 +2075,13 @@ int db8500_prcmu_start_temp_sense(u16 cycles32k)
 
        return config_hot_period(cycles32k);
 }
+EXPORT_SYMBOL_GPL(db8500_prcmu_start_temp_sense);
 
 int db8500_prcmu_stop_temp_sense(void)
 {
        return config_hot_period(0xFFFF);
 }
+EXPORT_SYMBOL_GPL(db8500_prcmu_stop_temp_sense);
 
 static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 {
index e11a0bd6c66e3f6068fbe032e1c67412ab09b6d3..0516ecda54d35fc6a590750a3f27e76083e80003 100644 (file)
@@ -34,6 +34,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
                if (ssc->pdev->dev.of_node) {
                        if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
                                == ssc_num) {
+                               ssc->pdev->id = ssc_num;
                                ssc_valid = 1;
                                break;
                        }
index 4c1903f781fc1793bb7ddf7205d138e60ea2133a..0c6c17a1c59e3a9417dde5ab842fffbab4f09e69 100644 (file)
@@ -415,7 +415,7 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
                delta = mftb() - psl_tb;
                if (delta < 0)
                        delta = -delta;
-       } while (cputime_to_usecs(delta) > 16);
+       } while (tb_to_ns(delta) > 16000);
 
        return 0;
 }
index 677d0362f334e842abb2c8c2439260978249b871..80f9afcb13823282a9859e08a96c36f55901efa6 100644 (file)
@@ -458,7 +458,11 @@ static int mei_ioctl_client_notify_request(struct file *file, u32 request)
 {
        struct mei_cl *cl = file->private_data;
 
-       return mei_cl_notify_request(cl, file, request);
+       if (request != MEI_HBM_NOTIFICATION_START &&
+           request != MEI_HBM_NOTIFICATION_STOP)
+               return -EINVAL;
+
+       return mei_cl_notify_request(cl, file, (u8)request);
 }
 
 /**
index 5914263090fc81447e26130baab143802504c088..fe207e5420324af3db9411902bcbedeb19e6f60f 100644 (file)
 #include "queue.h"
 
 MODULE_ALIAS("mmc:block");
-
-#ifdef KERNEL
 #ifdef MODULE_PARAM_PREFIX
 #undef MODULE_PARAM_PREFIX
 #endif
 #define MODULE_PARAM_PREFIX "mmcblk."
-#endif
 
 #define INAND_CMD38_ARG_EXT_CSD  113
 #define INAND_CMD38_ARG_ERASE    0x00
@@ -655,8 +652,10 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
        }
 
        md = mmc_blk_get(bdev->bd_disk);
-       if (!md)
+       if (!md) {
+               err = -EINVAL;
                goto cmd_err;
+       }
 
        card = md->queue.card;
        if (IS_ERR(card)) {
index 1c1b45ef3faf847d4087d61904ed18c1a6f7ce5e..3446097a43c01ca6cf7f8e163cc75dbbb3911f3f 100644 (file)
@@ -925,6 +925,10 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
 
                        dma_addr = dma_map_page(dma_dev, sg_page(sg), 0,
                                                PAGE_SIZE, dir);
+                       if (dma_mapping_error(dma_dev, dma_addr)) {
+                               data->error = -EFAULT;
+                               break;
+                       }
                        if (direction == DMA_TO_DEVICE)
                                t->tx_dma = dma_addr + sg->offset;
                        else
@@ -1393,10 +1397,12 @@ static int mmc_spi_probe(struct spi_device *spi)
                host->dma_dev = dev;
                host->ones_dma = dma_map_single(dev, ones,
                                MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE);
+               if (dma_mapping_error(dev, host->ones_dma))
+                       goto fail_ones_dma;
                host->data_dma = dma_map_single(dev, host->data,
                                sizeof(*host->data), DMA_BIDIRECTIONAL);
-
-               /* REVISIT in theory those map operations can fail... */
+               if (dma_mapping_error(dev, host->data_dma))
+                       goto fail_data_dma;
 
                dma_sync_single_for_cpu(host->dma_dev,
                                host->data_dma, sizeof(*host->data),
@@ -1462,6 +1468,11 @@ fail_glue_init:
        if (host->dma_dev)
                dma_unmap_single(host->dma_dev, host->data_dma,
                                sizeof(*host->data), DMA_BIDIRECTIONAL);
+fail_data_dma:
+       if (host->dma_dev)
+               dma_unmap_single(host->dma_dev, host->ones_dma,
+                               MMC_SPI_BLOCKSIZE, DMA_TO_DEVICE);
+fail_ones_dma:
        kfree(host->data);
 
 fail_nobuf1:
index b6639ea0bf18dbd37ccf0d639073119353b418b6..f6e4d97180359c32066ffa36d1ae99fd0f612d3d 100644 (file)
@@ -2232,6 +2232,7 @@ err_irq:
                dma_release_channel(host->tx_chan);
        if (host->rx_chan)
                dma_release_channel(host->rx_chan);
+       pm_runtime_dont_use_autosuspend(host->dev);
        pm_runtime_put_sync(host->dev);
        pm_runtime_disable(host->dev);
        if (host->dbclk)
@@ -2253,6 +2254,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
        dma_release_channel(host->tx_chan);
        dma_release_channel(host->rx_chan);
 
+       pm_runtime_dont_use_autosuspend(host->dev);
        pm_runtime_put_sync(host->dev);
        pm_runtime_disable(host->dev);
        device_init_wakeup(&pdev->dev, false);
index ce08896b9d696b00440fe7807aeddf72b922f320..da824772bbb4a37e29c33cb6c44a1be38b10c3a5 100644 (file)
@@ -86,7 +86,7 @@ struct pxamci_host {
 static inline void pxamci_init_ocr(struct pxamci_host *host)
 {
 #ifdef CONFIG_REGULATOR
-       host->vcc = regulator_get_optional(mmc_dev(host->mmc), "vmmc");
+       host->vcc = devm_regulator_get_optional(mmc_dev(host->mmc), "vmmc");
 
        if (IS_ERR(host->vcc))
                host->vcc = NULL;
@@ -654,12 +654,8 @@ static int pxamci_probe(struct platform_device *pdev)
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!r || irq < 0)
-               return -ENXIO;
-
-       r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
-       if (!r)
-               return -EBUSY;
+       if (irq < 0)
+               return irq;
 
        mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev);
        if (!mmc) {
@@ -695,7 +691,7 @@ static int pxamci_probe(struct platform_device *pdev)
        host->pdata = pdev->dev.platform_data;
        host->clkrt = CLKRT_OFF;
 
-       host->clk = clk_get(&pdev->dev, NULL);
+       host->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(host->clk)) {
                ret = PTR_ERR(host->clk);
                host->clk = NULL;
@@ -727,9 +723,9 @@ static int pxamci_probe(struct platform_device *pdev)
        host->irq = irq;
        host->imask = MMC_I_MASK_ALL;
 
-       host->base = ioremap(r->start, SZ_4K);
-       if (!host->base) {
-               ret = -ENOMEM;
+       host->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(host->base)) {
+               ret = PTR_ERR(host->base);
                goto out;
        }
 
@@ -742,7 +738,8 @@ static int pxamci_probe(struct platform_device *pdev)
        writel(64, host->base + MMC_RESTO);
        writel(host->imask, host->base + MMC_I_MASK);
 
-       ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
+       ret = devm_request_irq(&pdev->dev, host->irq, pxamci_irq, 0,
+                              DRIVER_NAME, host);
        if (ret)
                goto out;
 
@@ -804,7 +801,7 @@ static int pxamci_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
                goto out;
        } else {
-               mmc->caps |= host->pdata->gpio_card_ro_invert ?
+               mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
                        0 : MMC_CAP2_RO_ACTIVE_HIGH;
        }
 
@@ -833,14 +830,9 @@ out:
                        dma_release_channel(host->dma_chan_rx);
                if (host->dma_chan_tx)
                        dma_release_channel(host->dma_chan_tx);
-               if (host->base)
-                       iounmap(host->base);
-               if (host->clk)
-                       clk_put(host->clk);
        }
        if (mmc)
                mmc_free_host(mmc);
-       release_resource(r);
        return ret;
 }
 
@@ -859,9 +851,6 @@ static int pxamci_remove(struct platform_device *pdev)
                        gpio_ro = host->pdata->gpio_card_ro;
                        gpio_power = host->pdata->gpio_power;
                }
-               if (host->vcc)
-                       regulator_put(host->vcc);
-
                if (host->pdata && host->pdata->exit)
                        host->pdata->exit(&pdev->dev, mmc);
 
@@ -870,16 +859,10 @@ static int pxamci_remove(struct platform_device *pdev)
                       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
                       host->base + MMC_I_MASK);
 
-               free_irq(host->irq, host);
                dmaengine_terminate_all(host->dma_chan_rx);
                dmaengine_terminate_all(host->dma_chan_tx);
                dma_release_channel(host->dma_chan_rx);
                dma_release_channel(host->dma_chan_tx);
-               iounmap(host->base);
-
-               clk_put(host->clk);
-
-               release_resource(host->res);
 
                mmc_free_host(mmc);
        }
index f6047fc9406204d6ee672b74544d0ec6866308cd..a5cda926d38eb23be20eece31c6b1ef0c44723a3 100644 (file)
@@ -146,6 +146,33 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
        .ops = &sdhci_acpi_ops_int,
 };
 
+static int bxt_get_cd(struct mmc_host *mmc)
+{
+       int gpio_cd = mmc_gpio_get_cd(mmc);
+       struct sdhci_host *host = mmc_priv(mmc);
+       unsigned long flags;
+       int ret = 0;
+
+       if (!gpio_cd)
+               return 0;
+
+       pm_runtime_get_sync(mmc->parent);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       if (host->flags & SDHCI_DEVICE_DEAD)
+               goto out;
+
+       ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+out:
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       pm_runtime_mark_last_busy(mmc->parent);
+       pm_runtime_put_autosuspend(mmc->parent);
+
+       return ret;
+}
+
 static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev,
                                      const char *hid, const char *uid)
 {
@@ -196,6 +223,9 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev,
 
        /* Platform specific code during sd probe slot goes here */
 
+       if (hid && !strcmp(hid, "80865ACA"))
+               host->mmc_host_ops.get_cd = bxt_get_cd;
+
        return 0;
 }
 
index 7e7d8f0c9438fe4ac41bfb1f1759ff4fde776089..9cb86fb25976f380530fe0029015bdfaf408d743 100644 (file)
@@ -217,6 +217,7 @@ static int sdhci_at91_probe(struct platform_device *pdev)
 pm_runtime_disable:
        pm_runtime_disable(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
 clocks_disable_unprepare:
        clk_disable_unprepare(priv->gck);
        clk_disable_unprepare(priv->mainck);
index cc851b065d0ae685d5297f7e4b8ac7a40b3e3465..df3b8eced8c4a50a727774404a066086d4ebe0f7 100644 (file)
@@ -330,6 +330,33 @@ static void spt_read_drive_strength(struct sdhci_host *host)
        sdhci_pci_spt_drive_strength = 0x10 | ((val >> 12) & 0xf);
 }
 
+static int bxt_get_cd(struct mmc_host *mmc)
+{
+       int gpio_cd = mmc_gpio_get_cd(mmc);
+       struct sdhci_host *host = mmc_priv(mmc);
+       unsigned long flags;
+       int ret = 0;
+
+       if (!gpio_cd)
+               return 0;
+
+       pm_runtime_get_sync(mmc->parent);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       if (host->flags & SDHCI_DEVICE_DEAD)
+               goto out;
+
+       ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
+out:
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       pm_runtime_mark_last_busy(mmc->parent);
+       pm_runtime_put_autosuspend(mmc->parent);
+
+       return ret;
+}
+
 static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
@@ -362,6 +389,10 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
        slot->cd_con_id = NULL;
        slot->cd_idx = 0;
        slot->cd_override_level = true;
+       if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXT_SD ||
+           slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD)
+               slot->host->mmc_host_ops.get_cd = bxt_get_cd;
+
        return 0;
 }
 
index d622435d1bcc71e47e54cdb42cb847660b009a55..add9fdfd1d8feff619f70d58d581b877a668a88c 100644 (file)
@@ -1360,7 +1360,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        sdhci_runtime_pm_get(host);
 
        /* Firstly check card presence */
-       present = sdhci_do_get_cd(host);
+       present = mmc->ops->get_cd(mmc);
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -2849,6 +2849,8 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
 
        host = mmc_priv(mmc);
        host->mmc = mmc;
+       host->mmc_host_ops = sdhci_ops;
+       mmc->ops = &host->mmc_host_ops;
 
        return host;
 }
@@ -3037,7 +3039,6 @@ int sdhci_add_host(struct sdhci_host *host)
        /*
         * Set host parameters.
         */
-       mmc->ops = &sdhci_ops;
        max_clk = host->max_clk;
 
        if (host->ops->get_min_clock)
index 7654ae5d2b4e11b8b1814fa99b514223d4475d50..0115e9907bf8243aa394de60ac959e5876d5a3a9 100644 (file)
@@ -430,6 +430,7 @@ struct sdhci_host {
 
        /* Internal data */
        struct mmc_host *mmc;   /* MMC structure */
+       struct mmc_host_ops mmc_host_ops;       /* MMC host ops */
        u64 dma_mask;           /* custom DMA mask */
 
 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
index 1ca8a1359cbc1efd6a35cefb596c1c4534c77920..6234eab38ff3efe8b22b8386f4d635496dad0d08 100644 (file)
@@ -445,7 +445,7 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host)
                                                        pdata->slave_id_rx);
        } else {
                host->chan_tx = dma_request_slave_channel(dev, "tx");
-               host->chan_tx = dma_request_slave_channel(dev, "rx");
+               host->chan_rx = dma_request_slave_channel(dev, "rx");
        }
        dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx,
                host->chan_rx);
index 2a1b6e037e1a1ced496ac446ca07d6037ef61d0e..0134ba32a05784b65d1a0e6d470eee7a857df74c 100644 (file)
@@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
        vol->changing_leb = 1;
        vol->ch_lnum = req->lnum;
 
-       vol->upd_buf = vmalloc(req->bytes);
+       vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
        if (!vol->upd_buf)
                return -ENOMEM;
 
index 56b560558884dc6d87a0081d7d99c96ac4e99a67..b7f1a991903363cd6b3888722cb5742a70f0c765 100644 (file)
@@ -214,6 +214,8 @@ static void bond_uninit(struct net_device *bond_dev);
 static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
                                                struct rtnl_link_stats64 *stats);
 static void bond_slave_arr_handler(struct work_struct *work);
+static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act,
+                                 int mod);
 
 /*---------------------------- General routines -----------------------------*/
 
@@ -2127,6 +2129,7 @@ static void bond_miimon_commit(struct bonding *bond)
                        continue;
 
                case BOND_LINK_UP:
+                       bond_update_speed_duplex(slave);
                        bond_set_slave_link_state(slave, BOND_LINK_UP,
                                                  BOND_SLAVE_NOTIFY_NOW);
                        slave->last_link_up = jiffies;
@@ -2459,7 +2462,7 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
                 struct slave *slave)
 {
        struct arphdr *arp = (struct arphdr *)skb->data;
-       struct slave *curr_active_slave;
+       struct slave *curr_active_slave, *curr_arp_slave;
        unsigned char *arp_ptr;
        __be32 sip, tip;
        int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
@@ -2506,26 +2509,41 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
                     &sip, &tip);
 
        curr_active_slave = rcu_dereference(bond->curr_active_slave);
+       curr_arp_slave = rcu_dereference(bond->current_arp_slave);
 
-       /* Backup slaves won't see the ARP reply, but do come through
-        * here for each ARP probe (so we swap the sip/tip to validate
-        * the probe).  In a "redundant switch, common router" type of
-        * configuration, the ARP probe will (hopefully) travel from
-        * the active, through one switch, the router, then the other
-        * switch before reaching the backup.
+       /* We 'trust' the received ARP enough to validate it if:
+        *
+        * (a) the slave receiving the ARP is active (which includes the
+        * current ARP slave, if any), or
+        *
+        * (b) the receiving slave isn't active, but there is a currently
+        * active slave and it received valid arp reply(s) after it became
+        * the currently active slave, or
+        *
+        * (c) there is an ARP slave that sent an ARP during the prior ARP
+        * interval, and we receive an ARP reply on any slave.  We accept
+        * these because switch FDB update delays may deliver the ARP
+        * reply to a slave other than the sender of the ARP request.
         *
-        * We 'trust' the arp requests if there is an active slave and
-        * it received valid arp reply(s) after it became active. This
-        * is done to avoid endless looping when we can't reach the
+        * Note: for (b), backup slaves are receiving the broadcast ARP
+        * request, not a reply.  This request passes from the sending
+        * slave through the L2 switch(es) to the receiving slave.  Since
+        * this is checking the request, sip/tip are swapped for
+        * validation.
+        *
+        * This is done to avoid endless looping when we can't reach the
         * arp_ip_target and fool ourselves with our own arp requests.
         */
-
        if (bond_is_active_slave(slave))
                bond_validate_arp(bond, slave, sip, tip);
        else if (curr_active_slave &&
                 time_after(slave_last_rx(bond, curr_active_slave),
                            curr_active_slave->last_link_up))
                bond_validate_arp(bond, slave, tip, sip);
+       else if (curr_arp_slave && (arp->ar_op == htons(ARPOP_REPLY)) &&
+                bond_time_in_interval(bond,
+                                      dev_trans_start(curr_arp_slave->dev), 1))
+               bond_validate_arp(bond, slave, sip, tip);
 
 out_unlock:
        if (arp != (struct arphdr *)skb->data)
index fc5b75675cd8b6dbebbbc79d357001676900fefa..eb7192fab5932bcde88f31f0b90604997e27a524 100644 (file)
@@ -117,6 +117,9 @@ MODULE_LICENSE("GPL v2");
  */
 #define EMS_USB_ARM7_CLOCK 8000000
 
+#define CPC_TX_QUEUE_TRIGGER_LOW       25
+#define CPC_TX_QUEUE_TRIGGER_HIGH      35
+
 /*
  * CAN-Message representation in a CPC_MSG. Message object type is
  * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
@@ -278,6 +281,11 @@ static void ems_usb_read_interrupt_callback(struct urb *urb)
        switch (urb->status) {
        case 0:
                dev->free_slots = dev->intr_in_buffer[1];
+               if(dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH){
+                       if (netif_queue_stopped(netdev)){
+                               netif_wake_queue(netdev);
+                       }
+               }
                break;
 
        case -ECONNRESET: /* unlink */
@@ -526,8 +534,6 @@ static void ems_usb_write_bulk_callback(struct urb *urb)
        /* Release context */
        context->echo_index = MAX_TX_URBS;
 
-       if (netif_queue_stopped(netdev))
-               netif_wake_queue(netdev);
 }
 
 /*
@@ -587,7 +593,7 @@ static int ems_usb_start(struct ems_usb *dev)
        int err, i;
 
        dev->intr_in_buffer[0] = 0;
-       dev->free_slots = 15; /* initial size */
+       dev->free_slots = 50; /* initial size */
 
        for (i = 0; i < MAX_RX_URBS; i++) {
                struct urb *urb = NULL;
@@ -835,7 +841,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
 
                /* Slow down tx path */
                if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
-                   dev->free_slots < 5) {
+                   dev->free_slots < CPC_TX_QUEUE_TRIGGER_LOW) {
                        netif_stop_queue(netdev);
                }
        }
index cc6c5455341839eb91ba55dfd23e96e954c41fb7..a47f52f44b0d6b5f847a417f682c193ce127e29d 100644 (file)
@@ -25,6 +25,7 @@
 static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
        { PORT_SWITCH_ID_6172, "Marvell 88E6172" },
        { PORT_SWITCH_ID_6176, "Marvell 88E6176" },
+       { PORT_SWITCH_ID_6240, "Marvell 88E6240" },
        { PORT_SWITCH_ID_6320, "Marvell 88E6320" },
        { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" },
        { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" },
index cf34681af4f625d07bc43c77d528d632325bdc0d..512c8c0be1b4cbf029d4cb0bc692f88e9bf64660 100644 (file)
@@ -1555,7 +1555,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
 
        if (vlan.vid != vid || !vlan.valid ||
            vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
-               return -ENOENT;
+               return -EOPNOTSUPP;
 
        vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
 
@@ -1582,6 +1582,7 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
                            const struct switchdev_obj_port_vlan *vlan)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       const u16 defpvid = 4000 + ds->index * DSA_MAX_PORTS + port;
        u16 pvid, vid;
        int err = 0;
 
@@ -1597,7 +1598,8 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
                        goto unlock;
 
                if (vid == pvid) {
-                       err = _mv88e6xxx_port_pvid_set(ds, port, 0);
+                       /* restore reserved VLAN ID */
+                       err = _mv88e6xxx_port_pvid_set(ds, port, defpvid);
                        if (err)
                                goto unlock;
                }
@@ -1889,26 +1891,20 @@ unlock:
 
 int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members)
 {
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
-       int err;
-
-       /* The port joined a bridge, so leave its reserved VLAN */
-       mutex_lock(&ps->smi_mutex);
-       err = _mv88e6xxx_port_vlan_del(ds, port, pvid);
-       if (!err)
-               err = _mv88e6xxx_port_pvid_set(ds, port, 0);
-       mutex_unlock(&ps->smi_mutex);
-       return err;
+       return 0;
 }
 
 int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members)
+{
+       return 0;
+}
+
+static int mv88e6xxx_setup_port_default_vlan(struct dsa_switch *ds, int port)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
        const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
        int err;
 
-       /* The port left the bridge, so join its reserved VLAN */
        mutex_lock(&ps->smi_mutex);
        err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true);
        if (!err)
@@ -2192,8 +2188,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
                if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
                        continue;
 
-               /* setup the unbridged state */
-               ret = mv88e6xxx_port_bridge_leave(ds, i, 0);
+               ret = mv88e6xxx_setup_port_default_vlan(ds, i);
                if (ret < 0)
                        return ret;
        }
index 2777289a26c0419f855926ef028942074ca62a2f..2f79d29f17f2f0fae388f9cd4b4d9da201793775 100644 (file)
@@ -1501,6 +1501,7 @@ static const struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
        PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
        PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
+       PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0009),
        PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
        PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
        PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
index 3f3bcbea15bd7a6caf7c8296e6c5bc0bef14c6f1..0907ab6ff309e65ac4ff56250443dc23d6904b1c 100644 (file)
@@ -2380,7 +2380,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
                                                    sizeof(u32),
                                                    &tx_ring->tx_status_pa,
                                                    GFP_KERNEL);
-       if (!tx_ring->tx_status_pa) {
+       if (!tx_ring->tx_status) {
                dev_err(&adapter->pdev->dev,
                        "Cannot alloc memory for Tx status block\n");
                return -ENOMEM;
index 87e727b921dc0a20f99a6bdb084d2a6e3b168f9e..fcdf5dda448f9c7acf5a0a537cbbcb0de76b09df 100644 (file)
@@ -50,8 +50,8 @@ static const char version[] =
 static void write_rreg(u_long base, u_int reg, u_int val)
 {
        asm volatile(
-       "str%?h %1, [%2]        @ NET_RAP\n\t"
-       "str%?h %0, [%2, #-4]   @ NET_RDP"
+       "strh   %1, [%2]        @ NET_RAP\n\t"
+       "strh   %0, [%2, #-4]   @ NET_RDP"
        :
        : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
 }
@@ -60,8 +60,8 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg)
 {
        unsigned short v;
        asm volatile(
-       "str%?h %1, [%2]        @ NET_RAP\n\t"
-       "ldr%?h %0, [%2, #-4]   @ NET_RDP"
+       "strh   %1, [%2]        @ NET_RAP\n\t"
+       "ldrh   %0, [%2, #-4]   @ NET_RDP"
        : "=r" (v)
        : "r" (reg), "r" (ISAIO_BASE + 0x0464));
        return v;
@@ -70,8 +70,8 @@ static inline unsigned short read_rreg(u_long base_addr, u_int reg)
 static inline void write_ireg(u_long base, u_int reg, u_int val)
 {
        asm volatile(
-       "str%?h %1, [%2]        @ NET_RAP\n\t"
-       "str%?h %0, [%2, #8]    @ NET_IDP"
+       "strh   %1, [%2]        @ NET_RAP\n\t"
+       "strh   %0, [%2, #8]    @ NET_IDP"
        :
        : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
 }
@@ -80,8 +80,8 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg)
 {
        u_short v;
        asm volatile(
-       "str%?h %1, [%2]        @ NAT_RAP\n\t"
-       "ldr%?h %0, [%2, #8]    @ NET_IDP\n\t"
+       "strh   %1, [%2]        @ NAT_RAP\n\t"
+       "ldrh   %0, [%2, #8]    @ NET_IDP\n\t"
        : "=r" (v)
        : "r" (reg), "r" (ISAIO_BASE + 0x0464));
        return v;
@@ -96,7 +96,7 @@ am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigne
        offset = ISAMEM_BASE + (offset << 1);
        length = (length + 1) & ~1;
        if ((int)buf & 2) {
-               asm volatile("str%?h    %2, [%0], #4"
+               asm volatile("strh      %2, [%0], #4"
                 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
                buf += 2;
                length -= 2;
@@ -104,20 +104,20 @@ am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigne
        while (length > 8) {
                register unsigned int tmp asm("r2"), tmp2 asm("r3");
                asm volatile(
-                       "ldm%?ia        %0!, {%1, %2}"
+                       "ldmia  %0!, {%1, %2}"
                        : "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
                length -= 8;
                asm volatile(
-                       "str%?h %1, [%0], #4\n\t"
-                       "mov%?  %1, %1, lsr #16\n\t"
-                       "str%?h %1, [%0], #4\n\t"
-                       "str%?h %2, [%0], #4\n\t"
-                       "mov%?  %2, %2, lsr #16\n\t"
-                       "str%?h %2, [%0], #4"
+                       "strh   %1, [%0], #4\n\t"
+                       "mov    %1, %1, lsr #16\n\t"
+                       "strh   %1, [%0], #4\n\t"
+                       "strh   %2, [%0], #4\n\t"
+                       "mov    %2, %2, lsr #16\n\t"
+                       "strh   %2, [%0], #4"
                : "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
        }
        while (length > 0) {
-               asm volatile("str%?h    %2, [%0], #4"
+               asm volatile("strh      %2, [%0], #4"
                 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
                buf += 2;
                length -= 2;
@@ -132,23 +132,23 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
        if ((int)buf & 2) {
                unsigned int tmp;
                asm volatile(
-                       "ldr%?h %2, [%0], #4\n\t"
-                       "str%?b %2, [%1], #1\n\t"
-                       "mov%?  %2, %2, lsr #8\n\t"
-                       "str%?b %2, [%1], #1"
+                       "ldrh   %2, [%0], #4\n\t"
+                       "strb   %2, [%1], #1\n\t"
+                       "mov    %2, %2, lsr #8\n\t"
+                       "strb   %2, [%1], #1"
                : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
                length -= 2;
        }
        while (length > 8) {
                register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
                asm volatile(
-                       "ldr%?h %2, [%0], #4\n\t"
-                       "ldr%?h %4, [%0], #4\n\t"
-                       "ldr%?h %3, [%0], #4\n\t"
-                       "orr%?  %2, %2, %4, lsl #16\n\t"
-                       "ldr%?h %4, [%0], #4\n\t"
-                       "orr%?  %3, %3, %4, lsl #16\n\t"
-                       "stm%?ia        %1!, {%2, %3}"
+                       "ldrh   %2, [%0], #4\n\t"
+                       "ldrh   %4, [%0], #4\n\t"
+                       "ldrh   %3, [%0], #4\n\t"
+                       "orr    %2, %2, %4, lsl #16\n\t"
+                       "ldrh   %4, [%0], #4\n\t"
+                       "orr    %3, %3, %4, lsl #16\n\t"
+                       "stmia  %1!, {%2, %3}"
                : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
                : "0" (offset), "1" (buf));
                length -= 8;
@@ -156,10 +156,10 @@ am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned
        while (length > 0) {
                unsigned int tmp;
                asm volatile(
-                       "ldr%?h %2, [%0], #4\n\t"
-                       "str%?b %2, [%1], #1\n\t"
-                       "mov%?  %2, %2, lsr #8\n\t"
-                       "str%?b %2, [%1], #1"
+                       "ldrh   %2, [%0], #4\n\t"
+                       "strb   %2, [%1], #1\n\t"
+                       "mov    %2, %2, lsr #8\n\t"
+                       "strb   %2, [%1], #1"
                : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
                length -= 2;
        }
index 256f590f6bb1a6db167f4375b3ed2719d2ad5073..3a7ebfdda57dee33cbde71cf3440e5eb70aa262a 100644 (file)
@@ -547,8 +547,8 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
        /* Make certain the data structures used by the LANCE are aligned and DMAble. */
 
        lp = kzalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL);
-       if(lp==NULL)
-               return -ENODEV;
+       if (!lp)
+               return -ENOMEM;
        if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
        dev->ml_priv = lp;
        lp->name = chipname;
index abe1eabc017177ede3d1bdc7df6bec5a8ded86da..6446af1403f70be8101625ed9a8b03d3de17b792 100644 (file)
@@ -163,7 +163,7 @@ static void arc_emac_tx_clean(struct net_device *ndev)
                struct sk_buff *skb = tx_buff->skb;
                unsigned int info = le32_to_cpu(txbd->info);
 
-               if ((info & FOR_EMAC) || !txbd->data)
+               if ((info & FOR_EMAC) || !txbd->data || !skb)
                        break;
 
                if (unlikely(info & (DROP | DEFR | LTCL | UFLO))) {
@@ -191,6 +191,7 @@ static void arc_emac_tx_clean(struct net_device *ndev)
 
                txbd->data = 0;
                txbd->info = 0;
+               tx_buff->skb = NULL;
 
                *txbd_dirty = (*txbd_dirty + 1) % TX_BD_NUM;
        }
@@ -446,6 +447,9 @@ static int arc_emac_open(struct net_device *ndev)
                *last_rx_bd = (*last_rx_bd + 1) % RX_BD_NUM;
        }
 
+       priv->txbd_curr = 0;
+       priv->txbd_dirty = 0;
+
        /* Clean Tx BD's */
        memset(priv->txbd, 0, TX_RING_SZ);
 
@@ -513,6 +517,64 @@ static void arc_emac_set_rx_mode(struct net_device *ndev)
        }
 }
 
+/**
+ * arc_free_tx_queue - free skb from tx queue
+ * @ndev:      Pointer to the network device.
+ *
+ * This function must be called while EMAC disable
+ */
+static void arc_free_tx_queue(struct net_device *ndev)
+{
+       struct arc_emac_priv *priv = netdev_priv(ndev);
+       unsigned int i;
+
+       for (i = 0; i < TX_BD_NUM; i++) {
+               struct arc_emac_bd *txbd = &priv->txbd[i];
+               struct buffer_state *tx_buff = &priv->tx_buff[i];
+
+               if (tx_buff->skb) {
+                       dma_unmap_single(&ndev->dev, dma_unmap_addr(tx_buff, addr),
+                                        dma_unmap_len(tx_buff, len), DMA_TO_DEVICE);
+
+                       /* return the sk_buff to system */
+                       dev_kfree_skb_irq(tx_buff->skb);
+               }
+
+               txbd->info = 0;
+               txbd->data = 0;
+               tx_buff->skb = NULL;
+       }
+}
+
+/**
+ * arc_free_rx_queue - free skb from rx queue
+ * @ndev:      Pointer to the network device.
+ *
+ * This function must be called while EMAC disable
+ */
+static void arc_free_rx_queue(struct net_device *ndev)
+{
+       struct arc_emac_priv *priv = netdev_priv(ndev);
+       unsigned int i;
+
+       for (i = 0; i < RX_BD_NUM; i++) {
+               struct arc_emac_bd *rxbd = &priv->rxbd[i];
+               struct buffer_state *rx_buff = &priv->rx_buff[i];
+
+               if (rx_buff->skb) {
+                       dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr),
+                                       dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE);
+
+                       /* return the sk_buff to system */
+                       dev_kfree_skb_irq(rx_buff->skb);
+               }
+
+               rxbd->info = 0;
+               rxbd->data = 0;
+               rx_buff->skb = NULL;
+       }
+}
+
 /**
  * arc_emac_stop - Close the network device.
  * @ndev:      Pointer to the network device.
@@ -534,6 +596,10 @@ static int arc_emac_stop(struct net_device *ndev)
        /* Disable EMAC */
        arc_reg_clr(priv, R_CTRL, EN_MASK);
 
+       /* Return the sk_buff to system */
+       arc_free_tx_queue(ndev);
+       arc_free_rx_queue(ndev);
+
        return 0;
 }
 
@@ -610,7 +676,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr);
        dma_unmap_len_set(&priv->tx_buff[*txbd_curr], len, len);
 
-       priv->tx_buff[*txbd_curr].skb = skb;
        priv->txbd[*txbd_curr].data = cpu_to_le32(addr);
 
        /* Make sure pointer to data buffer is set */
@@ -620,6 +685,11 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
 
        *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len);
 
+       /* Make sure info word is set */
+       wmb();
+
+       priv->tx_buff[*txbd_curr].skb = skb;
+
        /* Increment index to point to the next BD */
        *txbd_curr = (*txbd_curr + 1) % TX_BD_NUM;
 
index d946bba43726f94b0d8a62973978a19d07959390..1fb80100e5e7d753b2ddd8ae741e0120ac161f42 100644 (file)
@@ -6185,26 +6185,80 @@ static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
                shift -= 4;
                digit = ((num & mask) >> shift);
                if (digit == 0 && remove_leading_zeros) {
-                       mask = mask >> 4;
-                       continue;
-               } else if (digit < 0xa)
-                       *str_ptr = digit + '0';
-               else
-                       *str_ptr = digit - 0xa + 'a';
-               remove_leading_zeros = 0;
-               str_ptr++;
-               (*len)--;
+                       *str_ptr = '0';
+               } else {
+                       if (digit < 0xa)
+                               *str_ptr = digit + '0';
+                       else
+                               *str_ptr = digit - 0xa + 'a';
+
+                       remove_leading_zeros = 0;
+                       str_ptr++;
+                       (*len)--;
+               }
                mask = mask >> 4;
                if (shift == 4*4) {
+                       if (remove_leading_zeros) {
+                               str_ptr++;
+                               (*len)--;
+                       }
                        *str_ptr = '.';
                        str_ptr++;
                        (*len)--;
                        remove_leading_zeros = 1;
                }
        }
+       if (remove_leading_zeros)
+               (*len)--;
        return 0;
 }
 
+static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len)
+{
+       u8 *str_ptr = str;
+       u32 mask = 0x00f00000;
+       u8 shift = 8*3;
+       u8 digit;
+       u8 remove_leading_zeros = 1;
+
+       if (*len < 10) {
+               /* Need more than 10chars for this format */
+               *str_ptr = '\0';
+               (*len)--;
+               return -EINVAL;
+       }
+
+       while (shift > 0) {
+               shift -= 4;
+               digit = ((num & mask) >> shift);
+               if (digit == 0 && remove_leading_zeros) {
+                       *str_ptr = '0';
+               } else {
+                       if (digit < 0xa)
+                               *str_ptr = digit + '0';
+                       else
+                               *str_ptr = digit - 0xa + 'a';
+
+                       remove_leading_zeros = 0;
+                       str_ptr++;
+                       (*len)--;
+               }
+               mask = mask >> 4;
+               if ((shift == 4*4) || (shift == 4*2)) {
+                       if (remove_leading_zeros) {
+                               str_ptr++;
+                               (*len)--;
+                       }
+                       *str_ptr = '.';
+                       str_ptr++;
+                       (*len)--;
+                       remove_leading_zeros = 1;
+               }
+       }
+       if (remove_leading_zeros)
+               (*len)--;
+       return 0;
+}
 
 static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
 {
@@ -9677,8 +9731,9 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 
        if (bnx2x_is_8483x_8485x(phy)) {
                bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
-               bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
-                               phy->ver_addr);
+               if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858)
+                       fw_ver1 &= 0xfff;
+               bnx2x_save_spirom_version(bp, port, fw_ver1, phy->ver_addr);
        } else {
                /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
                /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
@@ -9732,16 +9787,32 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
                                struct bnx2x_phy *phy)
 {
-       u16 val, offset, i;
+       u16 val, led3_blink_rate, offset, i;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080},
                {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018},
                {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006},
-               {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000},
                {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
                        MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ},
                {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD}
        };
+
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
+               /* Set LED5 source */
+               bnx2x_cl45_write(bp, phy,
+                                MDIO_PMA_DEVAD,
+                                MDIO_PMA_REG_8481_LED5_MASK,
+                                0x90);
+               led3_blink_rate = 0x000f;
+       } else {
+               led3_blink_rate = 0x0000;
+       }
+       /* Set LED3 BLINK */
+       bnx2x_cl45_write(bp, phy,
+                        MDIO_PMA_DEVAD,
+                        MDIO_PMA_REG_8481_LED3_BLINK,
+                        led3_blink_rate);
+
        /* PHYC_CTL_LED_CTL */
        bnx2x_cl45_read(bp, phy,
                        MDIO_PMA_DEVAD,
@@ -9749,6 +9820,9 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
        val &= 0xFE00;
        val |= 0x0092;
 
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858)
+               val |= 2 << 12; /* LED5 ON based on source */
+
        bnx2x_cl45_write(bp, phy,
                         MDIO_PMA_DEVAD,
                         MDIO_PMA_REG_8481_LINK_SIGNAL, val);
@@ -9762,10 +9836,17 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
        else
                offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
 
-       /* stretch_en for LED3*/
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858)
+               val = MDIO_PMA_REG_84858_ALLOW_GPHY_ACT |
+                     MDIO_PMA_REG_84823_LED3_STRETCH_EN;
+       else
+               val = MDIO_PMA_REG_84823_LED3_STRETCH_EN;
+
+       /* stretch_en for LEDs */
        bnx2x_cl45_read_or_write(bp, phy,
-                                MDIO_PMA_DEVAD, offset,
-                                MDIO_PMA_REG_84823_LED3_STRETCH_EN);
+                                MDIO_PMA_DEVAD,
+                                offset,
+                                val);
 }
 
 static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
@@ -9775,7 +9856,7 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        switch (action) {
        case PHY_INIT:
-               if (!bnx2x_is_8483x_8485x(phy)) {
+               if (bnx2x_is_8483x_8485x(phy)) {
                        /* Save spirom version */
                        bnx2x_save_848xx_spirom_version(phy, bp, params->port);
                }
@@ -10036,15 +10117,20 @@ static int bnx2x_84858_cmd_hdlr(struct bnx2x_phy *phy,
 
 static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
                                struct link_params *params, u16 fw_cmd,
-                               u16 cmd_args[], int argc)
+                               u16 cmd_args[], int argc, int process)
 {
        int idx;
        u16 val;
        struct bnx2x *bp = params->bp;
-       /* Write CMD_OPEN_OVERRIDE to STATUS reg */
-       bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                       MDIO_848xx_CMD_HDLR_STATUS,
-                       PHY84833_STATUS_CMD_OPEN_OVERRIDE);
+       int rc = 0;
+
+       if (process == PHY84833_MB_PROCESS2) {
+               /* Write CMD_OPEN_OVERRIDE to STATUS reg */
+               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+                                MDIO_848xx_CMD_HDLR_STATUS,
+                                PHY84833_STATUS_CMD_OPEN_OVERRIDE);
+       }
+
        for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
                bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
                                MDIO_848xx_CMD_HDLR_STATUS, &val);
@@ -10054,15 +10140,27 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
        }
        if (idx >= PHY848xx_CMDHDLR_WAIT) {
                DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
+               /* if the status is CMD_COMPLETE_PASS or CMD_COMPLETE_ERROR
+                * clear the status to CMD_CLEAR_COMPLETE
+                */
+               if (val == PHY84833_STATUS_CMD_COMPLETE_PASS ||
+                   val == PHY84833_STATUS_CMD_COMPLETE_ERROR) {
+                       bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+                                        MDIO_848xx_CMD_HDLR_STATUS,
+                                        PHY84833_STATUS_CMD_CLEAR_COMPLETE);
+               }
                return -EINVAL;
        }
-
-       /* Prepare argument(s) and issue command */
-       for (idx = 0; idx < argc; idx++) {
-               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_848xx_CMD_HDLR_DATA1 + idx,
-                               cmd_args[idx]);
+       if (process == PHY84833_MB_PROCESS1 ||
+           process == PHY84833_MB_PROCESS2) {
+               /* Prepare argument(s) */
+               for (idx = 0; idx < argc; idx++) {
+                       bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+                                        MDIO_848xx_CMD_HDLR_DATA1 + idx,
+                                        cmd_args[idx]);
+               }
        }
+
        bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
                        MDIO_848xx_CMD_HDLR_COMMAND, fw_cmd);
        for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
@@ -10076,24 +10174,30 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
        if ((idx >= PHY848xx_CMDHDLR_WAIT) ||
            (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
                DP(NETIF_MSG_LINK, "FW cmd failed.\n");
-               return -EINVAL;
+               rc = -EINVAL;
        }
-       /* Gather returning data */
-       for (idx = 0; idx < argc; idx++) {
-               bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-                               MDIO_848xx_CMD_HDLR_DATA1 + idx,
-                               &cmd_args[idx]);
+       if (process == PHY84833_MB_PROCESS3 && rc == 0) {
+               /* Gather returning data */
+               for (idx = 0; idx < argc; idx++) {
+                       bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+                                       MDIO_848xx_CMD_HDLR_DATA1 + idx,
+                                       &cmd_args[idx]);
+               }
        }
-       bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-                       MDIO_848xx_CMD_HDLR_STATUS,
-                       PHY84833_STATUS_CMD_CLEAR_COMPLETE);
-       return 0;
+       if (val == PHY84833_STATUS_CMD_COMPLETE_ERROR ||
+           val == PHY84833_STATUS_CMD_COMPLETE_PASS) {
+               bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+                                MDIO_848xx_CMD_HDLR_STATUS,
+                                PHY84833_STATUS_CMD_CLEAR_COMPLETE);
+       }
+       return rc;
 }
 
 static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy,
                                struct link_params *params,
                                u16 fw_cmd,
-                               u16 cmd_args[], int argc)
+                                          u16 cmd_args[], int argc,
+                                          int process)
 {
        struct bnx2x *bp = params->bp;
 
@@ -10106,7 +10210,7 @@ static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy,
                                            argc);
        } else {
                return bnx2x_84833_cmd_hdlr(phy, params, fw_cmd, cmd_args,
-                                           argc);
+                                           argc, process);
        }
 }
 
@@ -10133,7 +10237,7 @@ static int bnx2x_848xx_pair_swap_cfg(struct bnx2x_phy *phy,
 
        status = bnx2x_848xx_cmd_hdlr(phy, params,
                                      PHY848xx_CMD_SET_PAIR_SWAP, data,
-                                     PHY848xx_CMDHDLR_MAX_ARGS);
+                                     2, PHY84833_MB_PROCESS2);
        if (status == 0)
                DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]);
 
@@ -10222,8 +10326,8 @@ static int bnx2x_8483x_disable_eee(struct bnx2x_phy *phy,
        DP(NETIF_MSG_LINK, "Don't Advertise 10GBase-T EEE\n");
 
        /* Prevent Phy from working in EEE and advertising it */
-       rc = bnx2x_848xx_cmd_hdlr(phy, params,
-                                 PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1);
+       rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE,
+                                 &cmd_args, 1, PHY84833_MB_PROCESS1);
        if (rc) {
                DP(NETIF_MSG_LINK, "EEE disable failed.\n");
                return rc;
@@ -10240,8 +10344,8 @@ static int bnx2x_8483x_enable_eee(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u16 cmd_args = 1;
 
-       rc = bnx2x_848xx_cmd_hdlr(phy, params,
-                                 PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1);
+       rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE,
+                                 &cmd_args, 1, PHY84833_MB_PROCESS1);
        if (rc) {
                DP(NETIF_MSG_LINK, "EEE enable failed.\n");
                return rc;
@@ -10362,7 +10466,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                cmd_args[3] = PHY84833_CONSTANT_LATENCY;
                rc = bnx2x_848xx_cmd_hdlr(phy, params,
                                          PHY848xx_CMD_SET_EEE_MODE, cmd_args,
-                                         PHY848xx_CMDHDLR_MAX_ARGS);
+                                         4, PHY84833_MB_PROCESS1);
                if (rc)
                        DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
        }
@@ -10416,6 +10520,32 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
        }
 
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+               /* Additional settings for jumbo packets in 1000BASE-T mode */
+               /* Allow rx extended length */
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_8481_AUX_CTRL, &val);
+               val |= 0x4000;
+               bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                                MDIO_AN_REG_8481_AUX_CTRL, val);
+               /* TX FIFO Elasticity LSB */
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_8481_1G_100T_EXT_CTRL, &val);
+               val |= 0x1;
+               bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                                MDIO_AN_REG_8481_1G_100T_EXT_CTRL, val);
+               /* TX FIFO Elasticity MSB */
+               /* Enable expansion register 0x46 (Pattern Generator status) */
+               bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                                MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf46);
+
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, &val);
+               val |= 0x4000;
+               bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                                MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, val);
+       }
+
        if (bnx2x_is_8483x_8485x(phy)) {
                /* Bring PHY out of super isolate mode as the final step. */
                bnx2x_cl45_read_and_write(bp, phy,
@@ -10555,6 +10685,17 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
        return link_up;
 }
 
+static int bnx2x_8485x_format_ver(u32 raw_ver, u8 *str, u16 *len)
+{
+       int status = 0;
+       u32 num;
+
+       num = ((raw_ver & 0xF80) >> 7) << 16 | ((raw_ver & 0x7F) << 8) |
+             ((raw_ver & 0xF000) >> 12);
+       status = bnx2x_3_seq_format_ver(num, str, len);
+       return status;
+}
+
 static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
 {
        int status = 0;
@@ -10651,10 +10792,25 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                        0x0);
 
                } else {
+                       /* LED 1 OFF */
                        bnx2x_cl45_write(bp, phy,
                                         MDIO_PMA_DEVAD,
                                         MDIO_PMA_REG_8481_LED1_MASK,
                                         0x0);
+
+                       if (phy->type ==
+                               PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
+                               /* LED 2 OFF */
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED2_MASK,
+                                                0x0);
+                               /* LED 3 OFF */
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED3_MASK,
+                                                0x0);
+                       }
                }
                break;
        case LED_MODE_FRONT_PANEL_OFF:
@@ -10713,6 +10869,19 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                                 MDIO_PMA_REG_8481_SIGNAL_MASK,
                                                 0x0);
                        }
+                       if (phy->type ==
+                               PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
+                               /* LED 2 OFF */
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED2_MASK,
+                                                0x0);
+                               /* LED 3 OFF */
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED3_MASK,
+                                                0x0);
+                       }
                }
                break;
        case LED_MODE_ON:
@@ -10776,6 +10945,25 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                                params->port*4,
                                                NIG_MASK_MI_INT);
                                }
+                       }
+                       if (phy->type ==
+                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
+                               /* Tell LED3 to constant on */
+                               bnx2x_cl45_read(bp, phy,
+                                               MDIO_PMA_DEVAD,
+                                               MDIO_PMA_REG_8481_LINK_SIGNAL,
+                                               &val);
+                               val &= ~(7<<6);
+                               val |= (2<<6);  /* A83B[8:6]= 2 */
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LINK_SIGNAL,
+                                                val);
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED3_MASK,
+                                                0x20);
+                       } else {
                                bnx2x_cl45_write(bp, phy,
                                                 MDIO_PMA_DEVAD,
                                                 MDIO_PMA_REG_8481_SIGNAL_MASK,
@@ -10853,6 +11041,17 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
                                         MDIO_PMA_DEVAD,
                                         MDIO_PMA_REG_8481_LINK_SIGNAL,
                                         val);
+                       if (phy->type ==
+                           PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED2_MASK,
+                                                0x18);
+                               bnx2x_cl45_write(bp, phy,
+                                                MDIO_PMA_DEVAD,
+                                                MDIO_PMA_REG_8481_LED3_MASK,
+                                                0x06);
+                       }
                        if (phy->type ==
                            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
                                /* Restore LED4 source to external link,
@@ -11982,7 +12181,7 @@ static const struct bnx2x_phy phy_84858 = {
        .read_status    = (read_status_t)bnx2x_848xx_read_status,
        .link_reset     = (link_reset_t)bnx2x_848x3_link_reset,
        .config_loopback = (config_loopback_t)NULL,
-       .format_fw_ver  = (format_fw_ver_t)bnx2x_848xx_format_ver,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_8485x_format_ver,
        .hw_reset       = (hw_reset_t)bnx2x_84833_hw_reset_phy,
        .set_link_led   = (set_link_led_t)bnx2x_848xx_set_link_led,
        .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
@@ -13807,8 +14006,10 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
        if (CHIP_IS_E3(bp)) {
                struct bnx2x_phy *phy = &params->phy[INT_PHY];
                bnx2x_set_aer_mmd(params, phy);
-               if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
-                   (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))
+               if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+                    (phy->speed_cap_mask &
+                     PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
+                   (phy->req_line_speed == SPEED_20000))
                        bnx2x_check_kr2_wa(params, vars, phy);
                bnx2x_check_over_curr(params, vars);
                if (vars->rx_tx_asic_rst)
index 4dead49bd5cb0866ff89db2c5f2e149536b1ea3c..a43dea259b1290168c43f2713f51a2ba1c62652b 100644 (file)
@@ -7296,6 +7296,8 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_PMA_REG_84823_CTL_LED_CTL_1                       0xa8e3
 #define MDIO_PMA_REG_84833_CTL_LED_CTL_1                       0xa8ec
 #define MDIO_PMA_REG_84823_LED3_STRETCH_EN                     0x0080
+/* BCM84858 only */
+#define MDIO_PMA_REG_84858_ALLOW_GPHY_ACT                      0x8000
 
 /* BCM84833 only */
 #define MDIO_84833_TOP_CFG_FW_REV                      0x400f
@@ -7337,6 +7339,10 @@ Theotherbitsarereservedandshouldbezero*/
 #define PHY84833_STATUS_CMD_NOT_OPEN_FOR_CMDS          0x0040
 #define PHY84833_STATUS_CMD_CLEAR_COMPLETE             0x0080
 #define PHY84833_STATUS_CMD_OPEN_OVERRIDE              0xa5a5
+/* Mailbox Process */
+#define PHY84833_MB_PROCESS1                           1
+#define PHY84833_MB_PROCESS2                           2
+#define PHY84833_MB_PROCESS3                           3
 
 /* Mailbox status set used by 84858 only */
 #define PHY84858_STATUS_CMD_RECEIVED                   0x0001
index 5dc89e527e7deefe04c831d9ec556ed76ac40d26..8ab000dd52d958317323c8486fc0538576727803 100644 (file)
@@ -69,7 +69,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
 #define BNXT_RX_DMA_OFFSET NET_SKB_PAD
 #define BNXT_RX_COPY_THRESH 256
 
-#define BNXT_TX_PUSH_THRESH 92
+#define BNXT_TX_PUSH_THRESH 164
 
 enum board_idx {
        BCM57301,
@@ -223,11 +223,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) {
-               struct tx_push_bd *push = txr->tx_push;
-               struct tx_bd *tx_push = &push->txbd1;
-               struct tx_bd_ext *tx_push1 = &push->txbd2;
-               void *pdata = tx_push1 + 1;
-               int j;
+               struct tx_push_buffer *tx_push_buf = txr->tx_push;
+               struct tx_push_bd *tx_push = &tx_push_buf->push_bd;
+               struct tx_bd_ext *tx_push1 = &tx_push->txbd2;
+               void *pdata = tx_push_buf->data;
+               u64 *end;
+               int j, push_len;
 
                /* Set COAL_NOW to be ready quickly for the next push */
                tx_push->tx_bd_len_flags_type =
@@ -247,6 +248,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags);
                tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action);
 
+               end = PTR_ALIGN(pdata + length + 1, 8) - 1;
+               *end = 0;
+
                skb_copy_from_linear_data(skb, pdata, len);
                pdata += len;
                for (j = 0; j < last_frag; j++) {
@@ -261,22 +265,29 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        pdata += skb_frag_size(frag);
                }
 
-               memcpy(txbd, tx_push, sizeof(*txbd));
+               txbd->tx_bd_len_flags_type = tx_push->tx_bd_len_flags_type;
+               txbd->tx_bd_haddr = txr->data_mapping;
                prod = NEXT_TX(prod);
                txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
                memcpy(txbd, tx_push1, sizeof(*txbd));
                prod = NEXT_TX(prod);
-               push->doorbell =
+               tx_push->doorbell =
                        cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod);
                txr->tx_prod = prod;
 
                netdev_tx_sent_queue(txq, skb->len);
 
-               __iowrite64_copy(txr->tx_doorbell, push,
-                                (length + sizeof(*push) + 8) / 8);
+               push_len = (length + sizeof(*tx_push) + 7) / 8;
+               if (push_len > 16) {
+                       __iowrite64_copy(txr->tx_doorbell, tx_push_buf, 16);
+                       __iowrite64_copy(txr->tx_doorbell + 4, tx_push_buf + 1,
+                                        push_len - 16);
+               } else {
+                       __iowrite64_copy(txr->tx_doorbell, tx_push_buf,
+                                        push_len);
+               }
 
                tx_buf->is_push = 1;
-
                goto tx_done;
        }
 
@@ -1753,7 +1764,7 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
                push_size  = L1_CACHE_ALIGN(sizeof(struct tx_push_bd) +
                                        bp->tx_push_thresh);
 
-               if (push_size > 128) {
+               if (push_size > 256) {
                        push_size = 0;
                        bp->tx_push_thresh = 0;
                }
@@ -1772,7 +1783,6 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
                        return rc;
 
                if (bp->tx_push_size) {
-                       struct tx_bd *txbd;
                        dma_addr_t mapping;
 
                        /* One pre-allocated DMA buffer to backup
@@ -1786,13 +1796,11 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
                        if (!txr->tx_push)
                                return -ENOMEM;
 
-                       txbd = &txr->tx_push->txbd1;
-
                        mapping = txr->tx_push_mapping +
                                sizeof(struct tx_push_bd);
-                       txbd->tx_bd_haddr = cpu_to_le64(mapping);
+                       txr->data_mapping = cpu_to_le64(mapping);
 
-                       memset(txbd + 1, 0, sizeof(struct tx_bd_ext));
+                       memset(txr->tx_push, 0, sizeof(struct tx_push_bd));
                }
                ring->queue_id = bp->q_info[j].queue_id;
                if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
@@ -4546,20 +4554,18 @@ static int bnxt_update_phy_setting(struct bnxt *bp)
        if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) &&
            link_info->force_pause_setting != link_info->req_flow_ctrl)
                update_pause = true;
-       if (link_info->req_duplex != link_info->duplex_setting)
-               update_link = true;
        if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
                if (BNXT_AUTO_MODE(link_info->auto_mode))
                        update_link = true;
                if (link_info->req_link_speed != link_info->force_link_speed)
                        update_link = true;
+               if (link_info->req_duplex != link_info->duplex_setting)
+                       update_link = true;
        } else {
                if (link_info->auto_mode == BNXT_LINK_AUTO_NONE)
                        update_link = true;
                if (link_info->advertising != link_info->auto_link_speeds)
                        update_link = true;
-               if (link_info->req_link_speed != link_info->auto_link_speed)
-                       update_link = true;
        }
 
        if (update_link)
@@ -4636,7 +4642,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
        if (link_re_init) {
                rc = bnxt_update_phy_setting(bp);
                if (rc)
-                       goto open_err;
+                       netdev_warn(bp->dev, "failed to update phy settings\n");
        }
 
        if (irq_re_init) {
@@ -4654,6 +4660,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
        /* Enable TX queues */
        bnxt_tx_enable(bp);
        mod_timer(&bp->timer, jiffies + bp->current_interval);
+       bnxt_update_link(bp, true);
 
        return 0;
 
@@ -5670,22 +5677,16 @@ static int bnxt_probe_phy(struct bnxt *bp)
        }
 
        /*initialize the ethool setting copy with NVM settings */
-       if (BNXT_AUTO_MODE(link_info->auto_mode))
-               link_info->autoneg |= BNXT_AUTONEG_SPEED;
-
-       if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) {
-               if (link_info->auto_pause_setting == BNXT_LINK_PAUSE_BOTH)
-                       link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+       if (BNXT_AUTO_MODE(link_info->auto_mode)) {
+               link_info->autoneg = BNXT_AUTONEG_SPEED |
+                                    BNXT_AUTONEG_FLOW_CTRL;
+               link_info->advertising = link_info->auto_link_speeds;
                link_info->req_flow_ctrl = link_info->auto_pause_setting;
-       } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) {
+       } else {
+               link_info->req_link_speed = link_info->force_link_speed;
+               link_info->req_duplex = link_info->duplex_setting;
                link_info->req_flow_ctrl = link_info->force_pause_setting;
        }
-       link_info->req_duplex = link_info->duplex_setting;
-       if (link_info->autoneg & BNXT_AUTONEG_SPEED)
-               link_info->req_link_speed = link_info->auto_link_speed;
-       else
-               link_info->req_link_speed = link_info->force_link_speed;
-       link_info->advertising = link_info->auto_link_speeds;
        snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d",
                 link_info->phy_ver[0],
                 link_info->phy_ver[1],
index 8af3ca8efcef9ac275f2daac4e44a06d108eed61..2be51b332652b0d0fd63629795599c10e6c25dea 100644 (file)
@@ -411,8 +411,8 @@ struct rx_tpa_end_cmp_ext {
 
 #define BNXT_NUM_TESTS(bp)     0
 
-#define BNXT_DEFAULT_RX_RING_SIZE      1023
-#define BNXT_DEFAULT_TX_RING_SIZE      512
+#define BNXT_DEFAULT_RX_RING_SIZE      511
+#define BNXT_DEFAULT_TX_RING_SIZE      511
 
 #define MAX_TPA                64
 
@@ -523,10 +523,16 @@ struct bnxt_ring_struct {
 
 struct tx_push_bd {
        __le32                  doorbell;
-       struct tx_bd            txbd1;
+       __le32                  tx_bd_len_flags_type;
+       u32                     tx_bd_opaque;
        struct tx_bd_ext        txbd2;
 };
 
+struct tx_push_buffer {
+       struct tx_push_bd       push_bd;
+       u32                     data[25];
+};
+
 struct bnxt_tx_ring_info {
        struct bnxt_napi        *bnapi;
        u16                     tx_prod;
@@ -538,8 +544,9 @@ struct bnxt_tx_ring_info {
 
        dma_addr_t              tx_desc_mapping[MAX_TX_PAGES];
 
-       struct tx_push_bd       *tx_push;
+       struct tx_push_buffer   *tx_push;
        dma_addr_t              tx_push_mapping;
+       __le64                  data_mapping;
 
 #define BNXT_DEV_STATE_CLOSING 0x1
        u32                     dev_state;
index 922b898e7a320e39da102a27818a68c84af08e79..3238817dfd5f79e2bd6a13b97f2483ce7eb4d663 100644 (file)
@@ -486,15 +486,8 @@ static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info)
                speed_mask |= SUPPORTED_2500baseX_Full;
        if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB)
                speed_mask |= SUPPORTED_10000baseT_Full;
-       /* TODO: support 25GB, 50GB with different cable type */
-       if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB)
-               speed_mask |= SUPPORTED_20000baseMLD2_Full |
-                       SUPPORTED_20000baseKR2_Full;
        if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB)
-               speed_mask |= SUPPORTED_40000baseKR4_Full |
-                       SUPPORTED_40000baseCR4_Full |
-                       SUPPORTED_40000baseSR4_Full |
-                       SUPPORTED_40000baseLR4_Full;
+               speed_mask |= SUPPORTED_40000baseCR4_Full;
 
        return speed_mask;
 }
@@ -514,15 +507,8 @@ static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
                speed_mask |= ADVERTISED_2500baseX_Full;
        if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB)
                speed_mask |= ADVERTISED_10000baseT_Full;
-       /* TODO: how to advertise 20, 25, 40, 50GB with different cable type ?*/
-       if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB)
-               speed_mask |= ADVERTISED_20000baseMLD2_Full |
-                             ADVERTISED_20000baseKR2_Full;
        if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB)
-               speed_mask |= ADVERTISED_40000baseKR4_Full |
-                             ADVERTISED_40000baseCR4_Full |
-                             ADVERTISED_40000baseSR4_Full |
-                             ADVERTISED_40000baseLR4_Full;
+               speed_mask |= ADVERTISED_40000baseCR4_Full;
        return speed_mask;
 }
 
@@ -557,11 +543,12 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        u16 ethtool_speed;
 
        cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info);
+       cmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 
        if (link_info->auto_link_speeds)
                cmd->supported |= SUPPORTED_Autoneg;
 
-       if (BNXT_AUTO_MODE(link_info->auto_mode)) {
+       if (link_info->autoneg) {
                cmd->advertising =
                        bnxt_fw_to_ethtool_advertised_spds(link_info);
                cmd->advertising |= ADVERTISED_Autoneg;
@@ -570,28 +557,16 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->autoneg = AUTONEG_DISABLE;
                cmd->advertising = 0;
        }
-       if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) {
+       if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) {
                if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) ==
                    BNXT_LINK_PAUSE_BOTH) {
                        cmd->advertising |= ADVERTISED_Pause;
-                       cmd->supported |= SUPPORTED_Pause;
                } else {
                        cmd->advertising |= ADVERTISED_Asym_Pause;
-                       cmd->supported |= SUPPORTED_Asym_Pause;
                        if (link_info->auto_pause_setting &
                            BNXT_LINK_PAUSE_RX)
                                cmd->advertising |= ADVERTISED_Pause;
                }
-       } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) {
-               if ((link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) ==
-                   BNXT_LINK_PAUSE_BOTH) {
-                       cmd->supported |= SUPPORTED_Pause;
-               } else {
-                       cmd->supported |= SUPPORTED_Asym_Pause;
-                       if (link_info->force_pause_setting &
-                           BNXT_LINK_PAUSE_RX)
-                               cmd->supported |= SUPPORTED_Pause;
-               }
        }
 
        cmd->port = PORT_NONE;
@@ -670,6 +645,9 @@ static u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
        if (advertising & ADVERTISED_10000baseT_Full)
                fw_speed_mask |= BNXT_LINK_SPEED_MSK_10GB;
 
+       if (advertising & ADVERTISED_40000baseCR4_Full)
+               fw_speed_mask |= BNXT_LINK_SPEED_MSK_40GB;
+
        return fw_speed_mask;
 }
 
@@ -729,7 +707,7 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                speed = ethtool_cmd_speed(cmd);
                link_info->req_link_speed = bnxt_get_fw_speed(dev, speed);
                link_info->req_duplex = BNXT_LINK_DUPLEX_FULL;
-               link_info->autoneg &= ~BNXT_AUTONEG_SPEED;
+               link_info->autoneg = 0;
                link_info->advertising = 0;
        }
 
@@ -748,8 +726,7 @@ static void bnxt_get_pauseparam(struct net_device *dev,
 
        if (BNXT_VF(bp))
                return;
-       epause->autoneg = !!(link_info->auto_pause_setting &
-                            BNXT_LINK_PAUSE_BOTH);
+       epause->autoneg = !!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL);
        epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0);
        epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0);
 }
@@ -765,6 +742,9 @@ static int bnxt_set_pauseparam(struct net_device *dev,
                return rc;
 
        if (epause->autoneg) {
+               if (!(link_info->autoneg & BNXT_AUTONEG_SPEED))
+                       return -EINVAL;
+
                link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
                link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH;
        } else {
index b15a60d787c70354b780d9214e026dd2fbaebdec..d7e01a74e9275b29a915e4c5417c7116ffddcabf 100644 (file)
@@ -2445,8 +2445,7 @@ static void bcmgenet_irq_task(struct work_struct *work)
        }
 
        /* Link UP/DOWN event */
-       if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
-           (priv->irq0_stat & UMAC_IRQ_LINK_EVENT)) {
+       if (priv->irq0_stat & UMAC_IRQ_LINK_EVENT) {
                phy_mac_interrupt(priv->phydev,
                                  !!(priv->irq0_stat & UMAC_IRQ_LINK_UP));
                priv->irq0_stat &= ~UMAC_IRQ_LINK_EVENT;
index 49eea8981332d679b31614aa4d284e258abd97d6..3010080cfeee350a2e523ce0c26aeb427953f21a 100644 (file)
@@ -7831,6 +7831,14 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
        return ret;
 }
 
+static bool tg3_tso_bug_gso_check(struct tg3_napi *tnapi, struct sk_buff *skb)
+{
+       /* Check if we will never have enough descriptors,
+        * as gso_segs can be more than current ring size
+        */
+       return skb_shinfo(skb)->gso_segs < tnapi->tx_pending / 3;
+}
+
 static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
 
 /* Use GSO to workaround all TSO packets that meet HW bug conditions
@@ -7934,14 +7942,19 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                 * vlan encapsulated.
                 */
                if (skb->protocol == htons(ETH_P_8021Q) ||
-                   skb->protocol == htons(ETH_P_8021AD))
-                       return tg3_tso_bug(tp, tnapi, txq, skb);
+                   skb->protocol == htons(ETH_P_8021AD)) {
+                       if (tg3_tso_bug_gso_check(tnapi, skb))
+                               return tg3_tso_bug(tp, tnapi, txq, skb);
+                       goto drop;
+               }
 
                if (!skb_is_gso_v6(skb)) {
                        if (unlikely((ETH_HLEN + hdr_len) > 80) &&
-                           tg3_flag(tp, TSO_BUG))
-                               return tg3_tso_bug(tp, tnapi, txq, skb);
-
+                           tg3_flag(tp, TSO_BUG)) {
+                               if (tg3_tso_bug_gso_check(tnapi, skb))
+                                       return tg3_tso_bug(tp, tnapi, txq, skb);
+                               goto drop;
+                       }
                        ip_csum = iph->check;
                        ip_tot_len = iph->tot_len;
                        iph->check = 0;
@@ -8073,7 +8086,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (would_hit_hwbug) {
                tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
 
-               if (mss) {
+               if (mss && tg3_tso_bug_gso_check(tnapi, skb)) {
                        /* If it's a TSO packet, do GSO instead of
                         * allocating and copying to a large linear SKB
                         */
index 872765527081ab3d48d7701f8a9d8705553640fc..34d269cd5579b7e0f1c1afd29bffb04c8711d71d 100644 (file)
@@ -1683,7 +1683,7 @@ static int octeon_setup_droq(struct octeon_device *oct, int q_no, int num_descs,
        dev_dbg(&oct->pci_dev->dev, "Creating Droq: %d\n", q_no);
        /* droq creation and local register settings. */
        ret_val = octeon_create_droq(oct, q_no, num_descs, desc_size, app_ctx);
-       if (ret_val == -1)
+       if (ret_val < 0)
                return ret_val;
 
        if (ret_val == 1) {
@@ -2524,7 +2524,7 @@ static void handle_timestamp(struct octeon_device *oct,
 
        octeon_swap_8B_data(&resp->timestamp, 1);
 
-       if (unlikely((skb_shinfo(skb)->tx_flags | SKBTX_IN_PROGRESS) != 0)) {
+       if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) != 0)) {
                struct skb_shared_hwtstamps ts;
                u64 ns = resp->timestamp;
 
index 4dba86eaa04559649b012cbeff8707c47a176927..174072b3740b4a15f86f292a51a28d8239ee8c0a 100644 (file)
@@ -983,5 +983,5 @@ int octeon_create_droq(struct octeon_device *oct,
 
 create_droq_fail:
        octeon_delete_droq(oct, q_no);
-       return -1;
+       return -ENOMEM;
 }
index c24cb2a86a42f997c31536947ff0ad7f37bd577c..a009bc30dc4dd36e51c9a1269c28dcb10b8de23f 100644 (file)
@@ -574,8 +574,7 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
 
 static void nicvf_rcv_pkt_handler(struct net_device *netdev,
                                  struct napi_struct *napi,
-                                 struct cmp_queue *cq,
-                                 struct cqe_rx_t *cqe_rx, int cqe_type)
+                                 struct cqe_rx_t *cqe_rx)
 {
        struct sk_buff *skb;
        struct nicvf *nic = netdev_priv(netdev);
@@ -591,7 +590,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
        }
 
        /* Check for errors */
-       err = nicvf_check_cqe_rx_errs(nic, cq, cqe_rx);
+       err = nicvf_check_cqe_rx_errs(nic, cqe_rx);
        if (err && !cqe_rx->rb_cnt)
                return;
 
@@ -682,8 +681,7 @@ loop:
                           cq_idx, cq_desc->cqe_type);
                switch (cq_desc->cqe_type) {
                case CQE_TYPE_RX:
-                       nicvf_rcv_pkt_handler(netdev, napi, cq,
-                                             cq_desc, CQE_TYPE_RX);
+                       nicvf_rcv_pkt_handler(netdev, napi, cq_desc);
                        work_done++;
                break;
                case CQE_TYPE_SEND:
@@ -1125,7 +1123,6 @@ int nicvf_stop(struct net_device *netdev)
 
        /* Clear multiqset info */
        nic->pnicvf = nic;
-       nic->sqs_count = 0;
 
        return 0;
 }
@@ -1354,6 +1351,9 @@ void nicvf_update_stats(struct nicvf *nic)
        drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok +
                                  stats->tx_bcast_frames_ok +
                                  stats->tx_mcast_frames_ok;
+       drv_stats->rx_frames_ok = stats->rx_ucast_frames +
+                                 stats->rx_bcast_frames +
+                                 stats->rx_mcast_frames;
        drv_stats->rx_drops = stats->rx_drop_red +
                              stats->rx_drop_overrun;
        drv_stats->tx_drops = stats->tx_drops;
@@ -1538,6 +1538,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        nicvf_send_vf_struct(nic);
 
+       if (!pass1_silicon(nic->pdev))
+               nic->hw_tso = true;
+
        /* Check if this VF is in QS only mode */
        if (nic->sqs_mode)
                return 0;
@@ -1557,9 +1560,6 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
 
-       if (!pass1_silicon(nic->pdev))
-               nic->hw_tso = true;
-
        netdev->netdev_ops = &nicvf_netdev_ops;
        netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
 
index d0d1b54900610046955a390f6f5c87ce45cbf1df..767347b1f63122271a74363421cb78f717218948 100644 (file)
@@ -1329,16 +1329,12 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx)
 }
 
 /* Check for errors in the receive cmp.queue entry */
-int nicvf_check_cqe_rx_errs(struct nicvf *nic,
-                           struct cmp_queue *cq, struct cqe_rx_t *cqe_rx)
+int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
 {
        struct nicvf_hw_stats *stats = &nic->hw_stats;
-       struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
 
-       if (!cqe_rx->err_level && !cqe_rx->err_opcode) {
-               drv_stats->rx_frames_ok++;
+       if (!cqe_rx->err_level && !cqe_rx->err_opcode)
                return 0;
-       }
 
        if (netif_msg_rx_err(nic))
                netdev_err(nic->netdev,
index c5030a7f213ae57e9799142958e5d4fe64a8fbf5..6673e1133523881a4c1719e7d6ca4c123f7a8e1e 100644 (file)
@@ -338,8 +338,7 @@ u64  nicvf_queue_reg_read(struct nicvf *nic,
 /* Stats */
 void nicvf_update_rq_stats(struct nicvf *nic, int rq_idx);
 void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx);
-int nicvf_check_cqe_rx_errs(struct nicvf *nic,
-                           struct cmp_queue *cq, struct cqe_rx_t *cqe_rx);
+int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx);
 int nicvf_check_cqe_tx_errs(struct nicvf *nic,
                            struct cmp_queue *cq, struct cqe_send_t *cqe_tx);
 #endif /* NICVF_QUEUES_H */
index ee04caa6c4d8522d0cc34ec15ec7575bfbdc4afa..a89721fad633ec75a3ed46a7fc22d8988cbdada4 100644 (file)
@@ -681,6 +681,24 @@ int t3_seeprom_wp(struct adapter *adapter, int enable)
        return t3_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0);
 }
 
+static int vpdstrtouint(char *s, int len, unsigned int base, unsigned int *val)
+{
+       char tok[len + 1];
+
+       memcpy(tok, s, len);
+       tok[len] = 0;
+       return kstrtouint(strim(tok), base, val);
+}
+
+static int vpdstrtou16(char *s, int len, unsigned int base, u16 *val)
+{
+       char tok[len + 1];
+
+       memcpy(tok, s, len);
+       tok[len] = 0;
+       return kstrtou16(strim(tok), base, val);
+}
+
 /**
  *     get_vpd_params - read VPD parameters from VPD EEPROM
  *     @adapter: adapter to read
@@ -709,19 +727,19 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
                        return ret;
        }
 
-       ret = kstrtouint(vpd.cclk_data, 10, &p->cclk);
+       ret = vpdstrtouint(vpd.cclk_data, vpd.cclk_len, 10, &p->cclk);
        if (ret)
                return ret;
-       ret = kstrtouint(vpd.mclk_data, 10, &p->mclk);
+       ret = vpdstrtouint(vpd.mclk_data, vpd.mclk_len, 10, &p->mclk);
        if (ret)
                return ret;
-       ret = kstrtouint(vpd.uclk_data, 10, &p->uclk);
+       ret = vpdstrtouint(vpd.uclk_data, vpd.uclk_len, 10, &p->uclk);
        if (ret)
                return ret;
-       ret = kstrtouint(vpd.mdc_data, 10, &p->mdc);
+       ret = vpdstrtouint(vpd.mdc_data, vpd.mdc_len, 10, &p->mdc);
        if (ret)
                return ret;
-       ret = kstrtouint(vpd.mt_data, 10, &p->mem_timing);
+       ret = vpdstrtouint(vpd.mt_data, vpd.mt_len, 10, &p->mem_timing);
        if (ret)
                return ret;
        memcpy(p->sn, vpd.sn_data, SERNUM_LEN);
@@ -733,10 +751,12 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        } else {
                p->port_type[0] = hex_to_bin(vpd.port0_data[0]);
                p->port_type[1] = hex_to_bin(vpd.port1_data[0]);
-               ret = kstrtou16(vpd.xaui0cfg_data, 16, &p->xauicfg[0]);
+               ret = vpdstrtou16(vpd.xaui0cfg_data, vpd.xaui0cfg_len, 16,
+                                 &p->xauicfg[0]);
                if (ret)
                        return ret;
-               ret = kstrtou16(vpd.xaui1cfg_data, 16, &p->xauicfg[1]);
+               ret = vpdstrtou16(vpd.xaui1cfg_data, vpd.xaui1cfg_len, 16,
+                                 &p->xauicfg[1]);
                if (ret)
                        return ret;
        }
index a8dda635456dc1f8fb0d85799c3f605ea7cda39a..06bc2d2e7a7315ceb0f544aac1fcaec1af51fbc6 100644 (file)
@@ -165,6 +165,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
        CH_PCI_ID_TABLE_FENTRY(0x5098), /* Custom 2x40G QSFP */
        CH_PCI_ID_TABLE_FENTRY(0x5099), /* Custom 2x40G QSFP */
        CH_PCI_ID_TABLE_FENTRY(0x509a), /* Custom T520-CR */
+       CH_PCI_ID_TABLE_FENTRY(0x509b), /* Custom T540-CR LOM */
 
        /* T6 adapters:
         */
index 1671fa3332c2d3011db8c308a17ea5a9bf8b3fb2..7ba6d530b0c0ab6e3d1c3d4ea21b0b950ebe3c3f 100644 (file)
@@ -33,7 +33,7 @@
 
 #define DRV_NAME               "enic"
 #define DRV_DESCRIPTION                "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION            "2.3.0.12"
+#define DRV_VERSION            "2.3.0.20"
 #define DRV_COPYRIGHT          "Copyright 2008-2013 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX          6
index 1ffd1050860bb5cde576fd291e0651b351d578ff..1fdf5fe12a9562251e3bcee9fe635872053357a2 100644 (file)
@@ -298,7 +298,8 @@ static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
                          int wait)
 {
        struct devcmd2_controller *dc2c = vdev->devcmd2;
-       struct devcmd2_result *result = dc2c->result + dc2c->next_result;
+       struct devcmd2_result *result;
+       u8 color;
        unsigned int i;
        int delay, err;
        u32 fetch_index, new_posted;
@@ -336,13 +337,17 @@ static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
        if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
                return 0;
 
+       result = dc2c->result + dc2c->next_result;
+       color = dc2c->color;
+
+       dc2c->next_result++;
+       if (dc2c->next_result == dc2c->result_size) {
+               dc2c->next_result = 0;
+               dc2c->color = dc2c->color ? 0 : 1;
+       }
+
        for (delay = 0; delay < wait; delay++) {
-               if (result->color == dc2c->color) {
-                       dc2c->next_result++;
-                       if (dc2c->next_result == dc2c->result_size) {
-                               dc2c->next_result = 0;
-                               dc2c->color = dc2c->color ? 0 : 1;
-                       }
+               if (result->color == color) {
                        if (result->error) {
                                err = result->error;
                                if (err != ERR_ECMDUNKNOWN ||
index cf94b72dbacd942b9c56d2bc669854bea7c2ac18..48d91941408d8fe3aa148c632ff33c1ea4201335 100644 (file)
@@ -128,7 +128,6 @@ struct board_info {
        struct resource *data_res;
        struct resource *addr_req;   /* resources requested */
        struct resource *data_req;
-       struct resource *irq_res;
 
        int              irq_wake;
 
@@ -1300,22 +1299,16 @@ static int
 dm9000_open(struct net_device *dev)
 {
        struct board_info *db = netdev_priv(dev);
-       unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
 
        if (netif_msg_ifup(db))
                dev_dbg(db->dev, "enabling %s\n", dev->name);
 
-       /* If there is no IRQ type specified, default to something that
-        * may work, and tell the user that this is a problem */
-
-       if (irqflags == IRQF_TRIGGER_NONE)
-               irqflags = irq_get_trigger_type(dev->irq);
-
-       if (irqflags == IRQF_TRIGGER_NONE)
+       /* If there is no IRQ type specified, tell the user that this is a
+        * problem
+        */
+       if (irq_get_trigger_type(dev->irq) == IRQF_TRIGGER_NONE)
                dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
 
-       irqflags |= IRQF_SHARED;
-
        /* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
        iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
        mdelay(1); /* delay needs by DM9000B */
@@ -1323,7 +1316,8 @@ dm9000_open(struct net_device *dev)
        /* Initialize DM9000 board */
        dm9000_init_dm9000(dev);
 
-       if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
+       if (request_irq(dev->irq, dm9000_interrupt, IRQF_SHARED,
+                       dev->name, dev))
                return -EAGAIN;
        /* Now that we have an interrupt handler hooked up we can unmask
         * our interrupts
@@ -1500,15 +1494,22 @@ dm9000_probe(struct platform_device *pdev)
 
        db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
-       if (db->addr_res == NULL || db->data_res == NULL ||
-           db->irq_res == NULL) {
-               dev_err(db->dev, "insufficient resources\n");
+       if (!db->addr_res || !db->data_res) {
+               dev_err(db->dev, "insufficient resources addr=%p data=%p\n",
+                       db->addr_res, db->data_res);
                ret = -ENOENT;
                goto out;
        }
 
+       ndev->irq = platform_get_irq(pdev, 0);
+       if (ndev->irq < 0) {
+               dev_err(db->dev, "interrupt resource unavailable: %d\n",
+                       ndev->irq);
+               ret = ndev->irq;
+               goto out;
+       }
+
        db->irq_wake = platform_get_irq(pdev, 1);
        if (db->irq_wake >= 0) {
                dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
@@ -1570,7 +1571,6 @@ dm9000_probe(struct platform_device *pdev)
 
        /* fill in parameters for net-dev structure */
        ndev->base_addr = (unsigned long)db->io_addr;
-       ndev->irq       = db->irq_res->start;
 
        /* ensure at least we have a default set of IO routines */
        dm9000_set_io(db, iosize);
index a7139f588ad205e0a9441ce8e7d62a2513e4d814..678f5018d0be1c410c809fd8031a9f6e6601210e 100644 (file)
@@ -469,8 +469,8 @@ static int fmvj18x_config(struct pcmcia_device *link)
                    goto failed;
            }
            /* Read MACID from CIS */
-           for (i = 5; i < 11; i++)
-                   dev->dev_addr[i] = buf[i];
+           for (i = 0; i < 6; i++)
+                   dev->dev_addr[i] = buf[i + 5];
            kfree(buf);
        } else {
            if (pcmcia_get_mac_from_cis(link, dev))
index 662c2ee268c7c7512c7d5f1290e1cb02fa3883dc..b0ae69f8449369585dfa82de3243f401f8a1022a 100644 (file)
@@ -370,6 +370,11 @@ struct mvneta_port {
        struct net_device *dev;
        struct notifier_block cpu_notifier;
        int rxq_def;
+       /* Protect the access to the percpu interrupt registers,
+        * ensuring that the configuration remains coherent.
+        */
+       spinlock_t lock;
+       bool is_stopped;
 
        /* Core clock */
        struct clk *clk;
@@ -1038,6 +1043,43 @@ static void mvneta_set_autoneg(struct mvneta_port *pp, int enable)
        }
 }
 
+static void mvneta_percpu_unmask_interrupt(void *arg)
+{
+       struct mvneta_port *pp = arg;
+
+       /* All the queue are unmasked, but actually only the ones
+        * mapped to this CPU will be unmasked
+        */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+                   MVNETA_RX_INTR_MASK_ALL |
+                   MVNETA_TX_INTR_MASK_ALL |
+                   MVNETA_MISCINTR_INTR_MASK);
+}
+
+static void mvneta_percpu_mask_interrupt(void *arg)
+{
+       struct mvneta_port *pp = arg;
+
+       /* All the queue are masked, but actually only the ones
+        * mapped to this CPU will be masked
+        */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+}
+
+static void mvneta_percpu_clear_intr_cause(void *arg)
+{
+       struct mvneta_port *pp = arg;
+
+       /* All the queue are cleared, but actually only the ones
+        * mapped to this CPU will be cleared
+        */
+       mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
+}
+
 /* This method sets defaults to the NETA port:
  *     Clears interrupt Cause and Mask registers.
  *     Clears all MAC tables.
@@ -1055,14 +1097,10 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
        int max_cpu = num_present_cpus();
 
        /* Clear all Cause registers */
-       mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0);
-       mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
-       mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+       on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true);
 
        /* Mask all interrupts */
-       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
-       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
-       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+       on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
        mvreg_write(pp, MVNETA_INTR_ENABLE, 0);
 
        /* Enable MBUS Retry bit16 */
@@ -2528,34 +2566,9 @@ static int mvneta_setup_txqs(struct mvneta_port *pp)
        return 0;
 }
 
-static void mvneta_percpu_unmask_interrupt(void *arg)
-{
-       struct mvneta_port *pp = arg;
-
-       /* All the queue are unmasked, but actually only the ones
-        * maped to this CPU will be unmasked
-        */
-       mvreg_write(pp, MVNETA_INTR_NEW_MASK,
-                   MVNETA_RX_INTR_MASK_ALL |
-                   MVNETA_TX_INTR_MASK_ALL |
-                   MVNETA_MISCINTR_INTR_MASK);
-}
-
-static void mvneta_percpu_mask_interrupt(void *arg)
-{
-       struct mvneta_port *pp = arg;
-
-       /* All the queue are masked, but actually only the ones
-        * maped to this CPU will be masked
-        */
-       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
-       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
-       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
-}
-
 static void mvneta_start_dev(struct mvneta_port *pp)
 {
-       unsigned int cpu;
+       int cpu;
 
        mvneta_max_rx_size_set(pp, pp->pkt_size);
        mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
@@ -2564,16 +2577,15 @@ static void mvneta_start_dev(struct mvneta_port *pp)
        mvneta_port_enable(pp);
 
        /* Enable polling on the port */
-       for_each_present_cpu(cpu) {
+       for_each_online_cpu(cpu) {
                struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
 
                napi_enable(&port->napi);
        }
 
        /* Unmask interrupts. It has to be done from each CPU */
-       for_each_online_cpu(cpu)
-               smp_call_function_single(cpu, mvneta_percpu_unmask_interrupt,
-                                        pp, true);
+       on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
+
        mvreg_write(pp, MVNETA_INTR_MISC_MASK,
                    MVNETA_CAUSE_PHY_STATUS_CHANGE |
                    MVNETA_CAUSE_LINK_CHANGE |
@@ -2589,7 +2601,7 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
 
        phy_stop(pp->phy_dev);
 
-       for_each_present_cpu(cpu) {
+       for_each_online_cpu(cpu) {
                struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
 
                napi_disable(&port->napi);
@@ -2604,13 +2616,10 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
        mvneta_port_disable(pp);
 
        /* Clear all ethernet port interrupts */
-       mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
-       mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
+       on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true);
 
        /* Mask all ethernet port interrupts */
-       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
-       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
-       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+       on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
 
        mvneta_tx_reset(pp);
        mvneta_rx_reset(pp);
@@ -2847,11 +2856,20 @@ static void mvneta_percpu_disable(void *arg)
        disable_percpu_irq(pp->dev->irq);
 }
 
+/* Electing a CPU must be done in an atomic way: it should be done
+ * after or before the removal/insertion of a CPU and this function is
+ * not reentrant.
+ */
 static void mvneta_percpu_elect(struct mvneta_port *pp)
 {
-       int online_cpu_idx, max_cpu, cpu, i = 0;
+       int elected_cpu = 0, max_cpu, cpu, i = 0;
+
+       /* Use the cpu associated to the rxq when it is online, in all
+        * the other cases, use the cpu 0 which can't be offline.
+        */
+       if (cpu_online(pp->rxq_def))
+               elected_cpu = pp->rxq_def;
 
-       online_cpu_idx = pp->rxq_def % num_online_cpus();
        max_cpu = num_present_cpus();
 
        for_each_online_cpu(cpu) {
@@ -2862,7 +2880,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp)
                        if ((rxq % max_cpu) == cpu)
                                rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
 
-               if (i == online_cpu_idx)
+               if (cpu == elected_cpu)
                        /* Map the default receive queue queue to the
                         * elected CPU
                         */
@@ -2873,7 +2891,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp)
                 * the CPU bound to the default RX queue
                 */
                if (txq_number == 1)
-                       txq_map = (i == online_cpu_idx) ?
+                       txq_map = (cpu == elected_cpu) ?
                                MVNETA_CPU_TXQ_ACCESS(1) : 0;
                else
                        txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) &
@@ -2902,6 +2920,14 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb,
        switch (action) {
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
+               spin_lock(&pp->lock);
+               /* Configuring the driver for a new CPU while the
+                * driver is stopping is racy, so just avoid it.
+                */
+               if (pp->is_stopped) {
+                       spin_unlock(&pp->lock);
+                       break;
+               }
                netif_tx_stop_all_queues(pp->dev);
 
                /* We have to synchronise on tha napi of each CPU
@@ -2917,9 +2943,7 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb,
                }
 
                /* Mask all ethernet port interrupts */
-               mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
-               mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
-               mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+               on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
                napi_enable(&port->napi);
 
 
@@ -2934,27 +2958,25 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb,
                 */
                mvneta_percpu_elect(pp);
 
-               /* Unmask all ethernet port interrupts, as this
-                * notifier is called for each CPU then the CPU to
-                * Queue mapping is applied
-                */
-               mvreg_write(pp, MVNETA_INTR_NEW_MASK,
-                       MVNETA_RX_INTR_MASK(rxq_number) |
-                       MVNETA_TX_INTR_MASK(txq_number) |
-                       MVNETA_MISCINTR_INTR_MASK);
+               /* Unmask all ethernet port interrupts */
+               on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
                mvreg_write(pp, MVNETA_INTR_MISC_MASK,
                        MVNETA_CAUSE_PHY_STATUS_CHANGE |
                        MVNETA_CAUSE_LINK_CHANGE |
                        MVNETA_CAUSE_PSC_SYNC_CHANGE);
                netif_tx_start_all_queues(pp->dev);
+               spin_unlock(&pp->lock);
                break;
        case CPU_DOWN_PREPARE:
        case CPU_DOWN_PREPARE_FROZEN:
                netif_tx_stop_all_queues(pp->dev);
+               /* Thanks to this lock we are sure that any pending
+                * cpu election is done
+                */
+               spin_lock(&pp->lock);
                /* Mask all ethernet port interrupts */
-               mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
-               mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
-               mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+               on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
+               spin_unlock(&pp->lock);
 
                napi_synchronize(&port->napi);
                napi_disable(&port->napi);
@@ -2968,12 +2990,11 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb,
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
                /* Check if a new CPU must be elected now this on is down */
+               spin_lock(&pp->lock);
                mvneta_percpu_elect(pp);
+               spin_unlock(&pp->lock);
                /* Unmask all ethernet port interrupts */
-               mvreg_write(pp, MVNETA_INTR_NEW_MASK,
-                       MVNETA_RX_INTR_MASK(rxq_number) |
-                       MVNETA_TX_INTR_MASK(txq_number) |
-                       MVNETA_MISCINTR_INTR_MASK);
+               on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
                mvreg_write(pp, MVNETA_INTR_MISC_MASK,
                        MVNETA_CAUSE_PHY_STATUS_CHANGE |
                        MVNETA_CAUSE_LINK_CHANGE |
@@ -2988,7 +3009,7 @@ static int mvneta_percpu_notifier(struct notifier_block *nfb,
 static int mvneta_open(struct net_device *dev)
 {
        struct mvneta_port *pp = netdev_priv(dev);
-       int ret, cpu;
+       int ret;
 
        pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu);
        pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) +
@@ -3010,22 +3031,12 @@ static int mvneta_open(struct net_device *dev)
                goto err_cleanup_txqs;
        }
 
-       /* Even though the documentation says that request_percpu_irq
-        * doesn't enable the interrupts automatically, it actually
-        * does so on the local CPU.
-        *
-        * Make sure it's disabled.
-        */
-       mvneta_percpu_disable(pp);
-
        /* Enable per-CPU interrupt on all the CPU to handle our RX
         * queue interrupts
         */
-       for_each_online_cpu(cpu)
-               smp_call_function_single(cpu, mvneta_percpu_enable,
-                                        pp, true);
-
+       on_each_cpu(mvneta_percpu_enable, pp, true);
 
+       pp->is_stopped = false;
        /* Register a CPU notifier to handle the case where our CPU
         * might be taken offline.
         */
@@ -3057,13 +3068,20 @@ err_cleanup_rxqs:
 static int mvneta_stop(struct net_device *dev)
 {
        struct mvneta_port *pp = netdev_priv(dev);
-       int cpu;
 
+       /* Inform that we are stopping so we don't want to setup the
+        * driver for new CPUs in the notifiers
+        */
+       spin_lock(&pp->lock);
+       pp->is_stopped = true;
        mvneta_stop_dev(pp);
        mvneta_mdio_remove(pp);
        unregister_cpu_notifier(&pp->cpu_notifier);
-       for_each_present_cpu(cpu)
-               smp_call_function_single(cpu, mvneta_percpu_disable, pp, true);
+       /* Now that the notifier are unregistered, we can release le
+        * lock
+        */
+       spin_unlock(&pp->lock);
+       on_each_cpu(mvneta_percpu_disable, pp, true);
        free_percpu_irq(dev->irq, pp->ports);
        mvneta_cleanup_rxqs(pp);
        mvneta_cleanup_txqs(pp);
@@ -3312,9 +3330,7 @@ static int  mvneta_config_rss(struct mvneta_port *pp)
 
        netif_tx_stop_all_queues(pp->dev);
 
-       for_each_online_cpu(cpu)
-               smp_call_function_single(cpu, mvneta_percpu_mask_interrupt,
-                                        pp, true);
+       on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
 
        /* We have to synchronise on the napi of each CPU */
        for_each_online_cpu(cpu) {
@@ -3335,7 +3351,9 @@ static int  mvneta_config_rss(struct mvneta_port *pp)
        mvreg_write(pp, MVNETA_PORT_CONFIG, val);
 
        /* Update the elected CPU matching the new rxq_def */
+       spin_lock(&pp->lock);
        mvneta_percpu_elect(pp);
+       spin_unlock(&pp->lock);
 
        /* We have to synchronise on the napi of each CPU */
        for_each_online_cpu(cpu) {
index a4beccf1fd46e26483dc796829d444a15f77723f..c797971aefabbd89ddd31e8defd7ff9f93508f0c 100644 (file)
@@ -3061,7 +3061,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
 
                pe = kzalloc(sizeof(*pe), GFP_KERNEL);
                if (!pe)
-                       return -1;
+                       return -ENOMEM;
                mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
                pe->index = tid;
 
@@ -3077,7 +3077,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
        if (pmap == 0) {
                if (add) {
                        kfree(pe);
-                       return -1;
+                       return -EINVAL;
                }
                mvpp2_prs_hw_inv(priv, pe->index);
                priv->prs_shadow[pe->index].valid = false;
index 715de8affcc950e0ea18fd706bc8f04542d34a6f..c7e939945259dc876b66cfedd0d85f9d7e90a914 100644 (file)
@@ -182,10 +182,17 @@ void mlx4_enter_error_state(struct mlx4_dev_persistent *persist)
                err = mlx4_reset_slave(dev);
        else
                err = mlx4_reset_master(dev);
-       BUG_ON(err != 0);
 
+       if (!err) {
+               mlx4_err(dev, "device was reset successfully\n");
+       } else {
+               /* EEH could have disabled the PCI channel during reset. That's
+                * recoverable and the PCI error flow will handle it.
+                */
+               if (!pci_channel_offline(dev->persist->pdev))
+                       BUG_ON(1);
+       }
        dev->persist->state |= MLX4_DEVICE_STATE_INTERNAL_ERROR;
-       mlx4_err(dev, "device was reset successfully\n");
        mutex_unlock(&persist->device_state_mutex);
 
        /* At that step HW was already reset, now notify clients */
index d48d5793407d9ec729fe8548a049a2506d02a934..e94ca1c3fc7c6a83a190a29d4116086dcc9de8ca 100644 (file)
@@ -2429,7 +2429,7 @@ err_thread:
        flush_workqueue(priv->mfunc.master.comm_wq);
        destroy_workqueue(priv->mfunc.master.comm_wq);
 err_slaves:
-       while (--i) {
+       while (i--) {
                for (port = 1; port <= MLX4_MAX_PORTS; port++)
                        kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
        }
index 3348e646db705f41ff1cb3923d4d1533aea80e2d..a849da92f857e5c22cd1ec93158cecbff9c75d90 100644 (file)
@@ -318,7 +318,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
        if (timestamp_en)
                cq_context->flags  |= cpu_to_be32(1 << 19);
 
-       cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
+       cq_context->logsize_usrpage =
+               cpu_to_be32((ilog2(nent) << 24) |
+                           mlx4_to_hw_uar_index(dev, uar->index));
        cq_context->comp_eqn        = priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(vector)].eqn;
        cq_context->log_page_size   = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
 
index 038f9ce391e626f02d3fe2f51a19fbd4b08a2711..1494997c4f7e3bef36141ea439d812ca9bb1a335 100644 (file)
@@ -236,6 +236,24 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = {
        .enable         = mlx4_en_phc_enable,
 };
 
+#define MLX4_EN_WRAP_AROUND_SEC        10ULL
+
+/* This function calculates the max shift that enables the user range
+ * of MLX4_EN_WRAP_AROUND_SEC values in the cycles register.
+ */
+static u32 freq_to_shift(u16 freq)
+{
+       u32 freq_khz = freq * 1000;
+       u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC;
+       u64 max_val_cycles_rounded = is_power_of_2(max_val_cycles + 1) ?
+               max_val_cycles : roundup_pow_of_two(max_val_cycles) - 1;
+       /* calculate max possible multiplier in order to fit in 64bit */
+       u64 max_mul = div_u64(0xffffffffffffffffULL, max_val_cycles_rounded);
+
+       /* This comes from the reverse of clocksource_khz2mult */
+       return ilog2(div_u64(max_mul * freq_khz, 1000000));
+}
+
 void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
 {
        struct mlx4_dev *dev = mdev->dev;
@@ -254,12 +272,7 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
        memset(&mdev->cycles, 0, sizeof(mdev->cycles));
        mdev->cycles.read = mlx4_en_read_clock;
        mdev->cycles.mask = CLOCKSOURCE_MASK(48);
-       /* Using shift to make calculation more accurate. Since current HW
-        * clock frequency is 427 MHz, and cycles are given using a 48 bits
-        * register, the biggest shift when calculating using u64, is 14
-        * (max_cycles * multiplier < 2^64)
-        */
-       mdev->cycles.shift = 14;
+       mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock);
        mdev->cycles.mult =
                clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
        mdev->nominal_c_mult = mdev->cycles.mult;
index 0c7e3f69a73bb6f787b8387efd3d34624a188568..f191a16125893e5b742c5d99ea7bd814dba433a5 100644 (file)
@@ -2344,8 +2344,6 @@ out:
        /* set offloads */
        priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
                                      NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL;
-       priv->dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-       priv->dev->features    |= NETIF_F_GSO_UDP_TUNNEL;
 }
 
 static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
@@ -2356,8 +2354,6 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
        /* unset offloads */
        priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
                                      NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL);
-       priv->dev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL;
-       priv->dev->features    &= ~NETIF_F_GSO_UDP_TUNNEL;
 
        ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
                                  VXLAN_STEER_BY_OUTER_MAC, 0);
@@ -2980,6 +2976,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                priv->rss_hash_fn = ETH_RSS_HASH_TOP;
        }
 
+       if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+               dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+               dev->features    |= NETIF_F_GSO_UDP_TUNNEL;
+       }
+
        mdev->pndev[port] = dev;
        mdev->upper[port] = NULL;
 
index ee99e67187f5b1cc68fc224b91d5b2bf2d133b05..3904b5fc0b7c904548763ffbb2d31fbcccfe5b6c 100644 (file)
@@ -238,11 +238,11 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
        stats->collisions = 0;
        stats->rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP);
        stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
-       stats->rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+       stats->rx_over_errors = 0;
        stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
        stats->rx_frame_errors = 0;
        stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
-       stats->rx_missed_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+       stats->rx_missed_errors = 0;
        stats->tx_aborted_errors = 0;
        stats->tx_carrier_errors = 0;
        stats->tx_fifo_errors = 0;
index 12aab5a659d33e4c098a6b8bedf2d4014798e14c..02e925d6f7348d774fe70c4a91b5038d5a27ba35 100644 (file)
@@ -58,7 +58,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
        } else {
                context->sq_size_stride = ilog2(TXBB_SIZE) - 4;
        }
-       context->usr_page = cpu_to_be32(mdev->priv_uar.index);
+       context->usr_page = cpu_to_be32(mlx4_to_hw_uar_index(mdev->dev,
+                                       mdev->priv_uar.index));
        context->local_qpn = cpu_to_be32(qpn);
        context->pri_path.ackto = 1 & 0x07;
        context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6;
index 4421bf5463f67159618c3a4c572b4e9ebc04dd7b..e0946ab22010f4d1c28373b33e8a9b8d334c764b 100644 (file)
@@ -213,7 +213,9 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
        mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
                                ring->cqn, user_prio, &ring->context);
        if (ring->bf_alloced)
-               ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
+               ring->context.usr_page =
+                       cpu_to_be32(mlx4_to_hw_uar_index(mdev->dev,
+                                                        ring->bf.uar->index));
 
        err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
                               &ring->qp, &ring->qp_state);
index 4696053165f8ca192d5e8ccb21971d175d267ca7..f613977455e08340995baeb65763086e408479f3 100644 (file)
@@ -940,9 +940,10 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
 
        if (!priv->eq_table.uar_map[index]) {
                priv->eq_table.uar_map[index] =
-                       ioremap(pci_resource_start(dev->persist->pdev, 2) +
-                               ((eq->eqn / 4) << PAGE_SHIFT),
-                               PAGE_SIZE);
+                       ioremap(
+                               pci_resource_start(dev->persist->pdev, 2) +
+                               ((eq->eqn / 4) << (dev->uar_page_shift)),
+                               (1 << (dev->uar_page_shift)));
                if (!priv->eq_table.uar_map[index]) {
                        mlx4_err(dev, "Couldn't map EQ doorbell for EQN 0x%06x\n",
                                 eq->eqn);
index f1b6d219e445431c0dfe4f255b8abe9d3ec5f9b4..2cc3c626c3fea732d0862ff5f0ce520d442a6205 100644 (file)
@@ -168,6 +168,20 @@ struct mlx4_port_config {
 
 static atomic_t pf_loading = ATOMIC_INIT(0);
 
+static inline void mlx4_set_num_reserved_uars(struct mlx4_dev *dev,
+                                             struct mlx4_dev_cap *dev_cap)
+{
+       /* The reserved_uars is calculated by system page size unit.
+        * Therefore, adjustment is added when the uar page size is less
+        * than the system page size
+        */
+       dev->caps.reserved_uars =
+               max_t(int,
+                     mlx4_get_num_reserved_uar(dev),
+                     dev_cap->reserved_uars /
+                       (1 << (PAGE_SHIFT - dev->uar_page_shift)));
+}
+
 int mlx4_check_port_params(struct mlx4_dev *dev,
                           enum mlx4_port_type *port_type)
 {
@@ -386,8 +400,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        dev->caps.reserved_mtts      = dev_cap->reserved_mtts;
        dev->caps.reserved_mrws      = dev_cap->reserved_mrws;
 
-       /* The first 128 UARs are used for EQ doorbells */
-       dev->caps.reserved_uars      = max_t(int, 128, dev_cap->reserved_uars);
        dev->caps.reserved_pds       = dev_cap->reserved_pds;
        dev->caps.reserved_xrcds     = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
                                        dev_cap->reserved_xrcds : 0;
@@ -405,6 +417,15 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        dev->caps.max_gso_sz         = dev_cap->max_gso_sz;
        dev->caps.max_rss_tbl_sz     = dev_cap->max_rss_tbl_sz;
 
+       /* Save uar page shift */
+       if (!mlx4_is_slave(dev)) {
+               /* Virtual PCI function needs to determine UAR page size from
+                * firmware. Only master PCI function can set the uar page size
+                */
+               dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT;
+               mlx4_set_num_reserved_uars(dev, dev_cap);
+       }
+
        if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PHV_EN) {
                struct mlx4_init_hca_param hca_param;
 
@@ -815,16 +836,25 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                return -ENODEV;
        }
 
-       /* slave gets uar page size from QUERY_HCA fw command */
-       dev->caps.uar_page_size = 1 << (hca_param.uar_page_sz + 12);
+       /* Set uar_page_shift for VF */
+       dev->uar_page_shift = hca_param.uar_page_sz + 12;
 
-       /* TODO: relax this assumption */
-       if (dev->caps.uar_page_size != PAGE_SIZE) {
-               mlx4_err(dev, "UAR size:%d != kernel PAGE_SIZE of %ld\n",
-                        dev->caps.uar_page_size, PAGE_SIZE);
-               return -ENODEV;
+       /* Make sure the master uar page size is valid */
+       if (dev->uar_page_shift > PAGE_SHIFT) {
+               mlx4_err(dev,
+                        "Invalid configuration: uar page size is larger than system page size\n");
+               return  -ENODEV;
        }
 
+       /* Set reserved_uars based on the uar_page_shift */
+       mlx4_set_num_reserved_uars(dev, &dev_cap);
+
+       /* Although uar page size in FW differs from system page size,
+        * upper software layers (mlx4_ib, mlx4_en and part of mlx4_core)
+        * still works with assumption that uar page size == system page size
+        */
+       dev->caps.uar_page_size = PAGE_SIZE;
+
        memset(&func_cap, 0, sizeof(func_cap));
        err = mlx4_QUERY_FUNC_CAP(dev, 0, &func_cap);
        if (err) {
@@ -2179,8 +2209,12 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 
                dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1;
 
-               init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
-               init_hca.uar_page_sz = PAGE_SHIFT - 12;
+               /* Always set UAR page size 4KB, set log_uar_sz accordingly */
+               init_hca.log_uar_sz = ilog2(dev->caps.num_uars) +
+                                     PAGE_SHIFT -
+                                     DEFAULT_UAR_PAGE_SHIFT;
+               init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12;
+
                init_hca.mw_enabled = 0;
                if (dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW ||
                    dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN)
index 609c59dc854e987a073e32cb4ff2c08736998edb..b3cc3ab63799462709a569cff08f6e4c5de59f43 100644 (file)
@@ -269,9 +269,15 @@ EXPORT_SYMBOL_GPL(mlx4_bf_free);
 
 int mlx4_init_uar_table(struct mlx4_dev *dev)
 {
-       if (dev->caps.num_uars <= 128) {
-               mlx4_err(dev, "Only %d UAR pages (need more than 128)\n",
-                        dev->caps.num_uars);
+       int num_reserved_uar = mlx4_get_num_reserved_uar(dev);
+
+       mlx4_dbg(dev, "uar_page_shift = %d", dev->uar_page_shift);
+       mlx4_dbg(dev, "Effective reserved_uars=%d", dev->caps.reserved_uars);
+
+       if (dev->caps.num_uars <= num_reserved_uar) {
+               mlx4_err(
+                       dev, "Only %d UAR pages (need more than %d)\n",
+                       dev->caps.num_uars, num_reserved_uar);
                mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n");
                return -ENODEV;
        }
index b46dbe29ef6c8ec72db19c6e8fd841f5cb806a1b..25ce1b030a00f28cb3ea96833d368d7380aaff44 100644 (file)
@@ -915,11 +915,13 @@ static int handle_existing_counter(struct mlx4_dev *dev, u8 slave, int port,
 
        spin_lock_irq(mlx4_tlock(dev));
        r = find_res(dev, counter_index, RES_COUNTER);
-       if (!r || r->owner != slave)
+       if (!r || r->owner != slave) {
                ret = -EINVAL;
-       counter = container_of(r, struct res_counter, com);
-       if (!counter->port)
-               counter->port = port;
+       } else {
+               counter = container_of(r, struct res_counter, com);
+               if (!counter->port)
+                       counter->port = port;
+       }
 
        spin_unlock_irq(mlx4_tlock(dev));
        return ret;
index 6a3e430f10624e637fb8b3dcfaade968d2a83c53..d4e1c30452009718d9761a8a4949f5195d7f4c59 100644 (file)
@@ -2024,18 +2024,37 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
                                            vf_stats);
 }
 
-static struct net_device_ops mlx5e_netdev_ops = {
+static const struct net_device_ops mlx5e_netdev_ops_basic = {
        .ndo_open                = mlx5e_open,
        .ndo_stop                = mlx5e_close,
        .ndo_start_xmit          = mlx5e_xmit,
        .ndo_get_stats64         = mlx5e_get_stats,
        .ndo_set_rx_mode         = mlx5e_set_rx_mode,
        .ndo_set_mac_address     = mlx5e_set_mac,
-       .ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
-       .ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
+       .ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
        .ndo_set_features        = mlx5e_set_features,
-       .ndo_change_mtu          = mlx5e_change_mtu,
-       .ndo_do_ioctl            = mlx5e_ioctl,
+       .ndo_change_mtu          = mlx5e_change_mtu,
+       .ndo_do_ioctl            = mlx5e_ioctl,
+};
+
+static const struct net_device_ops mlx5e_netdev_ops_sriov = {
+       .ndo_open                = mlx5e_open,
+       .ndo_stop                = mlx5e_close,
+       .ndo_start_xmit          = mlx5e_xmit,
+       .ndo_get_stats64         = mlx5e_get_stats,
+       .ndo_set_rx_mode         = mlx5e_set_rx_mode,
+       .ndo_set_mac_address     = mlx5e_set_mac,
+       .ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
+       .ndo_set_features        = mlx5e_set_features,
+       .ndo_change_mtu          = mlx5e_change_mtu,
+       .ndo_do_ioctl            = mlx5e_ioctl,
+       .ndo_set_vf_mac          = mlx5e_set_vf_mac,
+       .ndo_set_vf_vlan         = mlx5e_set_vf_vlan,
+       .ndo_get_vf_config       = mlx5e_get_vf_config,
+       .ndo_set_vf_link_state   = mlx5e_set_vf_link_state,
+       .ndo_get_vf_stats        = mlx5e_get_vf_stats,
 };
 
 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
@@ -2137,18 +2156,11 @@ static void mlx5e_build_netdev(struct net_device *netdev)
 
        SET_NETDEV_DEV(netdev, &mdev->pdev->dev);
 
-       if (priv->params.num_tc > 1)
-               mlx5e_netdev_ops.ndo_select_queue = mlx5e_select_queue;
-
-       if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
-               mlx5e_netdev_ops.ndo_set_vf_mac = mlx5e_set_vf_mac;
-               mlx5e_netdev_ops.ndo_set_vf_vlan = mlx5e_set_vf_vlan;
-               mlx5e_netdev_ops.ndo_get_vf_config = mlx5e_get_vf_config;
-               mlx5e_netdev_ops.ndo_set_vf_link_state = mlx5e_set_vf_link_state;
-               mlx5e_netdev_ops.ndo_get_vf_stats = mlx5e_get_vf_stats;
-       }
+       if (MLX5_CAP_GEN(mdev, vport_group_manager))
+               netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
+       else
+               netdev->netdev_ops = &mlx5e_netdev_ops_basic;
 
-       netdev->netdev_ops        = &mlx5e_netdev_ops;
        netdev->watchdog_timeo    = 15 * HZ;
 
        netdev->ethtool_ops       = &mlx5e_ethtool_ops;
index 726f5435b32f15ec3a39c7710a998c469fdd3837..ae65b9940aed4823319f1e4db5c2ac6fe6dc9b28 100644 (file)
@@ -49,7 +49,7 @@
 #define MLXSW_PORT_MID                 0xd000
 
 #define MLXSW_PORT_MAX_PHY_PORTS       0x40
-#define MLXSW_PORT_MAX_PORTS           MLXSW_PORT_MAX_PHY_PORTS
+#define MLXSW_PORT_MAX_PORTS           (MLXSW_PORT_MAX_PHY_PORTS + 1)
 
 #define MLXSW_PORT_DEVID_BITS_OFFSET   10
 #define MLXSW_PORT_PHY_BITS_OFFSET     4
index bb77e2207804d9c3431b091f8d219297c8f92300..ffe4c030573332cf43bb8b3d66a0eb922031da5c 100644 (file)
@@ -873,6 +873,62 @@ static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port,
        }
 }
 
+/* SPAFT - Switch Port Acceptable Frame Types
+ * ------------------------------------------
+ * The Switch Port Acceptable Frame Types register configures the frame
+ * admittance of the port.
+ */
+#define MLXSW_REG_SPAFT_ID 0x2010
+#define MLXSW_REG_SPAFT_LEN 0x08
+
+static const struct mlxsw_reg_info mlxsw_reg_spaft = {
+       .id = MLXSW_REG_SPAFT_ID,
+       .len = MLXSW_REG_SPAFT_LEN,
+};
+
+/* reg_spaft_local_port
+ * Local port number.
+ * Access: Index
+ *
+ * Note: CPU port is not supported (all tag types are allowed).
+ */
+MLXSW_ITEM32(reg, spaft, local_port, 0x00, 16, 8);
+
+/* reg_spaft_sub_port
+ * Virtual port within the physical port.
+ * Should be set to 0 when virtual ports are not enabled on the port.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spaft, sub_port, 0x00, 8, 8);
+
+/* reg_spaft_allow_untagged
+ * When set, untagged frames on the ingress are allowed (default).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spaft, allow_untagged, 0x04, 31, 1);
+
+/* reg_spaft_allow_prio_tagged
+ * When set, priority tagged frames on the ingress are allowed (default).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spaft, allow_prio_tagged, 0x04, 30, 1);
+
+/* reg_spaft_allow_tagged
+ * When set, tagged frames on the ingress are allowed (default).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, spaft, allow_tagged, 0x04, 29, 1);
+
+static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port,
+                                       bool allow_untagged)
+{
+       MLXSW_REG_ZERO(spaft, payload);
+       mlxsw_reg_spaft_local_port_set(payload, local_port);
+       mlxsw_reg_spaft_allow_untagged_set(payload, allow_untagged);
+       mlxsw_reg_spaft_allow_prio_tagged_set(payload, true);
+       mlxsw_reg_spaft_allow_tagged_set(payload, true);
+}
+
 /* SFGC - Switch Flooding Group Configuration
  * ------------------------------------------
  * The following register controls the association of flooding tables and MIDs
@@ -3203,6 +3259,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id)
                return "SPVID";
        case MLXSW_REG_SPVM_ID:
                return "SPVM";
+       case MLXSW_REG_SPAFT_ID:
+               return "SPAFT";
        case MLXSW_REG_SFGC_ID:
                return "SFGC";
        case MLXSW_REG_SFTR_ID:
index 217856bdd400474d400d1e4e3dd275a096f50db5..09ce451c283bb8dfb5dd9c4c69bdeb04c0e796b3 100644 (file)
@@ -2123,6 +2123,8 @@ static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        if (flush_fdb && mlxsw_sp_port_fdb_flush(mlxsw_sp_port))
                netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n");
 
+       mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
+
        mlxsw_sp_port->learning = 0;
        mlxsw_sp_port->learning_sync = 0;
        mlxsw_sp_port->uc_flood = 0;
@@ -2746,6 +2748,13 @@ static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
                goto err_vport_flood_set;
        }
 
+       err = mlxsw_sp_port_stp_state_set(mlxsw_sp_vport, vid,
+                                         MLXSW_REG_SPMS_STATE_FORWARDING);
+       if (err) {
+               netdev_err(dev, "Failed to set STP state\n");
+               goto err_port_stp_state_set;
+       }
+
        if (flush_fdb && mlxsw_sp_vport_fdb_flush(mlxsw_sp_vport))
                netdev_err(dev, "Failed to flush FDB\n");
 
@@ -2763,6 +2772,7 @@ static int mlxsw_sp_vport_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_vport,
 
        return 0;
 
+err_port_stp_state_set:
 err_vport_flood_set:
 err_port_vid_learning_set:
 err_port_vid_to_fid_validate:
index 7f42eb1c320e1c02ff12892c94261800e29eed64..3b89ed2f3c76b8b6eebd5fa6f7d1f52a70d75585 100644 (file)
@@ -254,5 +254,6 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
 int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
                             bool set, bool only_uc);
 void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
+int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
 
 #endif
index e492ca2cdecd9953d5f0ec4124f7077e839803dc..7b56098acc58eb9e1d5cd4d586e75989ae83f01a 100644 (file)
@@ -370,7 +370,8 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
        return err;
 }
 
-static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
+static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                   u16 vid)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char spvid_pl[MLXSW_REG_SPVID_LEN];
@@ -379,6 +380,53 @@ static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
 }
 
+static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port,
+                                           bool allow)
+{
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+       char spaft_pl[MLXSW_REG_SPAFT_LEN];
+
+       mlxsw_reg_spaft_pack(spaft_pl, mlxsw_sp_port->local_port, allow);
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl);
+}
+
+int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
+{
+       struct net_device *dev = mlxsw_sp_port->dev;
+       int err;
+
+       if (!vid) {
+               err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, false);
+               if (err) {
+                       netdev_err(dev, "Failed to disallow untagged traffic\n");
+                       return err;
+               }
+       } else {
+               err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid);
+               if (err) {
+                       netdev_err(dev, "Failed to set PVID\n");
+                       return err;
+               }
+
+               /* Only allow if not already allowed. */
+               if (!mlxsw_sp_port->pvid) {
+                       err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port,
+                                                              true);
+                       if (err) {
+                               netdev_err(dev, "Failed to allow untagged traffic\n");
+                               goto err_port_allow_untagged_set;
+                       }
+               }
+       }
+
+       mlxsw_sp_port->pvid = vid;
+       return 0;
+
+err_port_allow_untagged_set:
+       __mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid);
+       return err;
+}
+
 static int mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp, u16 fid)
 {
        char sfmr_pl[MLXSW_REG_SFMR_LEN];
@@ -540,7 +588,12 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                        netdev_err(dev, "Unable to add PVID %d\n", vid_begin);
                        goto err_port_pvid_set;
                }
-               mlxsw_sp_port->pvid = vid_begin;
+       } else if (!flag_pvid && old_pvid >= vid_begin && old_pvid <= vid_end) {
+               err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
+               if (err) {
+                       netdev_err(dev, "Unable to del PVID\n");
+                       goto err_port_pvid_set;
+               }
        }
 
        /* Changing activity bits only if HW operation succeded */
@@ -892,20 +945,18 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
                return err;
        }
 
+       if (init)
+               goto out;
+
        pvid = mlxsw_sp_port->pvid;
-       if (pvid >= vid_begin && pvid <= vid_end && pvid != 1) {
-               /* Default VLAN is always 1 */
-               err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
+       if (pvid >= vid_begin && pvid <= vid_end) {
+               err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
                if (err) {
                        netdev_err(dev, "Unable to del PVID %d\n", pvid);
                        return err;
                }
-               mlxsw_sp_port->pvid = 1;
        }
 
-       if (init)
-               goto out;
-
        err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end,
                                        false, false);
        if (err) {
index 17d5571d04322f1fd88adde8592e3f6ee1d80e69..537974cfd427091442acc9098a0a40535bbda431 100644 (file)
@@ -6137,28 +6137,28 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
                sw_cnt_1ms_ini = 16000000/rg_saw_cnt;
                sw_cnt_1ms_ini &= 0x0fff;
                data = r8168_mac_ocp_read(tp, 0xd412);
-               data &= 0x0fff;
+               data &= ~0x0fff;
                data |= sw_cnt_1ms_ini;
                r8168_mac_ocp_write(tp, 0xd412, data);
        }
 
        data = r8168_mac_ocp_read(tp, 0xe056);
-       data &= 0xf0;
-       data |= 0x07;
+       data &= ~0xf0;
+       data |= 0x70;
        r8168_mac_ocp_write(tp, 0xe056, data);
 
        data = r8168_mac_ocp_read(tp, 0xe052);
-       data &= 0x8008;
-       data |= 0x6000;
+       data &= ~0x6000;
+       data |= 0x8008;
        r8168_mac_ocp_write(tp, 0xe052, data);
 
        data = r8168_mac_ocp_read(tp, 0xe0d6);
-       data &= 0x01ff;
+       data &= ~0x01ff;
        data |= 0x017f;
        r8168_mac_ocp_write(tp, 0xe0d6, data);
 
        data = r8168_mac_ocp_read(tp, 0xd420);
-       data &= 0x0fff;
+       data &= ~0x0fff;
        data |= 0x047f;
        r8168_mac_ocp_write(tp, 0xd420, data);
 
index ac43ed914fcf270653a6101a2f6c736b7ac2ef00..744d7806a9eec63e1c4fb18cc7b57fa96d73fcbc 100644 (file)
@@ -1139,7 +1139,8 @@ static int ravb_set_ringparam(struct net_device *ndev,
        if (netif_running(ndev)) {
                netif_device_detach(ndev);
                /* Stop PTP Clock driver */
-               ravb_ptp_stop(ndev);
+               if (priv->chip_id == RCAR_GEN2)
+                       ravb_ptp_stop(ndev);
                /* Wait for DMA stopping */
                error = ravb_stop_dma(ndev);
                if (error) {
@@ -1170,7 +1171,8 @@ static int ravb_set_ringparam(struct net_device *ndev,
                ravb_emac_init(ndev);
 
                /* Initialise PTP Clock driver */
-               ravb_ptp_init(ndev, priv->pdev);
+               if (priv->chip_id == RCAR_GEN2)
+                       ravb_ptp_init(ndev, priv->pdev);
 
                netif_device_attach(ndev);
        }
@@ -1298,7 +1300,8 @@ static void ravb_tx_timeout_work(struct work_struct *work)
        netif_tx_stop_all_queues(ndev);
 
        /* Stop PTP Clock driver */
-       ravb_ptp_stop(ndev);
+       if (priv->chip_id == RCAR_GEN2)
+               ravb_ptp_stop(ndev);
 
        /* Wait for DMA stopping */
        ravb_stop_dma(ndev);
@@ -1311,7 +1314,8 @@ static void ravb_tx_timeout_work(struct work_struct *work)
        ravb_emac_init(ndev);
 
        /* Initialise PTP Clock driver */
-       ravb_ptp_init(ndev, priv->pdev);
+       if (priv->chip_id == RCAR_GEN2)
+               ravb_ptp_init(ndev, priv->pdev);
 
        netif_tx_start_all_queues(ndev);
 }
@@ -1814,10 +1818,6 @@ static int ravb_probe(struct platform_device *pdev)
                           CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB, CCC);
        }
 
-       /* Set CSEL value */
-       ravb_write(ndev, (ravb_read(ndev, CCC) & ~CCC_CSEL) | CCC_CSEL_HPB,
-                  CCC);
-
        /* Set GTI value */
        error = ravb_set_gti(ndev);
        if (error)
index 0e2fc1a844ab2b2453681750368e1cf9d288e779..db7db8ac4ca308a2f5f52e11f052bbd246c824a4 100644 (file)
@@ -2342,8 +2342,8 @@ static int smc_drv_probe(struct platform_device *pdev)
        }
 
        ndev->irq = platform_get_irq(pdev, 0);
-       if (ndev->irq <= 0) {
-               ret = -ENODEV;
+       if (ndev->irq < 0) {
+               ret = ndev->irq;
                goto out_release_io;
        }
        /*
index 70814b7386b3119e55ac8be1a92cfdb8c0740c5c..fc8bbff2d7e37ec19d807008c1e9b70040551ea2 100644 (file)
@@ -1880,9 +1880,9 @@ static int dwceqos_open(struct net_device *ndev)
        }
        netdev_reset_queue(ndev);
 
+       dwceqos_init_hw(lp);
        napi_enable(&lp->napi);
        phy_start(lp->phy_dev);
-       dwceqos_init_hw(lp);
 
        netif_start_queue(ndev);
        tasklet_enable(&lp->tx_bdreclaim_tasklet);
index e9cc61e1ec742090157db6b792b1a6a9168e6635..c3e85acfdc70233a628f939477b208e3dd28121b 100644 (file)
@@ -63,8 +63,12 @@ static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv,
                mode = AM33XX_GMII_SEL_MODE_RGMII;
                break;
 
-       case PHY_INTERFACE_MODE_MII:
        default:
+               dev_warn(priv->dev,
+                        "Unsupported PHY mode: \"%s\". Defaulting to MII.\n",
+                       phy_modes(phy_mode));
+               /* fallthrough */
+       case PHY_INTERFACE_MODE_MII:
                mode = AM33XX_GMII_SEL_MODE_MII;
                break;
        };
@@ -106,8 +110,12 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv,
                mode = AM33XX_GMII_SEL_MODE_RGMII;
                break;
 
-       case PHY_INTERFACE_MODE_MII:
        default:
+               dev_warn(priv->dev,
+                        "Unsupported PHY mode: \"%s\". Defaulting to MII.\n",
+                       phy_modes(phy_mode));
+               /* fallthrough */
+       case PHY_INTERFACE_MODE_MII:
                mode = AM33XX_GMII_SEL_MODE_MII;
                break;
        };
index c61d66d386346a2eda12b8fab2efaa8760b3fff3..029841f98c3216e4d9b30b1ab82448aba3ae004f 100644 (file)
@@ -117,21 +117,17 @@ static void get_pkt_info(dma_addr_t *buff, u32 *buff_len, dma_addr_t *ndesc,
        *ndesc = le32_to_cpu(desc->next_desc);
 }
 
-static void get_pad_info(u32 *pad0, u32 *pad1, u32 *pad2, struct knav_dma_desc *desc)
+static u32 get_sw_data(int index, struct knav_dma_desc *desc)
 {
-       *pad0 = le32_to_cpu(desc->pad[0]);
-       *pad1 = le32_to_cpu(desc->pad[1]);
-       *pad2 = le32_to_cpu(desc->pad[2]);
+       /* No Endian conversion needed as this data is untouched by hw */
+       return desc->sw_data[index];
 }
 
-static void get_pad_ptr(void **padptr, struct knav_dma_desc *desc)
-{
-       u64 pad64;
-
-       pad64 = le32_to_cpu(desc->pad[0]) +
-               ((u64)le32_to_cpu(desc->pad[1]) << 32);
-       *padptr = (void *)(uintptr_t)pad64;
-}
+/* use these macros to get sw data */
+#define GET_SW_DATA0(desc) get_sw_data(0, desc)
+#define GET_SW_DATA1(desc) get_sw_data(1, desc)
+#define GET_SW_DATA2(desc) get_sw_data(2, desc)
+#define GET_SW_DATA3(desc) get_sw_data(3, desc)
 
 static void get_org_pkt_info(dma_addr_t *buff, u32 *buff_len,
                             struct knav_dma_desc *desc)
@@ -163,13 +159,18 @@ static void set_desc_info(u32 desc_info, u32 pkt_info,
        desc->packet_info = cpu_to_le32(pkt_info);
 }
 
-static void set_pad_info(u32 pad0, u32 pad1, u32 pad2, struct knav_dma_desc *desc)
+static void set_sw_data(int index, u32 data, struct knav_dma_desc *desc)
 {
-       desc->pad[0] = cpu_to_le32(pad0);
-       desc->pad[1] = cpu_to_le32(pad1);
-       desc->pad[2] = cpu_to_le32(pad1);
+       /* No Endian conversion needed as this data is untouched by hw */
+       desc->sw_data[index] = data;
 }
 
+/* use these macros to set sw data */
+#define SET_SW_DATA0(data, desc) set_sw_data(0, data, desc)
+#define SET_SW_DATA1(data, desc) set_sw_data(1, data, desc)
+#define SET_SW_DATA2(data, desc) set_sw_data(2, data, desc)
+#define SET_SW_DATA3(data, desc) set_sw_data(3, data, desc)
+
 static void set_org_pkt_info(dma_addr_t buff, u32 buff_len,
                             struct knav_dma_desc *desc)
 {
@@ -581,7 +582,6 @@ static void netcp_free_rx_desc_chain(struct netcp_intf *netcp,
        dma_addr_t dma_desc, dma_buf;
        unsigned int buf_len, dma_sz = sizeof(*ndesc);
        void *buf_ptr;
-       u32 pad[2];
        u32 tmp;
 
        get_words(&dma_desc, 1, &desc->next_desc);
@@ -593,14 +593,20 @@ static void netcp_free_rx_desc_chain(struct netcp_intf *netcp,
                        break;
                }
                get_pkt_info(&dma_buf, &tmp, &dma_desc, ndesc);
-               get_pad_ptr(&buf_ptr, ndesc);
+               /* warning!!!! We are retrieving the virtual ptr in the sw_data
+                * field as a 32bit value. Will not work on 64bit machines
+                */
+               buf_ptr = (void *)GET_SW_DATA0(ndesc);
+               buf_len = (int)GET_SW_DATA1(desc);
                dma_unmap_page(netcp->dev, dma_buf, PAGE_SIZE, DMA_FROM_DEVICE);
                __free_page(buf_ptr);
                knav_pool_desc_put(netcp->rx_pool, desc);
        }
-
-       get_pad_info(&pad[0], &pad[1], &buf_len, desc);
-       buf_ptr = (void *)(uintptr_t)(pad[0] + ((u64)pad[1] << 32));
+       /* warning!!!! We are retrieving the virtual ptr in the sw_data
+        * field as a 32bit value. Will not work on 64bit machines
+        */
+       buf_ptr = (void *)GET_SW_DATA0(desc);
+       buf_len = (int)GET_SW_DATA1(desc);
 
        if (buf_ptr)
                netcp_frag_free(buf_len <= PAGE_SIZE, buf_ptr);
@@ -639,7 +645,6 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
        dma_addr_t dma_desc, dma_buff;
        struct netcp_packet p_info;
        struct sk_buff *skb;
-       u32 pad[2];
        void *org_buf_ptr;
 
        dma_desc = knav_queue_pop(netcp->rx_queue, &dma_sz);
@@ -653,8 +658,11 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
        }
 
        get_pkt_info(&dma_buff, &buf_len, &dma_desc, desc);
-       get_pad_info(&pad[0], &pad[1], &org_buf_len, desc);
-       org_buf_ptr = (void *)(uintptr_t)(pad[0] + ((u64)pad[1] << 32));
+       /* warning!!!! We are retrieving the virtual ptr in the sw_data
+        * field as a 32bit value. Will not work on 64bit machines
+        */
+       org_buf_ptr = (void *)GET_SW_DATA0(desc);
+       org_buf_len = (int)GET_SW_DATA1(desc);
 
        if (unlikely(!org_buf_ptr)) {
                dev_err(netcp->ndev_dev, "NULL bufptr in desc\n");
@@ -679,7 +687,6 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
        /* Fill in the page fragment list */
        while (dma_desc) {
                struct page *page;
-               void *ptr;
 
                ndesc = knav_pool_desc_unmap(netcp->rx_pool, dma_desc, dma_sz);
                if (unlikely(!ndesc)) {
@@ -688,8 +695,10 @@ static int netcp_process_one_rx_packet(struct netcp_intf *netcp)
                }
 
                get_pkt_info(&dma_buff, &buf_len, &dma_desc, ndesc);
-               get_pad_ptr(&ptr, ndesc);
-               page = ptr;
+               /* warning!!!! We are retrieving the virtual ptr in the sw_data
+                * field as a 32bit value. Will not work on 64bit machines
+                */
+               page = (struct page *)GET_SW_DATA0(desc);
 
                if (likely(dma_buff && buf_len && page)) {
                        dma_unmap_page(netcp->dev, dma_buff, PAGE_SIZE,
@@ -777,7 +786,10 @@ static void netcp_free_rx_buf(struct netcp_intf *netcp, int fdq)
                }
 
                get_org_pkt_info(&dma, &buf_len, desc);
-               get_pad_ptr(&buf_ptr, desc);
+               /* warning!!!! We are retrieving the virtual ptr in the sw_data
+                * field as a 32bit value. Will not work on 64bit machines
+                */
+               buf_ptr = (void *)GET_SW_DATA0(desc);
 
                if (unlikely(!dma)) {
                        dev_err(netcp->ndev_dev, "NULL orig_buff in desc\n");
@@ -829,7 +841,7 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
        struct page *page;
        dma_addr_t dma;
        void *bufptr;
-       u32 pad[3];
+       u32 sw_data[2];
 
        /* Allocate descriptor */
        hwdesc = knav_pool_desc_get(netcp->rx_pool);
@@ -846,7 +858,7 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
                                SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
                bufptr = netdev_alloc_frag(primary_buf_len);
-               pad[2] = primary_buf_len;
+               sw_data[1] = primary_buf_len;
 
                if (unlikely(!bufptr)) {
                        dev_warn_ratelimited(netcp->ndev_dev,
@@ -858,9 +870,10 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
                if (unlikely(dma_mapping_error(netcp->dev, dma)))
                        goto fail;
 
-               pad[0] = lower_32_bits((uintptr_t)bufptr);
-               pad[1] = upper_32_bits((uintptr_t)bufptr);
-
+               /* warning!!!! We are saving the virtual ptr in the sw_data
+                * field as a 32bit value. Will not work on 64bit machines
+                */
+               sw_data[0] = (u32)bufptr;
        } else {
                /* Allocate a secondary receive queue entry */
                page = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_COLD);
@@ -870,9 +883,11 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
                }
                buf_len = PAGE_SIZE;
                dma = dma_map_page(netcp->dev, page, 0, buf_len, DMA_TO_DEVICE);
-               pad[0] = lower_32_bits(dma);
-               pad[1] = upper_32_bits(dma);
-               pad[2] = 0;
+               /* warning!!!! We are saving the virtual ptr in the sw_data
+                * field as a 32bit value. Will not work on 64bit machines
+                */
+               sw_data[0] = (u32)page;
+               sw_data[1] = 0;
        }
 
        desc_info =  KNAV_DMA_DESC_PS_INFO_IN_DESC;
@@ -882,7 +897,8 @@ static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
        pkt_info |= (netcp->rx_queue_id & KNAV_DMA_DESC_RETQ_MASK) <<
                    KNAV_DMA_DESC_RETQ_SHIFT;
        set_org_pkt_info(dma, buf_len, hwdesc);
-       set_pad_info(pad[0], pad[1], pad[2], hwdesc);
+       SET_SW_DATA0(sw_data[0], hwdesc);
+       SET_SW_DATA1(sw_data[1], hwdesc);
        set_desc_info(desc_info, pkt_info, hwdesc);
 
        /* Push to FDQs */
@@ -971,7 +987,6 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
                                          unsigned int budget)
 {
        struct knav_dma_desc *desc;
-       void *ptr;
        struct sk_buff *skb;
        unsigned int dma_sz;
        dma_addr_t dma;
@@ -988,8 +1003,10 @@ static int netcp_process_tx_compl_packets(struct netcp_intf *netcp,
                        continue;
                }
 
-               get_pad_ptr(&ptr, desc);
-               skb = ptr;
+               /* warning!!!! We are retrieving the virtual ptr in the sw_data
+                * field as a 32bit value. Will not work on 64bit machines
+                */
+               skb = (struct sk_buff *)GET_SW_DATA0(desc);
                netcp_free_tx_desc_chain(netcp, desc, dma_sz);
                if (!skb) {
                        dev_err(netcp->ndev_dev, "No skb in Tx desc\n");
@@ -1194,10 +1211,10 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp,
        }
 
        set_words(&tmp, 1, &desc->packet_info);
-       tmp = lower_32_bits((uintptr_t)&skb);
-       set_words(&tmp, 1, &desc->pad[0]);
-       tmp = upper_32_bits((uintptr_t)&skb);
-       set_words(&tmp, 1, &desc->pad[1]);
+       /* warning!!!! We are saving the virtual ptr in the sw_data
+        * field as a 32bit value. Will not work on 64bit machines
+        */
+       SET_SW_DATA0((u32)skb, desc);
 
        if (tx_pipe->flags & SWITCH_TO_PORT_IN_TAGINFO) {
                tmp = tx_pipe->switch_to_port;
index 0b14ac3b8d1189081967aad8bcbbfce30016aeea..0bf7edd99573d336f179031d358f0684cf454cc7 100644 (file)
@@ -1039,6 +1039,34 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        return geneve_xmit_skb(skb, dev, info);
 }
 
+static int __geneve_change_mtu(struct net_device *dev, int new_mtu, bool strict)
+{
+       /* The max_mtu calculation does not take account of GENEVE
+        * options, to avoid excluding potentially valid
+        * configurations.
+        */
+       int max_mtu = IP_MAX_MTU - GENEVE_BASE_HLEN - sizeof(struct iphdr)
+               - dev->hard_header_len;
+
+       if (new_mtu < 68)
+               return -EINVAL;
+
+       if (new_mtu > max_mtu) {
+               if (strict)
+                       return -EINVAL;
+
+               new_mtu = max_mtu;
+       }
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+static int geneve_change_mtu(struct net_device *dev, int new_mtu)
+{
+       return __geneve_change_mtu(dev, new_mtu, true);
+}
+
 static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 {
        struct ip_tunnel_info *info = skb_tunnel_info(skb);
@@ -1083,7 +1111,7 @@ static const struct net_device_ops geneve_netdev_ops = {
        .ndo_stop               = geneve_stop,
        .ndo_start_xmit         = geneve_xmit,
        .ndo_get_stats64        = ip_tunnel_get_stats64,
-       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_change_mtu         = geneve_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_fill_metadata_dst  = geneve_fill_metadata_dst,
@@ -1150,6 +1178,7 @@ static void geneve_setup(struct net_device *dev)
        dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 
        netif_keep_dst(dev);
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
        eth_hw_addr_random(dev);
 }
@@ -1441,12 +1470,23 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
                return dev;
 
        err = geneve_configure(net, dev, &geneve_remote_unspec,
-                              0, 0, 0, htons(dst_port), true, 0);
-       if (err) {
-               free_netdev(dev);
-               return ERR_PTR(err);
-       }
+                              0, 0, 0, htons(dst_port), true,
+                              GENEVE_F_UDP_ZERO_CSUM6_RX);
+       if (err)
+               goto err;
+
+       /* openvswitch users expect packet sizes to be unrestricted,
+        * so set the largest MTU we can.
+        */
+       err = __geneve_change_mtu(dev, IP_MAX_MTU, false);
+       if (err)
+               goto err;
+
        return dev;
+
+ err:
+       free_netdev(dev);
+       return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(geneve_dev_create_fb);
 
index 1d3a66563bacbb0628e90693f8f3409c62018d68..98e34fee45c76d1df80c9c52770e9902f47720ed 100644 (file)
@@ -1089,6 +1089,9 @@ static int netvsc_probe(struct hv_device *dev,
        net->ethtool_ops = &ethtool_ops;
        SET_NETDEV_DEV(net, &dev->device);
 
+       /* We always need headroom for rndis header */
+       net->needed_headroom = RNDIS_AND_PPI_SIZE;
+
        /* Notify the netvsc driver of the new device */
        memset(&device_info, 0, sizeof(device_info));
        device_info.ring_size = ring_size;
index bf241a3ec5e56ceb9d9f85aed73bab90f1559781..db507e3bcab92d65143c170c1338af5ff60b11c5 100644 (file)
@@ -250,10 +250,6 @@ static int bcm7xxx_config_init(struct phy_device *phydev)
        phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XX_64CLK_MDIO);
        phy_read(phydev, MII_BCM7XXX_AUX_MODE);
 
-       /* Workaround only required for 100Mbits/sec capable PHYs */
-       if (phydev->supported & PHY_GBIT_FEATURES)
-               return 0;
-
        /* set shadow mode 2 */
        ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
                        MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2);
@@ -270,7 +266,7 @@ static int bcm7xxx_config_init(struct phy_device *phydev)
        phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555);
 
        /* reset shadow mode 2 */
-       ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, MII_BCM7XXX_SHD_MODE_2, 0);
+       ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2);
        if (ret < 0)
                return ret;
 
@@ -307,11 +303,6 @@ static int bcm7xxx_suspend(struct phy_device *phydev)
        return 0;
 }
 
-static int bcm7xxx_dummy_config_init(struct phy_device *phydev)
-{
-       return 0;
-}
-
 #define BCM7XXX_28NM_GPHY(_oui, _name)                                 \
 {                                                                      \
        .phy_id         = (_oui),                                       \
@@ -337,7 +328,7 @@ static struct phy_driver bcm7xxx_driver[] = {
        .phy_id         = PHY_ID_BCM7425,
        .phy_id_mask    = 0xfffffff0,
        .name           = "Broadcom BCM7425",
-       .features       = PHY_GBIT_FEATURES |
+       .features       = PHY_BASIC_FEATURES |
                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
        .flags          = PHY_IS_INTERNAL,
        .config_init    = bcm7xxx_config_init,
@@ -349,7 +340,7 @@ static struct phy_driver bcm7xxx_driver[] = {
        .phy_id         = PHY_ID_BCM7429,
        .phy_id_mask    = 0xfffffff0,
        .name           = "Broadcom BCM7429",
-       .features       = PHY_GBIT_FEATURES |
+       .features       = PHY_BASIC_FEATURES |
                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
        .flags          = PHY_IS_INTERNAL,
        .config_init    = bcm7xxx_config_init,
@@ -361,7 +352,7 @@ static struct phy_driver bcm7xxx_driver[] = {
        .phy_id         = PHY_ID_BCM7435,
        .phy_id_mask    = 0xfffffff0,
        .name           = "Broadcom BCM7435",
-       .features       = PHY_GBIT_FEATURES |
+       .features       = PHY_BASIC_FEATURES |
                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
        .flags          = PHY_IS_INTERNAL,
        .config_init    = bcm7xxx_config_init,
@@ -369,30 +360,6 @@ static struct phy_driver bcm7xxx_driver[] = {
        .read_status    = genphy_read_status,
        .suspend        = bcm7xxx_suspend,
        .resume         = bcm7xxx_config_init,
-}, {
-       .phy_id         = PHY_BCM_OUI_4,
-       .phy_id_mask    = 0xffff0000,
-       .name           = "Broadcom BCM7XXX 40nm",
-       .features       = PHY_GBIT_FEATURES |
-                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
-       .flags          = PHY_IS_INTERNAL,
-       .config_init    = bcm7xxx_config_init,
-       .config_aneg    = genphy_config_aneg,
-       .read_status    = genphy_read_status,
-       .suspend        = bcm7xxx_suspend,
-       .resume         = bcm7xxx_config_init,
-}, {
-       .phy_id         = PHY_BCM_OUI_5,
-       .phy_id_mask    = 0xffffff00,
-       .name           = "Broadcom BCM7XXX 65nm",
-       .features       = PHY_BASIC_FEATURES |
-                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
-       .flags          = PHY_IS_INTERNAL,
-       .config_init    = bcm7xxx_dummy_config_init,
-       .config_aneg    = genphy_config_aneg,
-       .read_status    = genphy_read_status,
-       .suspend        = bcm7xxx_suspend,
-       .resume         = bcm7xxx_config_init,
 } };
 
 static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
@@ -404,8 +371,6 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
        { PHY_ID_BCM7439, 0xfffffff0, },
        { PHY_ID_BCM7435, 0xfffffff0, },
        { PHY_ID_BCM7445, 0xfffffff0, },
-       { PHY_BCM_OUI_4, 0xffff0000 },
-       { PHY_BCM_OUI_5, 0xffffff00 },
        { }
 };
 
index e3eb96443c97ad0bc6e03ad0784a119d35b89ee7..ab1d0fcaf1d9cb704882bb4c4bce65fd579252d1 100644 (file)
@@ -446,6 +446,12 @@ static int m88e1510_config_aneg(struct phy_device *phydev)
        if (err < 0)
                return err;
 
+       return 0;
+}
+
+static int marvell_config_init(struct phy_device *phydev)
+{
+       /* Set registers from marvell,reg-init DT property */
        return marvell_of_reg_init(phydev);
 }
 
@@ -495,7 +501,7 @@ static int m88e1116r_config_init(struct phy_device *phydev)
 
        mdelay(500);
 
-       return 0;
+       return marvell_config_init(phydev);
 }
 
 static int m88e3016_config_init(struct phy_device *phydev)
@@ -514,7 +520,7 @@ static int m88e3016_config_init(struct phy_device *phydev)
        if (reg < 0)
                return reg;
 
-       return 0;
+       return marvell_config_init(phydev);
 }
 
 static int m88e1111_config_init(struct phy_device *phydev)
@@ -1078,6 +1084,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .probe = marvell_probe,
                .flags = PHY_HAS_INTERRUPT,
+               .config_init = &marvell_config_init,
                .config_aneg = &marvell_config_aneg,
                .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
@@ -1149,6 +1156,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
+               .config_init = &marvell_config_init,
                .config_aneg = &m88e1121_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
@@ -1167,6 +1175,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
+               .config_init = &marvell_config_init,
                .config_aneg = &m88e1318_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
@@ -1259,6 +1268,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
+               .config_init = &marvell_config_init,
                .config_aneg = &m88e1510_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
@@ -1277,6 +1287,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
+               .config_init = &marvell_config_init,
                .config_aneg = &m88e1510_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
index bad3f005faee433608f1e059cf6f07f8cbae6093..e551f3a89cfd0212e381ec274c59f558eb07d2b0 100644 (file)
@@ -1410,7 +1410,7 @@ int genphy_config_init(struct phy_device *phydev)
 
        features = (SUPPORTED_TP | SUPPORTED_MII
                        | SUPPORTED_AUI | SUPPORTED_FIBRE |
-                       SUPPORTED_BNC);
+                       SUPPORTED_BNC | SUPPORTED_Pause | SUPPORTED_Asym_Pause);
 
        /* Do we support autonegotiation? */
        val = phy_read(phydev, MII_BMSR);
index f3c63022eb3c582b46841e381e67af478c03f629..4ddae8118c8566e4de07a16b136af13597fe4f3e 100644 (file)
@@ -395,6 +395,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
 
                if (!__pppoe_xmit(sk_pppox(relay_po), skb))
                        goto abort_put;
+
+               sock_put(sk_pppox(relay_po));
        } else {
                if (sock_queue_rcv_skb(sk, skb))
                        goto abort_kfree;
index 7f83504dfa69bba2c8db612d1d25196fa5b72d91..cdde59089f729fc3578e4aea56796df237c0cee2 100644 (file)
@@ -395,6 +395,10 @@ config USB_NET_RNDIS_HOST
          The protocol specification is incomplete, and is controlled by
          (and for) Microsoft; it isn't an "Open" ecosystem or market.
 
+config USB_NET_CDC_SUBSET_ENABLE
+       tristate
+       depends on USB_NET_CDC_SUBSET
+
 config USB_NET_CDC_SUBSET
        tristate "Simple USB Network Links (CDC Ethernet subset)"
        depends on USB_USBNET
@@ -413,6 +417,7 @@ config USB_NET_CDC_SUBSET
 config USB_ALI_M5632
        bool "ALi M5632 based 'USB 2.0 Data Link' cables"
        depends on USB_NET_CDC_SUBSET
+       select USB_NET_CDC_SUBSET_ENABLE
        help
          Choose this option if you're using a host-to-host cable
          based on this design, which supports USB 2.0 high speed.
@@ -420,6 +425,7 @@ config USB_ALI_M5632
 config USB_AN2720
        bool "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
        depends on USB_NET_CDC_SUBSET
+       select USB_NET_CDC_SUBSET_ENABLE
        help
          Choose this option if you're using a host-to-host cable
          based on this design.  Note that AnchorChips is now a
@@ -428,6 +434,7 @@ config USB_AN2720
 config USB_BELKIN
        bool "eTEK based host-to-host cables (Advance, Belkin, ...)"
        depends on USB_NET_CDC_SUBSET
+       select USB_NET_CDC_SUBSET_ENABLE
        default y
        help
          Choose this option if you're using a host-to-host cable
@@ -437,6 +444,7 @@ config USB_BELKIN
 config USB_ARMLINUX
        bool "Embedded ARM Linux links (iPaq, ...)"
        depends on USB_NET_CDC_SUBSET
+       select USB_NET_CDC_SUBSET_ENABLE
        default y
        help
          Choose this option to support the "usb-eth" networking driver
@@ -454,6 +462,7 @@ config USB_ARMLINUX
 config USB_EPSON2888
        bool "Epson 2888 based firmware (DEVELOPMENT)"
        depends on USB_NET_CDC_SUBSET
+       select USB_NET_CDC_SUBSET_ENABLE
        help
          Choose this option to support the usb networking links used
          by some sample firmware from Epson.
@@ -461,6 +470,7 @@ config USB_EPSON2888
 config USB_KC2190
        bool "KT Technology KC2190 based cables (InstaNet)"
        depends on USB_NET_CDC_SUBSET
+       select USB_NET_CDC_SUBSET_ENABLE
        help
          Choose this option if you're using a host-to-host cable
          with one of these chips.
index b5f04068dbe4859fb9581304c8bd893addaaeb1d..37fb46aee341a77bf734ea55999fd70c9b8eac3a 100644 (file)
@@ -23,7 +23,7 @@ obj-$(CONFIG_USB_NET_GL620A)  += gl620a.o
 obj-$(CONFIG_USB_NET_NET1080)  += net1080.o
 obj-$(CONFIG_USB_NET_PLUSB)    += plusb.o
 obj-$(CONFIG_USB_NET_RNDIS_HOST)       += rndis_host.o
-obj-$(CONFIG_USB_NET_CDC_SUBSET)       += cdc_subset.o
+obj-$(CONFIG_USB_NET_CDC_SUBSET_ENABLE)        += cdc_subset.o
 obj-$(CONFIG_USB_NET_ZAURUS)   += zaurus.o
 obj-$(CONFIG_USB_NET_MCS7830)  += mcs7830.o
 obj-$(CONFIG_USB_USBNET)       += usbnet.o
index 23e9880791fcd3c05997e0af13d6806a75b0dffb..570deef53f74301896cfbb8e2ca5c622a5b67185 100644 (file)
@@ -637,6 +637,7 @@ static const struct usb_device_id products[] = {
 
        /* 3. Combined interface devices matching on interface number */
        {QMI_FIXED_INTF(0x0408, 0xea42, 4)},    /* Yota / Megafon M100-1 */
+       {QMI_FIXED_INTF(0x05c6, 0x6001, 3)},    /* 4G LTE usb-modem U901 */
        {QMI_FIXED_INTF(0x05c6, 0x7000, 0)},
        {QMI_FIXED_INTF(0x05c6, 0x7001, 1)},
        {QMI_FIXED_INTF(0x05c6, 0x7002, 1)},
index 221a53025fd023077adbc64f0e53a6246373032e..72ba8ae7f09a6a5a7a8b14303731997f966c9fea 100644 (file)
@@ -377,7 +377,7 @@ union Vmxnet3_GenericDesc {
 #define VMXNET3_TX_RING_MAX_SIZE   4096
 #define VMXNET3_TC_RING_MAX_SIZE   4096
 #define VMXNET3_RX_RING_MAX_SIZE   4096
-#define VMXNET3_RX_RING2_MAX_SIZE  2048
+#define VMXNET3_RX_RING2_MAX_SIZE  4096
 #define VMXNET3_RC_RING_MAX_SIZE   8192
 
 /* a list of reasons for queue stop */
index bdb8a6c0f8aa2c62e22edc64d3900530477b6fa8..729c344e677499b6f737aa622d6925c07d647a17 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.4.5.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.4.6.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01040500
+#define VMXNET3_DRIVER_VERSION_NUM      0x01040600
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index 65439188c5829e1cce0464e6c34be1c8bb5c18c3..e6944b29588e1bd329c5b331988373d5297c0bd6 100644 (file)
@@ -2171,9 +2171,11 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
        }
 
-       if (vxlan->flags & VXLAN_F_COLLECT_METADATA &&
-           info && info->mode & IP_TUNNEL_INFO_TX) {
-               vxlan_xmit_one(skb, dev, NULL, false);
+       if (vxlan->flags & VXLAN_F_COLLECT_METADATA) {
+               if (info && info->mode & IP_TUNNEL_INFO_TX)
+                       vxlan_xmit_one(skb, dev, NULL, false);
+               else
+                       kfree_skb(skb);
                return NETDEV_TX_OK;
        }
 
@@ -2367,29 +2369,43 @@ static void vxlan_set_multicast_list(struct net_device *dev)
 {
 }
 
-static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
+static int __vxlan_change_mtu(struct net_device *dev,
+                             struct net_device *lowerdev,
+                             struct vxlan_rdst *dst, int new_mtu, bool strict)
 {
-       struct vxlan_dev *vxlan = netdev_priv(dev);
-       struct vxlan_rdst *dst = &vxlan->default_dst;
-       struct net_device *lowerdev;
-       int max_mtu;
+       int max_mtu = IP_MAX_MTU;
 
-       lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex);
-       if (lowerdev == NULL)
-               return eth_change_mtu(dev, new_mtu);
+       if (lowerdev)
+               max_mtu = lowerdev->mtu;
 
        if (dst->remote_ip.sa.sa_family == AF_INET6)
-               max_mtu = lowerdev->mtu - VXLAN6_HEADROOM;
+               max_mtu -= VXLAN6_HEADROOM;
        else
-               max_mtu = lowerdev->mtu - VXLAN_HEADROOM;
+               max_mtu -= VXLAN_HEADROOM;
 
-       if (new_mtu < 68 || new_mtu > max_mtu)
+       if (new_mtu < 68)
                return -EINVAL;
 
+       if (new_mtu > max_mtu) {
+               if (strict)
+                       return -EINVAL;
+
+               new_mtu = max_mtu;
+       }
+
        dev->mtu = new_mtu;
        return 0;
 }
 
+static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct vxlan_rdst *dst = &vxlan->default_dst;
+       struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
+                                                        dst->remote_ifindex);
+       return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true);
+}
+
 static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
                                struct ip_tunnel_info *info,
                                __be16 sport, __be16 dport)
@@ -2523,6 +2539,7 @@ static void vxlan_setup(struct net_device *dev)
        dev->hw_features |= NETIF_F_GSO_SOFTWARE;
        dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
        netif_keep_dst(dev);
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
 
        INIT_LIST_HEAD(&vxlan->next);
@@ -2765,6 +2782,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
        int err;
        bool use_ipv6 = false;
        __be16 default_port = vxlan->cfg.dst_port;
+       struct net_device *lowerdev = NULL;
 
        vxlan->net = src_net;
 
@@ -2785,9 +2803,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
        }
 
        if (conf->remote_ifindex) {
-               struct net_device *lowerdev
-                        = __dev_get_by_index(src_net, conf->remote_ifindex);
-
+               lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex);
                dst->remote_ifindex = conf->remote_ifindex;
 
                if (!lowerdev) {
@@ -2811,6 +2827,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
                needed_headroom = lowerdev->hard_header_len;
        }
 
+       if (conf->mtu) {
+               err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
+               if (err)
+                       return err;
+       }
+
        if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
                needed_headroom += VXLAN6_HEADROOM;
        else
index 7a72407208b161772ba66dc284c7701ea5a85f59..6292259804634e0c6251e23dd8eb7213f16211fb 100644 (file)
@@ -1626,7 +1626,7 @@ try:
                if (state & Xpr) {
                        void __iomem *scc_addr;
                        unsigned long ring;
-                       int i;
+                       unsigned int i;
 
                        /*
                         * - the busy condition happens (sometimes);
index 866067789330ad4f4eaf0cebd7f807aa9403d1ec..7438fbeef744d8dd6d237650b81ac48b5bc3e969 100644 (file)
@@ -53,7 +53,6 @@ config IWLWIFI_LEDS
 
 config IWLDVM
        tristate "Intel Wireless WiFi DVM Firmware support"
-       depends on m
        help
          This is the driver that supports the DVM firmware. The list
          of the devices that use this firmware is available here:
index c84a0299d43e0f12b3ad80128eea8838cb2bb2ff..bce9b3420a13529926d3919fb7f14fddca559ef6 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
  *
  * 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
 
 /* Highest firmware API version supported */
 #define IWL8000_UCODE_API_MAX  20
+#define IWL8265_UCODE_API_MAX  20
 
 /* Oldest version we won't warn about */
 #define IWL8000_UCODE_API_OK   13
+#define IWL8265_UCODE_API_OK   20
 
 /* Lowest firmware API version supported */
 #define IWL8000_UCODE_API_MIN  13
+#define IWL8265_UCODE_API_MIN  20
 
 /* NVM versions */
 #define IWL8000_NVM_VERSION            0x0a1d
 #define IWL8000_MODULE_FIRMWARE(api) \
        IWL8000_FW_PRE "-" __stringify(api) ".ucode"
 
+#define IWL8265_FW_PRE "iwlwifi-8265-"
+#define IWL8265_MODULE_FIRMWARE(api) \
+       IWL8265_FW_PRE __stringify(api) ".ucode"
+
 #define NVM_HW_SECTION_NUM_FAMILY_8000         10
 #define DEFAULT_NVM_FILE_FAMILY_8000B          "nvmData-8000B"
 #define DEFAULT_NVM_FILE_FAMILY_8000C          "nvmData-8000C"
@@ -144,10 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
        .support_tx_backoff = true,
 };
 
-#define IWL_DEVICE_8000                                                        \
-       .ucode_api_max = IWL8000_UCODE_API_MAX,                         \
-       .ucode_api_ok = IWL8000_UCODE_API_OK,                           \
-       .ucode_api_min = IWL8000_UCODE_API_MIN,                         \
+#define IWL_DEVICE_8000_COMMON                                         \
        .device_family = IWL_DEVICE_FAMILY_8000,                        \
        .max_inst_size = IWL60_RTC_INST_SIZE,                           \
        .max_data_size = IWL60_RTC_DATA_SIZE,                           \
@@ -167,10 +172,28 @@ static const struct iwl_tt_params iwl8000_tt_params = {
        .thermal_params = &iwl8000_tt_params,                           \
        .apmg_not_supported = true
 
+#define IWL_DEVICE_8000                                                        \
+       IWL_DEVICE_8000_COMMON,                                         \
+       .ucode_api_max = IWL8000_UCODE_API_MAX,                         \
+       .ucode_api_ok = IWL8000_UCODE_API_OK,                           \
+       .ucode_api_min = IWL8000_UCODE_API_MIN                          \
+
+#define IWL_DEVICE_8260                                                        \
+       IWL_DEVICE_8000_COMMON,                                         \
+       .ucode_api_max = IWL8000_UCODE_API_MAX,                         \
+       .ucode_api_ok = IWL8000_UCODE_API_OK,                           \
+       .ucode_api_min = IWL8000_UCODE_API_MIN                          \
+
+#define IWL_DEVICE_8265                                                        \
+       IWL_DEVICE_8000_COMMON,                                         \
+       .ucode_api_max = IWL8265_UCODE_API_MAX,                         \
+       .ucode_api_ok = IWL8265_UCODE_API_OK,                           \
+       .ucode_api_min = IWL8265_UCODE_API_MIN                          \
+
 const struct iwl_cfg iwl8260_2n_cfg = {
        .name = "Intel(R) Dual Band Wireless N 8260",
        .fw_name_pre = IWL8000_FW_PRE,
-       IWL_DEVICE_8000,
+       IWL_DEVICE_8260,
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@@ -179,7 +202,7 @@ const struct iwl_cfg iwl8260_2n_cfg = {
 const struct iwl_cfg iwl8260_2ac_cfg = {
        .name = "Intel(R) Dual Band Wireless AC 8260",
        .fw_name_pre = IWL8000_FW_PRE,
-       IWL_DEVICE_8000,
+       IWL_DEVICE_8260,
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@@ -188,8 +211,8 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
 
 const struct iwl_cfg iwl8265_2ac_cfg = {
        .name = "Intel(R) Dual Band Wireless AC 8265",
-       .fw_name_pre = IWL8000_FW_PRE,
-       IWL_DEVICE_8000,
+       .fw_name_pre = IWL8265_FW_PRE,
+       IWL_DEVICE_8265,
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@@ -209,7 +232,7 @@ const struct iwl_cfg iwl4165_2ac_cfg = {
 const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
        .name = "Intel(R) Dual Band Wireless-AC 8260",
        .fw_name_pre = IWL8000_FW_PRE,
-       IWL_DEVICE_8000,
+       IWL_DEVICE_8260,
        .ht_params = &iwl8000_ht_params,
        .nvm_ver = IWL8000_NVM_VERSION,
        .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
@@ -236,3 +259,4 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
 };
 
 MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK));
index 7acb49075683c115d602b20619eb03700718123f..ab4c2a0470b264cc9da8623c0f7bb198563c6e28 100644 (file)
@@ -243,8 +243,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
        if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
                char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev);
 
-               snprintf(drv->firmware_name, sizeof(drv->firmware_name),
-                        "%s%c-%s.ucode", name_pre, rev_step, tag);
+               if (rev_step != 'A')
+                       snprintf(drv->firmware_name,
+                                sizeof(drv->firmware_name), "%s%c-%s.ucode",
+                                name_pre, rev_step, tag);
        }
 
        IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
index 9a15642f80dd28b88dc4ae8326f465a7ec583e35..ea1e177c2ea101463a43a1c73b7dfb995dc9b135 100644 (file)
@@ -1298,6 +1298,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
                return -EBUSY;
        }
 
+       /* we don't support "match all" in the firmware */
+       if (!req->n_match_sets)
+               return -EOPNOTSUPP;
+
        ret = iwl_mvm_check_running_scans(mvm, type);
        if (ret)
                return ret;
index cc3888e2700daf1cfe07ebb4e003ca53bcf6d934..73c95594eabe2c530d503fa51aedce05f0ffb8a9 100644 (file)
@@ -490,6 +490,15 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans)
        iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
 }
 
+static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n");
+       trans_pcie->inta_mask = CSR_INT_BIT_FH_TX;
+       iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
+}
+
 static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
index ccafbd8cf4b3b224649b3fbc87da69207884743c..152cf9ad9566587320a4a8d5dd34140b3d6b24b9 100644 (file)
@@ -1438,9 +1438,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
                         inta & ~trans_pcie->inta_mask);
        }
 
-       /* Re-enable all interrupts */
-       /* only Re-enable if disabled by irq */
-       if (test_bit(STATUS_INT_ENABLED, &trans->status))
+       /* we are loading the firmware, enable FH_TX interrupt only */
+       if (handled & CSR_INT_BIT_FH_TX)
+               iwl_enable_fw_load_int(trans);
+       /* only Re-enable all interrupt if disabled by irq */
+       else if (test_bit(STATUS_INT_ENABLED, &trans->status))
                iwl_enable_interrupts(trans);
        /* Re-enable RF_KILL if it occurred */
        else if (handled & CSR_INT_BIT_RF_KILL)
index d60a467a983c6f220384b701953eb42d2cc4c1ae..5a854c60947749cc6dd9dfd90ec90ed9b20667c0 100644 (file)
@@ -1021,82 +1021,6 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
                                               &first_ucode_section);
 }
 
-static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
-                                  const struct fw_img *fw, bool run_in_rfkill)
-{
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       bool hw_rfkill;
-       int ret;
-
-       mutex_lock(&trans_pcie->mutex);
-
-       /* Someone called stop_device, don't try to start_fw */
-       if (trans_pcie->is_down) {
-               IWL_WARN(trans,
-                        "Can't start_fw since the HW hasn't been started\n");
-               ret = EIO;
-               goto out;
-       }
-
-       /* This may fail if AMT took ownership of the device */
-       if (iwl_pcie_prepare_card_hw(trans)) {
-               IWL_WARN(trans, "Exit HW not ready\n");
-               ret = -EIO;
-               goto out;
-       }
-
-       iwl_enable_rfkill_int(trans);
-
-       /* If platform's RF_KILL switch is NOT set to KILL */
-       hw_rfkill = iwl_is_rfkill_set(trans);
-       if (hw_rfkill)
-               set_bit(STATUS_RFKILL, &trans->status);
-       else
-               clear_bit(STATUS_RFKILL, &trans->status);
-       iwl_trans_pcie_rf_kill(trans, hw_rfkill);
-       if (hw_rfkill && !run_in_rfkill) {
-               ret = -ERFKILL;
-               goto out;
-       }
-
-       iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
-
-       ret = iwl_pcie_nic_init(trans);
-       if (ret) {
-               IWL_ERR(trans, "Unable to init nic\n");
-               goto out;
-       }
-
-       /* make sure rfkill handshake bits are cleared */
-       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
-                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-       /* clear (again), then enable host interrupts */
-       iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
-       iwl_enable_interrupts(trans);
-
-       /* really make sure rfkill handshake bits are cleared */
-       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-       /* Load the given image to the HW */
-       if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
-               ret = iwl_pcie_load_given_ucode_8000(trans, fw);
-       else
-               ret = iwl_pcie_load_given_ucode(trans, fw);
-
-out:
-       mutex_unlock(&trans_pcie->mutex);
-       return ret;
-}
-
-static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
-{
-       iwl_pcie_reset_ict(trans);
-       iwl_pcie_tx_start(trans, scd_addr);
-}
-
 static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1127,7 +1051,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
         * already dead.
         */
        if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
-               IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
+               IWL_DEBUG_INFO(trans,
+                              "DEVICE_ENABLED bit was set and is now cleared\n");
                iwl_pcie_tx_stop(trans);
                iwl_pcie_rx_stop(trans);
 
@@ -1161,7 +1086,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
        iwl_disable_interrupts(trans);
        spin_unlock(&trans_pcie->irq_lock);
 
-
        /* clear all status bits */
        clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
        clear_bit(STATUS_INT_ENABLED, &trans->status);
@@ -1194,10 +1118,116 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
        if (hw_rfkill != was_hw_rfkill)
                iwl_trans_pcie_rf_kill(trans, hw_rfkill);
 
-       /* re-take ownership to prevent other users from stealing the deivce */
+       /* re-take ownership to prevent other users from stealing the device */
        iwl_pcie_prepare_card_hw(trans);
 }
 
+static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
+                                  const struct fw_img *fw, bool run_in_rfkill)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       bool hw_rfkill;
+       int ret;
+
+       /* This may fail if AMT took ownership of the device */
+       if (iwl_pcie_prepare_card_hw(trans)) {
+               IWL_WARN(trans, "Exit HW not ready\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       iwl_enable_rfkill_int(trans);
+
+       iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
+
+       /*
+        * We enabled the RF-Kill interrupt and the handler may very
+        * well be running. Disable the interrupts to make sure no other
+        * interrupt can be fired.
+        */
+       iwl_disable_interrupts(trans);
+
+       /* Make sure it finished running */
+       synchronize_irq(trans_pcie->pci_dev->irq);
+
+       mutex_lock(&trans_pcie->mutex);
+
+       /* If platform's RF_KILL switch is NOT set to KILL */
+       hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans->status);
+       iwl_trans_pcie_rf_kill(trans, hw_rfkill);
+       if (hw_rfkill && !run_in_rfkill) {
+               ret = -ERFKILL;
+               goto out;
+       }
+
+       /* Someone called stop_device, don't try to start_fw */
+       if (trans_pcie->is_down) {
+               IWL_WARN(trans,
+                        "Can't start_fw since the HW hasn't been started\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       /* make sure rfkill handshake bits are cleared */
+       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
+                   CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+       /* clear (again), then enable host interrupts */
+       iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
+
+       ret = iwl_pcie_nic_init(trans);
+       if (ret) {
+               IWL_ERR(trans, "Unable to init nic\n");
+               goto out;
+       }
+
+       /*
+        * Now, we load the firmware and don't want to be interrupted, even
+        * by the RF-Kill interrupt (hence mask all the interrupt besides the
+        * FH_TX interrupt which is needed to load the firmware). If the
+        * RF-Kill switch is toggled, we will find out after having loaded
+        * the firmware and return the proper value to the caller.
+        */
+       iwl_enable_fw_load_int(trans);
+
+       /* really make sure rfkill handshake bits are cleared */
+       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+       iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+       /* Load the given image to the HW */
+       if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+               ret = iwl_pcie_load_given_ucode_8000(trans, fw);
+       else
+               ret = iwl_pcie_load_given_ucode(trans, fw);
+       iwl_enable_interrupts(trans);
+
+       /* re-check RF-Kill state since we may have missed the interrupt */
+       hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans->status);
+
+       iwl_trans_pcie_rf_kill(trans, hw_rfkill);
+       if (hw_rfkill && !run_in_rfkill)
+               ret = -ERFKILL;
+
+out:
+       mutex_unlock(&trans_pcie->mutex);
+       return ret;
+}
+
+static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
+{
+       iwl_pcie_reset_ict(trans);
+       iwl_pcie_tx_start(trans, scd_addr);
+}
+
 static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
index 74c14ce28238eed70f8ad798f0724642147411d3..28f7010e7108bf3c3f8d3a89296b2e0b16f2c555 100644 (file)
@@ -138,6 +138,11 @@ static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv,
                    ((wireless_mode == WIRELESS_MODE_N_5G) ||
                     (wireless_mode == WIRELESS_MODE_N_24G)))
                        rate->flags |= IEEE80211_TX_RC_MCS;
+               if (sta && sta->vht_cap.vht_supported &&
+                   (wireless_mode == WIRELESS_MODE_AC_5G ||
+                    wireless_mode == WIRELESS_MODE_AC_24G ||
+                    wireless_mode == WIRELESS_MODE_AC_ONLY))
+                       rate->flags |= IEEE80211_TX_RC_VHT_MCS;
        }
 }
 
index 9ac118e727e9402032bdfe972ee40c9d34d12a00..564ca750c5ee8895a702e9a9ea145e75391e02bf 100644 (file)
@@ -175,14 +175,14 @@ int wlcore_set_partition(struct wl1271 *wl,
        if (ret < 0)
                goto out;
 
+       /* We don't need the size of the last partition, as it is
+        * automatically calculated based on the total memory size and
+        * the sizes of the previous partitions.
+        */
        ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
        if (ret < 0)
                goto out;
 
-       ret = wlcore_raw_write32(wl, HW_PART3_SIZE_ADDR, p->mem3.size);
-       if (ret < 0)
-               goto out;
-
 out:
        return ret;
 }
index 6c257b54f4150323811c46d2a49251251c113170..10cf3747694d5bf46b865fc68a990b5b4c7c5a59 100644 (file)
@@ -36,8 +36,8 @@
 #define HW_PART1_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 12)
 #define HW_PART2_SIZE_ADDR              (HW_PARTITION_REGISTERS_ADDR + 16)
 #define HW_PART2_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 20)
-#define HW_PART3_SIZE_ADDR              (HW_PARTITION_REGISTERS_ADDR + 24)
-#define HW_PART3_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 28)
+#define HW_PART3_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 24)
+
 #define HW_ACCESS_REGISTER_SIZE         4
 
 #define HW_ACCESS_PRAM_MAX_RANGE       0x3c000
index 7e2c43f701bc451463c5273ed3a5a1e49f6be15f..5d28e9405f32fb96dc79049d5cc4dbca01af14c3 100644 (file)
@@ -382,18 +382,18 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
        [ND_CMD_ARS_CAP] = {
                .in_num = 2,
                .in_sizes = { 8, 8, },
-               .out_num = 2,
-               .out_sizes = { 4, 4, },
+               .out_num = 4,
+               .out_sizes = { 4, 4, 4, 4, },
        },
        [ND_CMD_ARS_START] = {
-               .in_num = 4,
-               .in_sizes = { 8, 8, 2, 6, },
-               .out_num = 1,
-               .out_sizes = { 4, },
+               .in_num = 5,
+               .in_sizes = { 8, 8, 2, 1, 5, },
+               .out_num = 2,
+               .out_sizes = { 4, 4, },
        },
        [ND_CMD_ARS_STATUS] = {
-               .out_num = 2,
-               .out_sizes = { 4, UINT_MAX, },
+               .out_num = 3,
+               .out_sizes = { 4, 4, UINT_MAX, },
        },
 };
 
@@ -442,8 +442,8 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
                return in_field[1];
        else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2)
                return out_field[1];
-       else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 1)
-               return ND_CMD_ARS_STATUS_MAX;
+       else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
+               return out_field[1] - 8;
 
        return UINT_MAX;
 }
index 7edf31671dabed8f8d193806f54f3d1b30401e7c..8d0b546701848eb2b57d87b7207490133e5c32a9 100644 (file)
@@ -41,7 +41,7 @@ struct pmem_device {
        phys_addr_t             phys_addr;
        /* when non-zero this device is hosting a 'pfn' instance */
        phys_addr_t             data_offset;
-       unsigned long           pfn_flags;
+       u64                     pfn_flags;
        void __pmem             *virt_addr;
        size_t                  size;
        struct badblocks        bb;
index 5d6237391dcd4e3851390abe9b1412217d2428d8..b586d84f251881801ae75023fd3fd6e6bd884047 100644 (file)
@@ -17,5 +17,6 @@ config BLK_DEV_NVME_SCSI
          and block devices nodes, as well a a translation for a small
          number of selected SCSI commands to NVMe commands to the NVMe
          driver.  If you don't know what this means you probably want
-         to say N here, and if you know what it means you probably
-         want to say N as well.
+         to say N here, unless you run a distro that abuses the SCSI
+         emulation to provide stable device names for mount by id, like
+         some OpenSuSE and SLES versions.
index c5bf001af55954e2c9275d34c65cbb5dfa2a037d..03c46412fff4d602477239d0672cbdeb54c13dfb 100644 (file)
@@ -55,8 +55,9 @@ static void nvme_free_ns(struct kref *kref)
        ns->disk->private_data = NULL;
        spin_unlock(&dev_list_lock);
 
-       nvme_put_ctrl(ns->ctrl);
        put_disk(ns->disk);
+       ida_simple_remove(&ns->ctrl->ns_ida, ns->instance);
+       nvme_put_ctrl(ns->ctrl);
        kfree(ns);
 }
 
@@ -183,7 +184,7 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
                        goto out_unmap;
                }
 
-               if (meta_buffer) {
+               if (meta_buffer && meta_len) {
                        struct bio_integrity_payload *bip;
 
                        meta = kmalloc(meta_len, GFP_KERNEL);
@@ -373,6 +374,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
 
        if (copy_from_user(&io, uio, sizeof(io)))
                return -EFAULT;
+       if (io.flags)
+               return -EINVAL;
 
        switch (io.opcode) {
        case nvme_cmd_write:
@@ -424,6 +427,8 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
                return -EACCES;
        if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
                return -EFAULT;
+       if (cmd.flags)
+               return -EINVAL;
 
        memset(&c, 0, sizeof(c));
        c.common.opcode = cmd.opcode;
@@ -556,6 +561,10 @@ static int nvme_revalidate_disk(struct gendisk *disk)
        u16 old_ms;
        unsigned short bs;
 
+       if (test_bit(NVME_NS_DEAD, &ns->flags)) {
+               set_capacity(disk, 0);
+               return -ENODEV;
+       }
        if (nvme_identify_ns(ns->ctrl, ns->ns_id, &id)) {
                dev_warn(ns->ctrl->dev, "%s: Identify failure nvme%dn%d\n",
                                __func__, ns->ctrl->instance, ns->ns_id);
@@ -831,6 +840,23 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl)
        return ret;
 }
 
+static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
+               struct request_queue *q)
+{
+       if (ctrl->max_hw_sectors) {
+               u32 max_segments =
+                       (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1;
+
+               blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors);
+               blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX));
+       }
+       if (ctrl->stripe_size)
+               blk_queue_chunk_sectors(q, ctrl->stripe_size >> 9);
+       if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
+               blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
+       blk_queue_virt_boundary(q, ctrl->page_size - 1);
+}
+
 /*
  * Initialize the cached copies of the Identify data and various controller
  * register in our nvme_ctrl structure.  This should be called as soon as
@@ -888,6 +914,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                }
        }
 
+       nvme_set_queue_limits(ctrl, ctrl->admin_q);
+
        kfree(id);
        return 0;
 }
@@ -1118,10 +1146,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        if (!ns)
                return;
 
+       ns->instance = ida_simple_get(&ctrl->ns_ida, 1, 0, GFP_KERNEL);
+       if (ns->instance < 0)
+               goto out_free_ns;
+
        ns->queue = blk_mq_init_queue(ctrl->tagset);
        if (IS_ERR(ns->queue))
-               goto out_free_ns;
-       queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, ns->queue);
+               goto out_release_instance;
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, ns->queue);
        ns->queue->queuedata = ns;
        ns->ctrl = ctrl;
@@ -1135,17 +1166,9 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        ns->disk = disk;
        ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */
 
+
        blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
-       if (ctrl->max_hw_sectors) {
-               blk_queue_max_hw_sectors(ns->queue, ctrl->max_hw_sectors);
-               blk_queue_max_segments(ns->queue,
-                       (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1);
-       }
-       if (ctrl->stripe_size)
-               blk_queue_chunk_sectors(ns->queue, ctrl->stripe_size >> 9);
-       if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
-               blk_queue_flush(ns->queue, REQ_FLUSH | REQ_FUA);
-       blk_queue_virt_boundary(ns->queue, ctrl->page_size - 1);
+       nvme_set_queue_limits(ctrl, ns->queue);
 
        disk->major = nvme_major;
        disk->first_minor = 0;
@@ -1154,7 +1177,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        disk->queue = ns->queue;
        disk->driverfs_dev = ctrl->device;
        disk->flags = GENHD_FL_EXT_DEVT;
-       sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance, nsid);
+       sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance, ns->instance);
 
        if (nvme_revalidate_disk(ns->disk))
                goto out_free_disk;
@@ -1174,40 +1197,29 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        kfree(disk);
  out_free_queue:
        blk_cleanup_queue(ns->queue);
+ out_release_instance:
+       ida_simple_remove(&ctrl->ns_ida, ns->instance);
  out_free_ns:
        kfree(ns);
 }
 
 static void nvme_ns_remove(struct nvme_ns *ns)
 {
-       bool kill = nvme_io_incapable(ns->ctrl) &&
-                       !blk_queue_dying(ns->queue);
-
-       lockdep_assert_held(&ns->ctrl->namespaces_mutex);
-
-       if (kill) {
-               blk_set_queue_dying(ns->queue);
+       if (test_and_set_bit(NVME_NS_REMOVING, &ns->flags))
+               return;
 
-               /*
-                * The controller was shutdown first if we got here through
-                * device removal. The shutdown may requeue outstanding
-                * requests. These need to be aborted immediately so
-                * del_gendisk doesn't block indefinitely for their completion.
-                */
-               blk_mq_abort_requeue_list(ns->queue);
-       }
        if (ns->disk->flags & GENHD_FL_UP) {
                if (blk_get_integrity(ns->disk))
                        blk_integrity_unregister(ns->disk);
                sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
                                        &nvme_ns_attr_group);
                del_gendisk(ns->disk);
-       }
-       if (kill || !blk_queue_dying(ns->queue)) {
                blk_mq_abort_requeue_list(ns->queue);
                blk_cleanup_queue(ns->queue);
        }
+       mutex_lock(&ns->ctrl->namespaces_mutex);
        list_del_init(&ns->list);
+       mutex_unlock(&ns->ctrl->namespaces_mutex);
        nvme_put_ns(ns);
 }
 
@@ -1301,10 +1313,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
 {
        struct nvme_ns *ns, *next;
 
-       mutex_lock(&ctrl->namespaces_mutex);
        list_for_each_entry_safe(ns, next, &ctrl->namespaces, list)
                nvme_ns_remove(ns);
-       mutex_unlock(&ctrl->namespaces_mutex);
 }
 
 static DEFINE_IDA(nvme_instance_ida);
@@ -1351,6 +1361,7 @@ static void nvme_free_ctrl(struct kref *kref)
 
        put_device(ctrl->device);
        nvme_release_instance(ctrl);
+       ida_destroy(&ctrl->ns_ida);
 
        ctrl->ops->free_ctrl(ctrl);
 }
@@ -1391,6 +1402,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
        }
        get_device(ctrl->device);
        dev_set_drvdata(ctrl->device, ctrl);
+       ida_init(&ctrl->ns_ida);
 
        spin_lock(&dev_list_lock);
        list_add_tail(&ctrl->node, &nvme_ctrl_list);
@@ -1403,6 +1415,38 @@ out:
        return ret;
 }
 
+/**
+ * nvme_kill_queues(): Ends all namespace queues
+ * @ctrl: the dead controller that needs to end
+ *
+ * Call this function when the driver determines it is unable to get the
+ * controller in a state capable of servicing IO.
+ */
+void nvme_kill_queues(struct nvme_ctrl *ctrl)
+{
+       struct nvme_ns *ns;
+
+       mutex_lock(&ctrl->namespaces_mutex);
+       list_for_each_entry(ns, &ctrl->namespaces, list) {
+               if (!kref_get_unless_zero(&ns->kref))
+                       continue;
+
+               /*
+                * Revalidating a dead namespace sets capacity to 0. This will
+                * end buffered writers dirtying pages that can't be synced.
+                */
+               if (!test_and_set_bit(NVME_NS_DEAD, &ns->flags))
+                       revalidate_disk(ns->disk);
+
+               blk_set_queue_dying(ns->queue);
+               blk_mq_abort_requeue_list(ns->queue);
+               blk_mq_start_stopped_hw_queues(ns->queue, true);
+
+               nvme_put_ns(ns);
+       }
+       mutex_unlock(&ctrl->namespaces_mutex);
+}
+
 void nvme_stop_queues(struct nvme_ctrl *ctrl)
 {
        struct nvme_ns *ns;
index 5cd3725e2fa44ae7379a81a6f1bf03bf0d45e895..6bb15e4926dc86ed8b30e5cc2c504dc29090d545 100644 (file)
@@ -146,9 +146,10 @@ struct nvme_nvm_command {
        };
 };
 
+#define NVME_NVM_LP_MLC_PAIRS 886
 struct nvme_nvm_lp_mlc {
        __u16                   num_pairs;
-       __u8                    pairs[886];
+       __u8                    pairs[NVME_NVM_LP_MLC_PAIRS];
 };
 
 struct nvme_nvm_lp_tbl {
@@ -282,9 +283,14 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
                        memcpy(dst->lptbl.id, src->lptbl.id, 8);
                        dst->lptbl.mlc.num_pairs =
                                        le16_to_cpu(src->lptbl.mlc.num_pairs);
-                       /* 4 bits per pair */
+
+                       if (dst->lptbl.mlc.num_pairs > NVME_NVM_LP_MLC_PAIRS) {
+                               pr_err("nvm: number of MLC pairs not supported\n");
+                               return -EINVAL;
+                       }
+
                        memcpy(dst->lptbl.mlc.pairs, src->lptbl.mlc.pairs,
-                                               dst->lptbl.mlc.num_pairs >> 1);
+                                               dst->lptbl.mlc.num_pairs);
                }
        }
 
index 4fb5bb737868ce2db7da41700cd238c8804b086c..fb15ba5f5d19f5650fd2cb76643b2217b06891b0 100644 (file)
@@ -72,6 +72,7 @@ struct nvme_ctrl {
        struct mutex namespaces_mutex;
        struct device *device;  /* char device */
        struct list_head node;
+       struct ida ns_ida;
 
        char name[12];
        char serial[20];
@@ -102,6 +103,7 @@ struct nvme_ns {
        struct request_queue *queue;
        struct gendisk *disk;
        struct kref kref;
+       int instance;
 
        u8 eui[8];
        u8 uuid[16];
@@ -112,6 +114,11 @@ struct nvme_ns {
        bool ext;
        u8 pi_type;
        int type;
+       unsigned long flags;
+
+#define NVME_NS_REMOVING 0
+#define NVME_NS_DEAD     1
+
        u64 mode_select_num_blocks;
        u32 mode_select_block_len;
 };
@@ -139,9 +146,9 @@ static inline bool nvme_io_incapable(struct nvme_ctrl *ctrl)
        u32 val = 0;
 
        if (ctrl->ops->io_incapable(ctrl))
-               return false;
+               return true;
        if (ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &val))
-               return false;
+               return true;
        return val & NVME_CSTS_CFS;
 }
 
@@ -240,6 +247,7 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl);
 
 void nvme_stop_queues(struct nvme_ctrl *ctrl);
 void nvme_start_queues(struct nvme_ctrl *ctrl);
+void nvme_kill_queues(struct nvme_ctrl *ctrl);
 
 struct request *nvme_alloc_request(struct request_queue *q,
                struct nvme_command *cmd, unsigned int flags);
index 72ef8322d32ac7180912e2ae2cf38245f3713d9a..680f5780750cffa45efc93101fb60eb744fdd04c 100644 (file)
@@ -86,7 +86,6 @@ struct nvme_queue;
 
 static int nvme_reset(struct nvme_dev *dev);
 static void nvme_process_cq(struct nvme_queue *nvmeq);
-static void nvme_remove_dead_ctrl(struct nvme_dev *dev);
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
 
 /*
@@ -120,6 +119,7 @@ struct nvme_dev {
        unsigned long flags;
 
 #define NVME_CTRL_RESETTING    0
+#define NVME_CTRL_REMOVING     1
 
        struct nvme_ctrl ctrl;
        struct completion ioq_wait;
@@ -286,6 +286,17 @@ static int nvme_init_request(void *data, struct request *req,
        return 0;
 }
 
+static void nvme_queue_scan(struct nvme_dev *dev)
+{
+       /*
+        * Do not queue new scan work when a controller is reset during
+        * removal.
+        */
+       if (test_bit(NVME_CTRL_REMOVING, &dev->flags))
+               return;
+       queue_work(nvme_workq, &dev->scan_work);
+}
+
 static void nvme_complete_async_event(struct nvme_dev *dev,
                struct nvme_completion *cqe)
 {
@@ -300,7 +311,7 @@ static void nvme_complete_async_event(struct nvme_dev *dev,
        switch (result & 0xff07) {
        case NVME_AER_NOTICE_NS_CHANGED:
                dev_info(dev->dev, "rescanning\n");
-               queue_work(nvme_workq, &dev->scan_work);
+               nvme_queue_scan(dev);
        default:
                dev_warn(dev->dev, "async event result %08x\n", result);
        }
@@ -678,6 +689,14 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
        blk_mq_start_request(req);
 
        spin_lock_irq(&nvmeq->q_lock);
+       if (unlikely(nvmeq->cq_vector < 0)) {
+               if (ns && !test_bit(NVME_NS_DEAD, &ns->flags))
+                       ret = BLK_MQ_RQ_QUEUE_BUSY;
+               else
+                       ret = BLK_MQ_RQ_QUEUE_ERROR;
+               spin_unlock_irq(&nvmeq->q_lock);
+               goto out;
+       }
        __nvme_submit_cmd(nvmeq, &cmnd);
        nvme_process_cq(nvmeq);
        spin_unlock_irq(&nvmeq->q_lock);
@@ -999,7 +1018,7 @@ static void nvme_cancel_queue_ios(struct request *req, void *data, bool reserved
        if (!blk_mq_request_started(req))
                return;
 
-       dev_warn(nvmeq->q_dmadev,
+       dev_dbg_ratelimited(nvmeq->q_dmadev,
                 "Cancelling I/O %d QID %d\n", req->tag, nvmeq->qid);
 
        status = NVME_SC_ABORT_REQ;
@@ -1245,6 +1264,12 @@ static struct blk_mq_ops nvme_mq_ops = {
 static void nvme_dev_remove_admin(struct nvme_dev *dev)
 {
        if (dev->ctrl.admin_q && !blk_queue_dying(dev->ctrl.admin_q)) {
+               /*
+                * If the controller was reset during removal, it's possible
+                * user requests may be waiting on a stopped queue. Start the
+                * queue to flush these to completion.
+                */
+               blk_mq_start_stopped_hw_queues(dev->ctrl.admin_q, true);
                blk_cleanup_queue(dev->ctrl.admin_q);
                blk_mq_free_tag_set(&dev->admin_tagset);
        }
@@ -1685,14 +1710,14 @@ static int nvme_dev_add(struct nvme_dev *dev)
                        return 0;
                dev->ctrl.tagset = &dev->tagset;
        }
-       queue_work(nvme_workq, &dev->scan_work);
+       nvme_queue_scan(dev);
        return 0;
 }
 
-static int nvme_dev_map(struct nvme_dev *dev)
+static int nvme_pci_enable(struct nvme_dev *dev)
 {
        u64 cap;
-       int bars, result = -ENOMEM;
+       int result = -ENOMEM;
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
        if (pci_enable_device_mem(pdev))
@@ -1700,24 +1725,14 @@ static int nvme_dev_map(struct nvme_dev *dev)
 
        dev->entry[0].vector = pdev->irq;
        pci_set_master(pdev);
-       bars = pci_select_bars(pdev, IORESOURCE_MEM);
-       if (!bars)
-               goto disable_pci;
-
-       if (pci_request_selected_regions(pdev, bars, "nvme"))
-               goto disable_pci;
 
        if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) &&
            dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(32)))
                goto disable;
 
-       dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
-       if (!dev->bar)
-               goto disable;
-
        if (readl(dev->bar + NVME_REG_CSTS) == -1) {
                result = -ENODEV;
-               goto unmap;
+               goto disable;
        }
 
        /*
@@ -1727,7 +1742,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
        if (!pdev->irq) {
                result = pci_enable_msix(pdev, dev->entry, 1);
                if (result < 0)
-                       goto unmap;
+                       goto disable;
        }
 
        cap = lo_hi_readq(dev->bar + NVME_REG_CAP);
@@ -1754,17 +1769,19 @@ static int nvme_dev_map(struct nvme_dev *dev)
        pci_save_state(pdev);
        return 0;
 
- unmap:
-       iounmap(dev->bar);
-       dev->bar = NULL;
  disable:
-       pci_release_regions(pdev);
- disable_pci:
        pci_disable_device(pdev);
        return result;
 }
 
 static void nvme_dev_unmap(struct nvme_dev *dev)
+{
+       if (dev->bar)
+               iounmap(dev->bar);
+       pci_release_regions(to_pci_dev(dev->dev));
+}
+
+static void nvme_pci_disable(struct nvme_dev *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
@@ -1773,12 +1790,6 @@ static void nvme_dev_unmap(struct nvme_dev *dev)
        else if (pdev->msix_enabled)
                pci_disable_msix(pdev);
 
-       if (dev->bar) {
-               iounmap(dev->bar);
-               dev->bar = NULL;
-               pci_release_regions(pdev);
-       }
-
        if (pci_is_enabled(pdev)) {
                pci_disable_pcie_error_reporting(pdev);
                pci_disable_device(pdev);
@@ -1837,7 +1848,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
        nvme_dev_list_remove(dev);
 
        mutex_lock(&dev->shutdown_lock);
-       if (dev->bar) {
+       if (pci_is_enabled(to_pci_dev(dev->dev))) {
                nvme_stop_queues(&dev->ctrl);
                csts = readl(dev->bar + NVME_REG_CSTS);
        }
@@ -1850,7 +1861,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
                nvme_disable_io_queues(dev);
                nvme_disable_admin_queue(dev, shutdown);
        }
-       nvme_dev_unmap(dev);
+       nvme_pci_disable(dev);
 
        for (i = dev->queue_count - 1; i >= 0; i--)
                nvme_clear_queue(dev->queues[i]);
@@ -1894,10 +1905,20 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl)
        kfree(dev);
 }
 
+static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status)
+{
+       dev_warn(dev->dev, "Removing after probe failure status: %d\n", status);
+
+       kref_get(&dev->ctrl.kref);
+       nvme_dev_disable(dev, false);
+       if (!schedule_work(&dev->remove_work))
+               nvme_put_ctrl(&dev->ctrl);
+}
+
 static void nvme_reset_work(struct work_struct *work)
 {
        struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
-       int result;
+       int result = -ENODEV;
 
        if (WARN_ON(test_bit(NVME_CTRL_RESETTING, &dev->flags)))
                goto out;
@@ -1906,37 +1927,37 @@ static void nvme_reset_work(struct work_struct *work)
         * If we're called to reset a live controller first shut it down before
         * moving on.
         */
-       if (dev->bar)
+       if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
                nvme_dev_disable(dev, false);
 
        set_bit(NVME_CTRL_RESETTING, &dev->flags);
 
-       result = nvme_dev_map(dev);
+       result = nvme_pci_enable(dev);
        if (result)
                goto out;
 
        result = nvme_configure_admin_queue(dev);
        if (result)
-               goto unmap;
+               goto out;
 
        nvme_init_queue(dev->queues[0], 0);
        result = nvme_alloc_admin_tags(dev);
        if (result)
-               goto disable;
+               goto out;
 
        result = nvme_init_identify(&dev->ctrl);
        if (result)
-               goto free_tags;
+               goto out;
 
        result = nvme_setup_io_queues(dev);
        if (result)
-               goto free_tags;
+               goto out;
 
        dev->ctrl.event_limit = NVME_NR_AEN_COMMANDS;
 
        result = nvme_dev_list_add(dev);
        if (result)
-               goto remove;
+               goto out;
 
        /*
         * Keep the controller around but remove all namespaces if we don't have
@@ -1953,19 +1974,8 @@ static void nvme_reset_work(struct work_struct *work)
        clear_bit(NVME_CTRL_RESETTING, &dev->flags);
        return;
 
- remove:
-       nvme_dev_list_remove(dev);
- free_tags:
-       nvme_dev_remove_admin(dev);
-       blk_put_queue(dev->ctrl.admin_q);
-       dev->ctrl.admin_q = NULL;
-       dev->queues[0]->tags = NULL;
- disable:
-       nvme_disable_admin_queue(dev, false);
- unmap:
-       nvme_dev_unmap(dev);
  out:
-       nvme_remove_dead_ctrl(dev);
+       nvme_remove_dead_ctrl(dev, result);
 }
 
 static void nvme_remove_dead_ctrl_work(struct work_struct *work)
@@ -1973,19 +1983,12 @@ static void nvme_remove_dead_ctrl_work(struct work_struct *work)
        struct nvme_dev *dev = container_of(work, struct nvme_dev, remove_work);
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
+       nvme_kill_queues(&dev->ctrl);
        if (pci_get_drvdata(pdev))
                pci_stop_and_remove_bus_device_locked(pdev);
        nvme_put_ctrl(&dev->ctrl);
 }
 
-static void nvme_remove_dead_ctrl(struct nvme_dev *dev)
-{
-       dev_warn(dev->dev, "Removing after probe failure\n");
-       kref_get(&dev->ctrl.kref);
-       if (!schedule_work(&dev->remove_work))
-               nvme_put_ctrl(&dev->ctrl);
-}
-
 static int nvme_reset(struct nvme_dev *dev)
 {
        if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q))
@@ -2037,6 +2040,27 @@ static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
        .free_ctrl              = nvme_pci_free_ctrl,
 };
 
+static int nvme_dev_map(struct nvme_dev *dev)
+{
+       int bars;
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+       bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       if (!bars)
+               return -ENODEV;
+       if (pci_request_selected_regions(pdev, bars, "nvme"))
+               return -ENODEV;
+
+       dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
+       if (!dev->bar)
+               goto release;
+
+       return 0;
+  release:
+       pci_release_regions(pdev);
+       return -ENODEV;
+}
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int node, result = -ENOMEM;
@@ -2061,6 +2085,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dev->dev = get_device(&pdev->dev);
        pci_set_drvdata(pdev, dev);
 
+       result = nvme_dev_map(dev);
+       if (result)
+               goto free;
+
        INIT_LIST_HEAD(&dev->node);
        INIT_WORK(&dev->scan_work, nvme_dev_scan);
        INIT_WORK(&dev->reset_work, nvme_reset_work);
@@ -2084,6 +2112,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        nvme_release_prp_pools(dev);
  put_pci:
        put_device(dev->dev);
+       nvme_dev_unmap(dev);
  free:
        kfree(dev->queues);
        kfree(dev->entry);
@@ -2107,24 +2136,27 @@ static void nvme_shutdown(struct pci_dev *pdev)
        nvme_dev_disable(dev, true);
 }
 
+/*
+ * The driver's remove may be called on a device in a partially initialized
+ * state. This function must not have any dependencies on the device state in
+ * order to proceed.
+ */
 static void nvme_remove(struct pci_dev *pdev)
 {
        struct nvme_dev *dev = pci_get_drvdata(pdev);
 
-       spin_lock(&dev_list_lock);
-       list_del_init(&dev->node);
-       spin_unlock(&dev_list_lock);
-
+       set_bit(NVME_CTRL_REMOVING, &dev->flags);
        pci_set_drvdata(pdev, NULL);
-       flush_work(&dev->reset_work);
        flush_work(&dev->scan_work);
        nvme_remove_namespaces(&dev->ctrl);
        nvme_uninit_ctrl(&dev->ctrl);
        nvme_dev_disable(dev, true);
+       flush_work(&dev->reset_work);
        nvme_dev_remove_admin(dev);
        nvme_free_queues(dev, 0);
        nvme_release_cmb(dev);
        nvme_release_prp_pools(dev);
+       nvme_dev_unmap(dev);
        nvme_put_ctrl(&dev->ctrl);
 }
 
index 6fd4e5a5ef4a495bbd412ee33b931f4fb3a8a24f..9d11d98373128fef3de3406975d8bcc2ca286b9a 100644 (file)
@@ -70,6 +70,9 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
        if (pos >= nvmem->size)
                return 0;
 
+       if (count < nvmem->word_size)
+               return -EINVAL;
+
        if (pos + count > nvmem->size)
                count = nvmem->size - pos;
 
@@ -95,6 +98,9 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
        if (pos >= nvmem->size)
                return 0;
 
+       if (count < nvmem->word_size)
+               return -EINVAL;
+
        if (pos + count > nvmem->size)
                count = nvmem->size - pos;
 
index afb67e7eeee4a89612d56d0404726d7778c12a53..3829e5fbf8c366bf3ae7fa7149e87e5c0ddcf6f3 100644 (file)
@@ -21,6 +21,7 @@ static struct regmap_config qfprom_regmap_config = {
        .reg_bits = 32,
        .val_bits = 8,
        .reg_stride = 1,
+       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 static struct nvmem_config econfig = {
index 7ee21ae305ae10d480adce961ad59fe284ca366e..e7bfc175b8e1e9a0a171a3173191861399d21b1d 100644 (file)
@@ -635,6 +635,13 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
                msi_base = be32_to_cpup(msi_map + 2);
                rid_len = be32_to_cpup(msi_map + 3);
 
+               if (rid_base & ~map_mask) {
+                       dev_err(parent_dev,
+                               "Invalid msi-map translation - msi-map-mask (0x%x) ignores rid-base (0x%x)\n",
+                               map_mask, rid_base);
+                       return rid_out;
+               }
+
                msi_controller_node = of_find_node_by_phandle(phandle);
 
                matched = (masked_rid >= rid_base &&
@@ -654,7 +661,7 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
        if (!matched)
                return rid_out;
 
-       rid_out = masked_rid + msi_base;
+       rid_out = masked_rid - rid_base + msi_base;
        dev_dbg(dev,
                "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n",
                dev_name(parent_dev), map_mask, rid_base, msi_base,
index 5648317d355f1c4cde7cf7b48cdd21f644d882ca..39c4be41ef83d6cf23302fb9af6270f8857f85de 100644 (file)
@@ -154,6 +154,7 @@ static const struct of_device_id whitelist_phys[] = {
        { .compatible = "marvell,88E1111", },
        { .compatible = "marvell,88e1116", },
        { .compatible = "marvell,88e1118", },
+       { .compatible = "marvell,88e1145", },
        { .compatible = "marvell,88e1149r", },
        { .compatible = "marvell,88e1310", },
        { .compatible = "marvell,88E1510", },
index 75a6054265384d806623caabcc34d98e29a45f82..d1cdd9c992ac018fb0d8adb45780a01c201bac25 100644 (file)
@@ -14,6 +14,7 @@ config PCI_DRA7XX
 config PCI_MVEBU
        bool "Marvell EBU PCIe controller"
        depends on ARCH_MVEBU || ARCH_DOVE
+       depends on ARM
        depends on OF
 
 config PCIE_DW
index ed34c9520a02987503b02e2f371ea9e2a6d3a1a4..6153853ca9c31e319f4c6aae6dd92ed05215ba07 100644 (file)
 
 #define to_keystone_pcie(x)    container_of(x, struct keystone_pcie, pp)
 
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-       return sys->private_data;
-}
-
 static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
                                             u32 *bit_pos)
 {
@@ -108,7 +103,7 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
        struct pcie_port *pp;
 
        msi = irq_data_get_msi_desc(d);
-       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+       pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
        ks_pcie = to_keystone_pcie(pp);
        offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
        update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
@@ -146,7 +141,7 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
        u32 offset;
 
        msi = irq_data_get_msi_desc(d);
-       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+       pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
        ks_pcie = to_keystone_pcie(pp);
        offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
 
@@ -167,7 +162,7 @@ static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
        u32 offset;
 
        msi = irq_data_get_msi_desc(d);
-       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+       pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
        ks_pcie = to_keystone_pcie(pp);
        offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
 
index 3923bed93c7e06fa8327cafef9429c34d1b063cb..f39961bcf7aadb8b79d6635d3a7d9ecbce2f1cae 100644 (file)
@@ -77,6 +77,16 @@ static void ls_pcie_fix_class(struct ls_pcie *pcie)
        iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
 }
 
+/* Drop MSG TLP except for Vendor MSG */
+static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
+{
+       u32 val;
+
+       val = ioread32(pcie->dbi + PCIE_STRFMR1);
+       val &= 0xDFFFFFFF;
+       iowrite32(val, pcie->dbi + PCIE_STRFMR1);
+}
+
 static int ls1021_pcie_link_up(struct pcie_port *pp)
 {
        u32 state;
@@ -97,7 +107,7 @@ static int ls1021_pcie_link_up(struct pcie_port *pp)
 static void ls1021_pcie_host_init(struct pcie_port *pp)
 {
        struct ls_pcie *pcie = to_ls_pcie(pp);
-       u32 val, index[2];
+       u32 index[2];
 
        pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node,
                                                     "fsl,pcie-scfg");
@@ -116,13 +126,7 @@ static void ls1021_pcie_host_init(struct pcie_port *pp)
 
        dw_pcie_setup_rc(pp);
 
-       /*
-        * LS1021A Workaround for internal TKT228622
-        * to fix the INTx hang issue
-        */
-       val = ioread32(pcie->dbi + PCIE_STRFMR1);
-       val &= 0xffff;
-       iowrite32(val, pcie->dbi + PCIE_STRFMR1);
+       ls_pcie_drop_msg_tlp(pcie);
 }
 
 static int ls_pcie_link_up(struct pcie_port *pp)
@@ -147,6 +151,7 @@ static void ls_pcie_host_init(struct pcie_port *pp)
        iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
        ls_pcie_fix_class(pcie);
        ls_pcie_clear_multifunction(pcie);
+       ls_pcie_drop_msg_tlp(pcie);
        iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
 }
 
index 5816bceddb650c24576464913f9b7044d38be585..a576aeeb22da6cec1a01784328e209a66e96e8df 100644 (file)
@@ -64,7 +64,6 @@
 #define OARR_SIZE_CFG                BIT(OARR_SIZE_CFG_SHIFT)
 
 #define MAX_NUM_OB_WINDOWS           2
-#define MAX_NUM_PAXC_PF              4
 
 #define IPROC_PCIE_REG_INVALID 0xffff
 
@@ -170,20 +169,6 @@ static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie,
        writel(val, pcie->base + offset + (window * 8));
 }
 
-static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie,
-                                             unsigned int slot,
-                                             unsigned int fn)
-{
-       if (slot > 0)
-               return false;
-
-       /* PAXC can only support limited number of functions */
-       if (pcie->type == IPROC_PCIE_PAXC && fn >= MAX_NUM_PAXC_PF)
-               return false;
-
-       return true;
-}
-
 /**
  * Note access to the configuration registers are protected at the higher layer
  * by 'pci_lock' in drivers/pci/access.c
@@ -199,11 +184,11 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
        u32 val;
        u16 offset;
 
-       if (!iproc_pcie_device_is_valid(pcie, slot, fn))
-               return NULL;
-
        /* root complex access */
        if (busno == 0) {
+               if (slot > 0 || fn > 0)
+                       return NULL;
+
                iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR,
                                     where & CFG_IND_ADDR_MASK);
                offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA);
@@ -213,6 +198,14 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
                        return (pcie->base + offset);
        }
 
+       /*
+        * PAXC is connected to an internally emulated EP within the SoC.  It
+        * allows only one device.
+        */
+       if (pcie->type == IPROC_PCIE_PAXC)
+               if (slot > 0)
+                       return NULL;
+
        /* EP device access */
        val = (busno << CFG_ADDR_BUS_NUM_SHIFT) |
                (slot << CFG_ADDR_DEV_NUM_SHIFT) |
index 0bf82a20a0fb479ccfbdb43479bf9b0cf6ecff6a..48d21e0edd568cedc16b1626f78f0a95b22bca1c 100644 (file)
@@ -262,7 +262,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
        rpc->rpd = dev;
        INIT_WORK(&rpc->dpc_handler, aer_isr);
        mutex_init(&rpc->rpc_mutex);
-       init_waitqueue_head(&rpc->wait_release);
 
        /* Use PCIe bus function to store rpc into PCIe device */
        set_service_data(dev, rpc);
@@ -285,8 +284,7 @@ static void aer_remove(struct pcie_device *dev)
                if (rpc->isr)
                        free_irq(dev->irq, dev);
 
-               wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
-
+               flush_work(&rpc->dpc_handler);
                aer_disable_rootport(rpc);
                kfree(rpc);
                set_service_data(dev, NULL);
index 84420b7c9456ecbb0e43a9e8ca539af5b2ee1a20..945c939a86c5c2919335d85a95dbeee34f9c0bff 100644 (file)
@@ -72,7 +72,6 @@ struct aer_rpc {
                                         * recovery on the same
                                         * root port hierarchy
                                         */
-       wait_queue_head_t wait_release;
 };
 
 struct aer_broadcast_data {
index 712392504ed9b9f1a8992079f801cf2c271a0ae6..521e39c1b66d597f8881d9ab02a4e4b41c1b68a0 100644 (file)
@@ -811,8 +811,6 @@ void aer_isr(struct work_struct *work)
        while (get_e_source(rpc, &e_src))
                aer_isr_one_error(p_device, &e_src);
        mutex_unlock(&rpc->rpc_mutex);
-
-       wake_up(&rpc->wait_release);
 }
 
 /**
index c777b97207d5378936a8f25a54be603d76691ab9..5f70fee59a947da1daddbeb2253043dc79c794fb 100644 (file)
@@ -53,7 +53,7 @@ struct pcifront_device {
 };
 
 struct pcifront_sd {
-       int domain;
+       struct pci_sysdata sd;
        struct pcifront_device *pdev;
 };
 
@@ -67,7 +67,9 @@ static inline void pcifront_init_sd(struct pcifront_sd *sd,
                                    unsigned int domain, unsigned int bus,
                                    struct pcifront_device *pdev)
 {
-       sd->domain = domain;
+       /* Because we do not expose that information via XenBus. */
+       sd->sd.node = first_online_node;
+       sd->sd.domain = domain;
        sd->pdev = pdev;
 }
 
@@ -468,8 +470,8 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
        dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
                 domain, bus);
 
-       bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
-       sd = kmalloc(sizeof(*sd), GFP_KERNEL);
+       bus_entry = kzalloc(sizeof(*bus_entry), GFP_KERNEL);
+       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
        if (!bus_entry || !sd) {
                err = -ENOMEM;
                goto err_out;
index e7e117d5dbbe466f71d7a836ee3b898a560a1bed..0124d17bd9fe4bbff14eaced2db3a5f6d5e09b1b 100644 (file)
@@ -224,6 +224,7 @@ config PHY_MT65XX_USB3
 
 config PHY_HI6220_USB
        tristate "hi6220 USB PHY support"
+       depends on (ARCH_HISI && ARM64) || COMPILE_TEST
        select GENERIC_PHY
        select MFD_SYSCON
        help
index 8c7f27db6ad352260f8ad8675758ed365b6390a6..e7e574dc667a35d6d2c68ddf9e21744453d11bec 100644 (file)
@@ -275,20 +275,21 @@ EXPORT_SYMBOL_GPL(phy_exit);
 
 int phy_power_on(struct phy *phy)
 {
-       int ret;
+       int ret = 0;
 
        if (!phy)
-               return 0;
+               goto out;
 
        if (phy->pwr) {
                ret = regulator_enable(phy->pwr);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
-               return ret;
+               goto err_pm_sync;
+
        ret = 0; /* Override possible ret == -ENOTSUPP */
 
        mutex_lock(&phy->mutex);
@@ -296,19 +297,20 @@ int phy_power_on(struct phy *phy)
                ret = phy->ops->power_on(phy);
                if (ret < 0) {
                        dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
-                       goto out;
+                       goto err_pwr_on;
                }
        }
        ++phy->power_count;
        mutex_unlock(&phy->mutex);
        return 0;
 
-out:
+err_pwr_on:
        mutex_unlock(&phy->mutex);
        phy_pm_runtime_put_sync(phy);
+err_pm_sync:
        if (phy->pwr)
                regulator_disable(phy->pwr);
-
+out:
        return ret;
 }
 EXPORT_SYMBOL_GPL(phy_power_on);
index 4a3fc6e59f8e1982ecdd4b13b1500456959c0b71..840f3eae428b84292534d324ef856b485d001584 100644 (file)
@@ -715,6 +715,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
        pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        /* Our job is to use irqs and status from the power module
         * to keep the transceiver disabled when nothing's connected.
@@ -750,6 +751,7 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        struct twl4030_usb *twl = platform_get_drvdata(pdev);
        int val;
 
+       usb_remove_phy(&twl->phy);
        pm_runtime_get_sync(twl->dev);
        cancel_delayed_work(&twl->id_workaround_work);
        device_remove_file(twl->dev, &dev_attr_vbus);
@@ -757,6 +759,13 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        /* set transceiver mode to power on defaults */
        twl4030_usb_set_mode(twl, -1);
 
+       /* idle ulpi before powering off */
+       if (cable_present(twl->linkstat))
+               pm_runtime_put_noidle(twl->dev);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put_sync_suspend(twl->dev);
+       pm_runtime_disable(twl->dev);
+
        /* autogate 60MHz ULPI clock,
         * clear dpll clock request for i2c access,
         * disable 32KHz
@@ -771,11 +780,6 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        /* disable complete OTG block */
        twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
 
-       if (cable_present(twl->linkstat))
-               pm_runtime_put_noidle(twl->dev);
-       pm_runtime_mark_last_busy(twl->dev);
-       pm_runtime_put(twl->dev);
-
        return 0;
 }
 
index 16d48a4ed2253b7760e296deb95de9d76a6d85b4..e96e86d2e745e06e691344cca3fd38922450de58 100644 (file)
@@ -347,6 +347,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev,
                ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg);
                break;
        case PIN_CONFIG_INPUT_ENABLE:
+               mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true);
                ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
                break;
        case PIN_CONFIG_OUTPUT:
@@ -354,6 +355,7 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev,
                ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
                break;
        case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+               mtk_pmx_gpio_set_direction(pctldev, NULL, pin, true);
                ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
                break;
        case PIN_CONFIG_DRIVE_STRENGTH:
index e4d473811bb366c84cf5ab180529c36411aacd6d..3ef798fac81bdba4926273f74b8c2b62b80102b3 100644 (file)
@@ -666,16 +666,19 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
                struct mvebu_mpp_ctrl_setting *set = &mode->settings[0];
                struct mvebu_pinctrl_group *grp;
                unsigned num_settings;
+               unsigned supp_settings;
 
-               for (num_settings = 0; ; set++) {
+               for (num_settings = 0, supp_settings = 0; ; set++) {
                        if (!set->name)
                                break;
 
+                       num_settings++;
+
                        /* skip unsupported settings for this variant */
                        if (pctl->variant && !(pctl->variant & set->variant))
                                continue;
 
-                       num_settings++;
+                       supp_settings++;
 
                        /* find gpio/gpo/gpi settings */
                        if (strcmp(set->name, "gpio") == 0)
@@ -688,7 +691,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
                }
 
                /* skip modes with no settings for this variant */
-               if (!num_settings)
+               if (!supp_settings)
                        continue;
 
                grp = mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
index 085e60106ec2c2f94dd83bfbc2f21fbd8ba17da6..1f7469c9857d6ad14f80a4232aa836ce65d39620 100644 (file)
@@ -191,6 +191,7 @@ static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
                dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret);
 }
 
+#ifdef CONFIG_DEBUG_FS
 static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset,
                                  enum abx500_gpio_pull_updown *pull_updown)
 {
@@ -226,6 +227,7 @@ out:
 
        return ret;
 }
+#endif
 
 static int abx500_set_pull_updown(struct abx500_pinctrl *pct,
                                  int offset, enum abx500_gpio_pull_updown val)
@@ -468,6 +470,7 @@ out:
        return ret;
 }
 
+#ifdef CONFIG_DEBUG_FS
 static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                          unsigned gpio)
 {
@@ -553,8 +556,6 @@ out:
        return ret;
 }
 
-#ifdef CONFIG_DEBUG_FS
-
 #include <linux/seq_file.h>
 
 static void abx500_gpio_dbg_show_one(struct seq_file *s,
index d90e205cf809e5f3ec4c9d9ed9ca15bec8288d82..216f227c60092f580df47bc5e5f7c64828419d80 100644 (file)
@@ -426,6 +426,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev,
 
        return 0;
 }
+EXPORT_SYMBOL(pxa2xx_pinctrl_init);
 
 int pxa2xx_pinctrl_exit(struct platform_device *pdev)
 {
index f67b1e958589b9f9b4a891ce860bcfeb8909690d..5cc97f85db02d4986b3c9249a1116d952838fde0 100644 (file)
@@ -514,25 +514,35 @@ static const struct pinconf_ops samsung_pinconf_ops = {
        .pin_config_group_set   = samsung_pinconf_group_set,
 };
 
-/* gpiolib gpio_set callback function */
-static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+/*
+ * The samsung_gpio_set_vlaue() should be called with "bank->slock" held
+ * to avoid race condition.
+ */
+static void samsung_gpio_set_value(struct gpio_chip *gc,
+                                         unsigned offset, int value)
 {
        struct samsung_pin_bank *bank = gpiochip_get_data(gc);
        const struct samsung_pin_bank_type *type = bank->type;
-       unsigned long flags;
        void __iomem *reg;
        u32 data;
 
        reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-       spin_lock_irqsave(&bank->slock, flags);
-
        data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
        data &= ~(1 << offset);
        if (value)
                data |= 1 << offset;
        writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
+}
+
+/* gpiolib gpio_set callback function */
+static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+       struct samsung_pin_bank *bank = gpiochip_get_data(gc);
+       unsigned long flags;
 
+       spin_lock_irqsave(&bank->slock, flags);
+       samsung_gpio_set_value(gc, offset, value);
        spin_unlock_irqrestore(&bank->slock, flags);
 }
 
@@ -553,6 +563,8 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
 }
 
 /*
+ * The samsung_gpio_set_direction() should be called with "bank->slock" held
+ * to avoid race condition.
  * The calls to gpio_direction_output() and gpio_direction_input()
  * leads to this function call.
  */
@@ -564,7 +576,6 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc,
        struct samsung_pinctrl_drv_data *drvdata;
        void __iomem *reg;
        u32 data, mask, shift;
-       unsigned long flags;
 
        bank = gpiochip_get_data(gc);
        type = bank->type;
@@ -581,31 +592,42 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc,
                reg += 4;
        }
 
-       spin_lock_irqsave(&bank->slock, flags);
-
        data = readl(reg);
        data &= ~(mask << shift);
        if (!input)
                data |= FUNC_OUTPUT << shift;
        writel(data, reg);
 
-       spin_unlock_irqrestore(&bank->slock, flags);
-
        return 0;
 }
 
 /* gpiolib gpio_direction_input callback function. */
 static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
 {
-       return samsung_gpio_set_direction(gc, offset, true);
+       struct samsung_pin_bank *bank = gpiochip_get_data(gc);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&bank->slock, flags);
+       ret = samsung_gpio_set_direction(gc, offset, true);
+       spin_unlock_irqrestore(&bank->slock, flags);
+       return ret;
 }
 
 /* gpiolib gpio_direction_output callback function. */
 static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
                                                        int value)
 {
-       samsung_gpio_set(gc, offset, value);
-       return samsung_gpio_set_direction(gc, offset, false);
+       struct samsung_pin_bank *bank = gpiochip_get_data(gc);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&bank->slock, flags);
+       samsung_gpio_set_value(gc, offset, value);
+       ret = samsung_gpio_set_direction(gc, offset, false);
+       spin_unlock_irqrestore(&bank->slock, flags);
+
+       return ret;
 }
 
 /*
index 77d4cf047ceea71dd9bcc50bf0d4e59527d7aac8..11760bbe9d51acd4ebb4d44b82af2c525f68e1dd 100644 (file)
@@ -492,6 +492,7 @@ static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = {
        .pins = sun8i_h3_pins,
        .npins = ARRAY_SIZE(sun8i_h3_pins),
        .irq_banks = 2,
+       .irq_read_needs_mux = true
 };
 
 static int sun8i_h3_pinctrl_probe(struct platform_device *pdev)
index 20f0ad9bb9f373efedfdf42de3af7da5321f21a6..e20f23e04c24ce8071ea03ea238b5a1a765d70ff 100644 (file)
@@ -41,8 +41,7 @@ static const struct key_entry intel_hid_keymap[] = {
        { KE_KEY, 4, { KEY_HOME } },
        { KE_KEY, 5, { KEY_END } },
        { KE_KEY, 6, { KEY_PAGEUP } },
-       { KE_KEY, 4, { KEY_PAGEDOWN } },
-       { KE_KEY, 4, { KEY_HOME } },
+       { KE_KEY, 7, { KEY_PAGEDOWN } },
        { KE_KEY, 8, { KEY_RFKILL } },
        { KE_KEY, 9, { KEY_POWER } },
        { KE_KEY, 11, { KEY_SLEEP } },
index 02bc5a6343c3fbeeb34b00ef282ba5f31ceff96a..aa454241489c9f541864f34828e19318514d3560 100644 (file)
@@ -49,7 +49,7 @@ struct scu_ipc_data {
 
 static int scu_reg_access(u32 cmd, struct scu_ipc_data  *data)
 {
-       int count = data->count;
+       unsigned int count = data->count;
 
        if (count == 0 || count == 3 || count > 4)
                return -EINVAL;
index 9429e66be09641fd818f8da593d47c45124d3efe..8eafc6f0df88be5fbf26c6725beb656e49464c0b 100644 (file)
@@ -21,6 +21,9 @@
 
 #include <linux/power/bq27xxx_battery.h>
 
+static DEFINE_IDR(battery_id);
+static DEFINE_MUTEX(battery_mutex);
+
 static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
 {
        struct bq27xxx_device_info *di = data;
@@ -70,19 +73,33 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
 {
        struct bq27xxx_device_info *di;
        int ret;
+       char *name;
+       int num;
+
+       /* Get new ID for the new battery device */
+       mutex_lock(&battery_mutex);
+       num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
+       mutex_unlock(&battery_mutex);
+       if (num < 0)
+               return num;
+
+       name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
+       if (!name)
+               goto err_mem;
 
        di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
        if (!di)
-               return -ENOMEM;
+               goto err_mem;
 
+       di->id = num;
        di->dev = &client->dev;
        di->chip = id->driver_data;
-       di->name = id->name;
+       di->name = name;
        di->bus.read = bq27xxx_battery_i2c_read;
 
        ret = bq27xxx_battery_setup(di);
        if (ret)
-               return ret;
+               goto err_failed;
 
        /* Schedule a polling after about 1 min */
        schedule_delayed_work(&di->work, 60 * HZ);
@@ -103,6 +120,16 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
        }
 
        return 0;
+
+err_mem:
+       ret = -ENOMEM;
+
+err_failed:
+       mutex_lock(&battery_mutex);
+       idr_remove(&battery_id, num);
+       mutex_unlock(&battery_mutex);
+
+       return ret;
 }
 
 static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
@@ -111,6 +138,10 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
 
        bq27xxx_battery_teardown(di);
 
+       mutex_lock(&battery_mutex);
+       idr_remove(&battery_id, di->id);
+       mutex_unlock(&battery_mutex);
+
        return 0;
 }
 
index 41605dac83094813441530ae9cacad093a352f71..c78db05e75b1323f9b0adb35aac8cc78316355ab 100644 (file)
@@ -3035,6 +3035,7 @@ static void dasd_setup_queue(struct dasd_block *block)
                max = block->base->discipline->max_blocks << block->s2b_shift;
        }
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue);
+       block->request_queue->limits.max_dev_sectors = max;
        blk_queue_logical_block_size(block->request_queue,
                                     block->bp_block);
        blk_queue_max_hw_sectors(block->request_queue, max);
index 184b1dbeb55463b768eb9aa7215665686d5e4591..286782c60da4e3b197d7d9901b7e17c2e69673ac 100644 (file)
@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
                spin_unlock_irqrestore(&lcu->lock, flags);
                cancel_work_sync(&lcu->suc_data.worker);
                spin_lock_irqsave(&lcu->lock, flags);
-               if (device == lcu->suc_data.device)
+               if (device == lcu->suc_data.device) {
+                       dasd_put_device(device);
                        lcu->suc_data.device = NULL;
+               }
        }
        was_pending = 0;
        if (device == lcu->ruac_data.device) {
@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
                was_pending = 1;
                cancel_delayed_work_sync(&lcu->ruac_data.dwork);
                spin_lock_irqsave(&lcu->lock, flags);
-               if (device == lcu->ruac_data.device)
+               if (device == lcu->ruac_data.device) {
+                       dasd_put_device(device);
                        lcu->ruac_data.device = NULL;
+               }
        }
        private->lcu = NULL;
        spin_unlock_irqrestore(&lcu->lock, flags);
@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work)
        if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
                DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
                            " alias data in lcu (rc = %d), retry later", rc);
-               schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
+               if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ))
+                       dasd_put_device(device);
        } else {
+               dasd_put_device(device);
                lcu->ruac_data.device = NULL;
                lcu->flags &= ~UPDATE_PENDING;
        }
@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu,
         */
        if (!usedev)
                return -EINVAL;
+       dasd_get_device(usedev);
        lcu->ruac_data.device = usedev;
-       schedule_delayed_work(&lcu->ruac_data.dwork, 0);
+       if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0))
+               dasd_put_device(usedev);
        return 0;
 }
 
@@ -723,7 +731,7 @@ static int reset_summary_unit_check(struct alias_lcu *lcu,
        ASCEBC((char *) &cqr->magic, 4);
        ccw = cqr->cpaddr;
        ccw->cmd_code = DASD_ECKD_CCW_RSCK;
-       ccw->flags = ;
+       ccw->flags = CCW_FLAG_SLI;
        ccw->count = 16;
        ccw->cda = (__u32)(addr_t) cqr->data;
        ((char *)cqr->data)[0] = reason;
@@ -930,6 +938,7 @@ static void summary_unit_check_handling_work(struct work_struct *work)
        /* 3. read new alias configuration */
        _schedule_lcu_update(lcu, device);
        lcu->suc_data.device = NULL;
+       dasd_put_device(device);
        spin_unlock_irqrestore(&lcu->lock, flags);
 }
 
@@ -989,6 +998,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
        }
        lcu->suc_data.reason = reason;
        lcu->suc_data.device = device;
+       dasd_get_device(device);
        spin_unlock(&lcu->lock);
-       schedule_work(&lcu->suc_data.worker);
+       if (!schedule_work(&lcu->suc_data.worker))
+               dasd_put_device(device);
 };
index 3613581343159dc67e8980424b2346d301dec01f..93880ed6291cfbda8a88ad6130a433c0c461c727 100644 (file)
@@ -562,7 +562,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
                        /*
                         * Command Lock contention
                         */
-                       err = SCSI_DH_RETRY;
+                       err = SCSI_DH_IMM_RETRY;
                break;
        default:
                break;
@@ -612,6 +612,8 @@ retry:
                err = mode_select_handle_sense(sdev, h->sense);
                if (err == SCSI_DH_RETRY && retry_cnt--)
                        goto retry;
+               if (err == SCSI_DH_IMM_RETRY)
+                       goto retry;
        }
        if (err == SCSI_DH_OK) {
                h->state = RDAC_STATE_ACTIVE;
index b67661836c9fa26fccd1e23a82508c1d567a5916..d1dd1616f983bb7a567d4eb465e09a5c9cd611c5 100644 (file)
@@ -1,6 +1,6 @@
 config SCSI_HISI_SAS
        tristate "HiSilicon SAS"
-       depends on HAS_DMA
+       depends on HAS_DMA && HAS_IOMEM
        depends on ARM64 || COMPILE_TEST
        select SCSI_SAS_LIBSAS
        select BLK_DEV_INTEGRITY
index 057fdeb720acec997f4a4a5952318c58ab2f0b3e..eea24d7531cf51eec585afbe0575a0dc6d804279 100644 (file)
@@ -1289,13 +1289,10 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
                goto out;
        }
 
-       if (cmplt_hdr_data & CMPLT_HDR_ERR_RCRD_XFRD_MSK) {
-               if (!(cmplt_hdr_data & CMPLT_HDR_CMD_CMPLT_MSK) ||
-                   !(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK))
-                       ts->stat = SAS_DATA_OVERRUN;
-               else
-                       slot_err_v1_hw(hisi_hba, task, slot);
+       if (cmplt_hdr_data & CMPLT_HDR_ERR_RCRD_XFRD_MSK &&
+               !(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK)) {
 
+               slot_err_v1_hw(hisi_hba, task, slot);
                goto out;
        }
 
index 3b3e0998fa6e72b71f5417c4f942ff9bb67caee0..d6a691e27d33317c72d785340b5b371378932741 100644 (file)
@@ -4002,6 +4002,7 @@ static ssize_t ipr_store_update_fw(struct device *dev,
        struct ipr_sglist *sglist;
        char fname[100];
        char *src;
+       char *endline;
        int result, dnld_size;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -4009,6 +4010,10 @@ static ssize_t ipr_store_update_fw(struct device *dev,
 
        snprintf(fname, sizeof(fname), "%s", buf);
 
+       endline = strchr(fname, '\n');
+       if (endline)
+               *endline = '\0';
+
        if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) {
                dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname);
                return -EIO;
index 52a87657c7dd3e4945aad29e9b3cbf983b94efad..692a7570b5e1475da8371f1d08939b8898912ebe 100644 (file)
@@ -2204,7 +2204,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
        /* Clear outstanding commands array. */
        for (que = 0; que < ha->max_req_queues; que++) {
                req = ha->req_q_map[que];
-               if (!req)
+               if (!req || !test_bit(que, ha->req_qid_map))
                        continue;
                req->out_ptr = (void *)(req->ring + req->length);
                *req->out_ptr = 0;
@@ -2221,7 +2221,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
 
        for (que = 0; que < ha->max_rsp_queues; que++) {
                rsp = ha->rsp_q_map[que];
-               if (!rsp)
+               if (!rsp || !test_bit(que, ha->rsp_qid_map))
                        continue;
                rsp->in_ptr = (void *)(rsp->ring + rsp->length);
                *rsp->in_ptr = 0;
@@ -4981,7 +4981,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
 
        for (i = 1; i < ha->max_rsp_queues; i++) {
                rsp = ha->rsp_q_map[i];
-               if (rsp) {
+               if (rsp && test_bit(i, ha->rsp_qid_map)) {
                        rsp->options &= ~BIT_0;
                        ret = qla25xx_init_rsp_que(base_vha, rsp);
                        if (ret != QLA_SUCCESS)
@@ -4996,8 +4996,8 @@ qla25xx_init_queues(struct qla_hw_data *ha)
        }
        for (i = 1; i < ha->max_req_queues; i++) {
                req = ha->req_q_map[i];
-               if (req) {
-               /* Clear outstanding commands array. */
+               if (req && test_bit(i, ha->req_qid_map)) {
+                       /* Clear outstanding commands array. */
                        req->options &= ~BIT_0;
                        ret = qla25xx_init_req_que(base_vha, req);
                        if (ret != QLA_SUCCESS)
index d4d65eb0e9b41264eb2d86e4d4af4997e0268c5c..4af95479a9db9325d8bb42fff0dc0d0f5ec6b682 100644 (file)
@@ -3063,9 +3063,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                    "MSI-X: Failed to enable support "
                    "-- %d/%d\n Retry with %d vectors.\n",
                    ha->msix_count, ret, ret);
+               ha->msix_count = ret;
+               ha->max_rsp_queues = ha->msix_count - 1;
        }
-       ha->msix_count = ret;
-       ha->max_rsp_queues = ha->msix_count - 1;
        ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
                                ha->msix_count, GFP_KERNEL);
        if (!ha->msix_entries) {
index c5dd594f6c316185b203f3e25c1595b4c320da81..cf7ba52bae665fa482b8535f92e5fcb1dbe25244 100644 (file)
@@ -600,7 +600,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
        /* Delete request queues */
        for (cnt = 1; cnt < ha->max_req_queues; cnt++) {
                req = ha->req_q_map[cnt];
-               if (req) {
+               if (req && test_bit(cnt, ha->req_qid_map)) {
                        ret = qla25xx_delete_req_que(vha, req);
                        if (ret != QLA_SUCCESS) {
                                ql_log(ql_log_warn, vha, 0x00ea,
@@ -614,7 +614,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
        /* Delete response queues */
        for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) {
                rsp = ha->rsp_q_map[cnt];
-               if (rsp) {
+               if (rsp && test_bit(cnt, ha->rsp_qid_map)) {
                        ret = qla25xx_delete_rsp_que(vha, rsp);
                        if (ret != QLA_SUCCESS) {
                                ql_log(ql_log_warn, vha, 0x00eb,
index f1788db4319560c8210eda5a0fc4f576d5ec321f..f6c7ce35b542ecadfe0305095e300bfabe95950c 100644 (file)
@@ -409,6 +409,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
        int cnt;
 
        for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
+               if (!test_bit(cnt, ha->req_qid_map))
+                       continue;
+
                req = ha->req_q_map[cnt];
                qla2x00_free_req_que(ha, req);
        }
@@ -416,6 +419,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
        ha->req_q_map = NULL;
 
        for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
+               if (!test_bit(cnt, ha->rsp_qid_map))
+                       continue;
+
                rsp = ha->rsp_q_map[cnt];
                qla2x00_free_rsp_que(ha, rsp);
        }
index 8075a4cdb45cf85aaa09c1e26fef1bdd8dc82b55..ee967becd257e1b5a5724aed241a9537fc0f3bc3 100644 (file)
@@ -105,7 +105,7 @@ static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt);
 static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
        int fn, void *iocb, int flags);
 static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd
-       *cmd, struct atio_from_isp *atio, int ha_locked);
+       *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort);
 static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha,
        struct qla_tgt_srr_imm *imm, int ha_lock);
 static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
@@ -1756,7 +1756,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
                qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy,
                    0, 0, 0, 0, 0, 0);
        else {
-               if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK)
+               if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX)
                        qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts,
                            mcmd->fc_tm_rsp, false);
                else
@@ -2665,7 +2665,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
                        /* no need to terminate. FW already freed exchange. */
                        qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
                else
-                       qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
+                       qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
                return 0;
        }
@@ -3173,7 +3173,8 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
 }
 
 static void qlt_send_term_exchange(struct scsi_qla_host *vha,
-       struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked)
+       struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked,
+       int ul_abort)
 {
        unsigned long flags = 0;
        int rc;
@@ -3193,8 +3194,7 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha,
                qlt_alloc_qfull_cmd(vha, atio, 0, 0);
 
 done:
-       if (cmd && (!cmd->aborted ||
-           !cmd->cmd_sent_to_fw)) {
+       if (cmd && !ul_abort && !cmd->aborted) {
                if (cmd->sg_mapped)
                        qlt_unmap_sg(vha, cmd);
                vha->hw->tgt.tgt_ops->free_cmd(cmd);
@@ -3253,21 +3253,38 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha)
 
 }
 
-void qlt_abort_cmd(struct qla_tgt_cmd *cmd)
+int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
 {
        struct qla_tgt *tgt = cmd->tgt;
        struct scsi_qla_host *vha = tgt->vha;
        struct se_cmd *se_cmd = &cmd->se_cmd;
+       unsigned long flags;
 
        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
            "qla_target(%d): terminating exchange for aborted cmd=%p "
            "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
            se_cmd->tag);
 
+       spin_lock_irqsave(&cmd->cmd_lock, flags);
+       if (cmd->aborted) {
+               spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+               /*
+                * It's normal to see 2 calls in this path:
+                *  1) XFER Rdy completion + CMD_T_ABORT
+                *  2) TCM TMR - drain_state_list
+                */
+               ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
+                       "multiple abort. %p transport_state %x, t_state %x,"
+                       " se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state,
+                       cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags);
+               return EIO;
+       }
        cmd->aborted = 1;
        cmd->cmd_flags |= BIT_6;
+       spin_unlock_irqrestore(&cmd->cmd_lock, flags);
 
-       qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
+       qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1);
+       return 0;
 }
 EXPORT_SYMBOL(qlt_abort_cmd);
 
@@ -3282,6 +3299,9 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd)
 
        BUG_ON(cmd->cmd_in_wq);
 
+       if (cmd->sg_mapped)
+               qlt_unmap_sg(cmd->vha, cmd);
+
        if (!cmd->q_full)
                qlt_decr_num_pend_cmds(cmd->vha);
 
@@ -3399,7 +3419,7 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
                term = 1;
 
        if (term)
-               qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
+               qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
 
        return term;
 }
@@ -3580,12 +3600,13 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
                case CTIO_PORT_LOGGED_OUT:
                case CTIO_PORT_UNAVAILABLE:
                {
-                       int logged_out = (status & 0xFFFF);
+                       int logged_out =
+                               (status & 0xFFFF) == CTIO_PORT_LOGGED_OUT;
+
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059,
                            "qla_target(%d): CTIO with %s status %x "
                            "received (state %x, se_cmd %p)\n", vha->vp_idx,
-                           (logged_out == CTIO_PORT_LOGGED_OUT) ?
-                           "PORT LOGGED OUT" : "PORT UNAVAILABLE",
+                           logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE",
                            status, cmd->state, se_cmd);
 
                        if (logged_out && cmd->sess) {
@@ -3754,6 +3775,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
                goto out_term;
        }
 
+       spin_lock_init(&cmd->cmd_lock);
        cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
        cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
        cmd->unpacked_lun = scsilun_to_int(
@@ -3796,7 +3818,7 @@ out_term:
         */
        cmd->cmd_flags |= BIT_2;
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       qlt_send_term_exchange(vha, NULL, &cmd->atio, 1);
+       qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0);
 
        qlt_decr_num_pend_cmds(vha);
        percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
@@ -3918,7 +3940,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
 
 out_term:
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       qlt_send_term_exchange(vha, NULL, &op->atio, 1);
+       qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
        kfree(op);
 
@@ -3982,7 +4004,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 
        cmd->cmd_in_wq = 1;
        cmd->cmd_flags |= BIT_0;
-       cmd->se_cmd.cpuid = -1;
+       cmd->se_cmd.cpuid = ha->msix_count ?
+               ha->tgt.rspq_vector_cpuid : WORK_CPU_UNBOUND;
 
        spin_lock(&vha->cmd_list_lock);
        list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
@@ -3990,7 +4013,6 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 
        INIT_WORK(&cmd->work, qlt_do_work);
        if (ha->msix_count) {
-               cmd->se_cmd.cpuid = ha->tgt.rspq_vector_cpuid;
                if (cmd->atio.u.isp24.fcp_cmnd.rddata)
                        queue_work_on(smp_processor_id(), qla_tgt_wq,
                            &cmd->work);
@@ -4771,7 +4793,7 @@ out_reject:
                dump_stack();
        } else {
                cmd->cmd_flags |= BIT_9;
-               qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
+               qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
        }
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
@@ -4950,7 +4972,7 @@ static void qlt_prepare_srr_imm(struct scsi_qla_host *vha,
                                    sctio, sctio->srr_id);
                                list_del(&sctio->srr_list_entry);
                                qlt_send_term_exchange(vha, sctio->cmd,
-                                   &sctio->cmd->atio, 1);
+                                   &sctio->cmd->atio, 1, 0);
                                kfree(sctio);
                        }
                }
@@ -5123,7 +5145,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
            atio->u.isp24.fcp_hdr.s_id);
        spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
        if (!sess) {
-               qlt_send_term_exchange(vha, NULL, atio, 1);
+               qlt_send_term_exchange(vha, NULL, atio, 1, 0);
                return 0;
        }
        /* Sending marker isn't necessary, since we called from ISR */
@@ -5406,7 +5428,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
 #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
                                qlt_send_busy(vha, atio, SAM_STAT_BUSY);
 #else
-                               qlt_send_term_exchange(vha, NULL, atio, 1);
+                               qlt_send_term_exchange(vha, NULL, atio, 1, 0);
 #endif
 
                                if (!ha_locked)
@@ -5523,7 +5545,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
 #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
                                qlt_send_busy(vha, atio, 0);
 #else
-                               qlt_send_term_exchange(vha, NULL, atio, 1);
+                               qlt_send_term_exchange(vha, NULL, atio, 1, 0);
 #endif
                        } else {
                                if (tgt->tgt_stop) {
@@ -5532,7 +5554,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
                                            "command to target, sending TERM "
                                            "EXCHANGE for rsp\n");
                                        qlt_send_term_exchange(vha, NULL,
-                                           atio, 1);
+                                           atio, 1, 0);
                                } else {
                                        ql_dbg(ql_dbg_tgt, vha, 0xe060,
                                            "qla_target(%d): Unable to send "
@@ -5960,7 +5982,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
        return;
 
 out_term:
-       qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0);
+       qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
        if (sess)
                ha->tgt.tgt_ops->put_sess(sess);
        spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
index 71b2865ba3c8416d6ce583df64125dfb7071ca2b..22a6a767fe07b1eba54e23007606bb3c39226b0f 100644 (file)
@@ -943,6 +943,36 @@ struct qla_tgt_sess {
        qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX];
 };
 
+typedef enum {
+       /*
+        * BIT_0 - Atio Arrival / schedule to work
+        * BIT_1 - qlt_do_work
+        * BIT_2 - qlt_do work failed
+        * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending
+        * BIT_4 - read respond/tcm_qla2xx_queue_data_in
+        * BIT_5 - status respond / tcm_qla2xx_queue_status
+        * BIT_6 - tcm request to abort/Term exchange.
+        *      pre_xmit_response->qlt_send_term_exchange
+        * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response)
+        * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer)
+        * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange)
+        * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data
+
+        * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd
+        * BIT_13 - Bad completion -
+        *      qlt_ctio_do_completion --> qlt_term_ctio_exchange
+        * BIT_14 - Back end data received/sent.
+        * BIT_15 - SRR prepare ctio
+        * BIT_16 - complete free
+        * BIT_17 - flush - qlt_abort_cmd_on_host_reset
+        * BIT_18 - completion w/abort status
+        * BIT_19 - completion w/unknown status
+        * BIT_20 - tcm_qla2xxx_free_cmd
+        */
+       CMD_FLAG_DATA_WORK = BIT_11,
+       CMD_FLAG_DATA_WORK_FREE = BIT_21,
+} cmd_flags_t;
+
 struct qla_tgt_cmd {
        struct se_cmd se_cmd;
        struct qla_tgt_sess *sess;
@@ -952,6 +982,7 @@ struct qla_tgt_cmd {
        /* Sense buffer that will be mapped into outgoing status */
        unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
 
+       spinlock_t cmd_lock;
        /* to save extra sess dereferences */
        unsigned int conf_compl_supported:1;
        unsigned int sg_mapped:1;
@@ -986,30 +1017,8 @@ struct qla_tgt_cmd {
 
        uint64_t jiffies_at_alloc;
        uint64_t jiffies_at_free;
-       /* BIT_0 - Atio Arrival / schedule to work
-        * BIT_1 - qlt_do_work
-        * BIT_2 - qlt_do work failed
-        * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending
-        * BIT_4 - read respond/tcm_qla2xx_queue_data_in
-        * BIT_5 - status respond / tcm_qla2xx_queue_status
-        * BIT_6 - tcm request to abort/Term exchange.
-        *      pre_xmit_response->qlt_send_term_exchange
-        * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response)
-        * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer)
-        * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange)
-        * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data
-        * BIT_11 - Data actually going to TCM : tcm_qla2xx_handle_data_work
-        * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd
-        * BIT_13 - Bad completion -
-        *      qlt_ctio_do_completion --> qlt_term_ctio_exchange
-        * BIT_14 - Back end data received/sent.
-        * BIT_15 - SRR prepare ctio
-        * BIT_16 - complete free
-        * BIT_17 - flush - qlt_abort_cmd_on_host_reset
-        * BIT_18 - completion w/abort status
-        * BIT_19 - completion w/unknown status
-        */
-       uint32_t cmd_flags;
+
+       cmd_flags_t cmd_flags;
 };
 
 struct qla_tgt_sess_work_param {
@@ -1148,7 +1157,7 @@ static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p)
 extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
 extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
 extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
-extern void qlt_abort_cmd(struct qla_tgt_cmd *);
+extern int qlt_abort_cmd(struct qla_tgt_cmd *);
 extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
 extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
 extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
index ddbe2e7ac14d095129cc9cbd90ab87cbd414bc36..c3e62252460452aac6507db5ddc7ad576f969ffa 100644 (file)
@@ -395,6 +395,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
        if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) {
                for (i = 0; i < vha->hw->max_req_queues; i++) {
                        struct req_que *req = vha->hw->req_q_map[i];
+
+                       if (!test_bit(i, vha->hw->req_qid_map))
+                               continue;
+
                        if (req || !buf) {
                                length = req ?
                                    req->length : REQUEST_ENTRY_CNT_24XX;
@@ -408,6 +412,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
        } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) {
                for (i = 0; i < vha->hw->max_rsp_queues; i++) {
                        struct rsp_que *rsp = vha->hw->rsp_q_map[i];
+
+                       if (!test_bit(i, vha->hw->rsp_qid_map))
+                               continue;
+
                        if (rsp || !buf) {
                                length = rsp ?
                                    rsp->length : RESPONSE_ENTRY_CNT_MQ;
@@ -634,6 +642,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
        if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) {
                for (i = 0; i < vha->hw->max_req_queues; i++) {
                        struct req_que *req = vha->hw->req_q_map[i];
+
+                       if (!test_bit(i, vha->hw->req_qid_map))
+                               continue;
+
                        if (req || !buf) {
                                qla27xx_insert16(i, buf, len);
                                qla27xx_insert16(1, buf, len);
@@ -645,6 +657,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
        } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) {
                for (i = 0; i < vha->hw->max_rsp_queues; i++) {
                        struct rsp_que *rsp = vha->hw->rsp_q_map[i];
+
+                       if (!test_bit(i, vha->hw->rsp_qid_map))
+                               continue;
+
                        if (rsp || !buf) {
                                qla27xx_insert16(i, buf, len);
                                qla27xx_insert16(1, buf, len);
index faf0a126627f65d6cbe275c1ea4b34062a579a7a..1808a01cfb7e79fe9aa34d341bfcd8fc3603c898 100644 (file)
@@ -298,6 +298,10 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
 {
        cmd->vha->tgt_counters.core_qla_free_cmd++;
        cmd->cmd_in_wq = 1;
+
+       BUG_ON(cmd->cmd_flags & BIT_20);
+       cmd->cmd_flags |= BIT_20;
+
        INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free);
        queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
 }
@@ -374,6 +378,20 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
 {
        struct qla_tgt_cmd *cmd = container_of(se_cmd,
                                struct qla_tgt_cmd, se_cmd);
+
+       if (cmd->aborted) {
+               /* Cmd can loop during Q-full.  tcm_qla2xxx_aborted_task
+                * can get ahead of this cmd. tcm_qla2xxx_aborted_task
+                * already kick start the free.
+                */
+               pr_debug("write_pending aborted cmd[%p] refcount %d "
+                       "transport_state %x, t_state %x, se_cmd_flags %x\n",
+                       cmd,cmd->se_cmd.cmd_kref.refcount.counter,
+                       cmd->se_cmd.transport_state,
+                       cmd->se_cmd.t_state,
+                       cmd->se_cmd.se_cmd_flags);
+               return 0;
+       }
        cmd->cmd_flags |= BIT_3;
        cmd->bufflen = se_cmd->data_length;
        cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
@@ -405,7 +423,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd)
            se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) {
                spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
                wait_for_completion_timeout(&se_cmd->t_transport_stop_comp,
-                                           3 * HZ);
+                                               50);
                return 0;
        }
        spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
@@ -444,6 +462,9 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
        if (bidi)
                flags |= TARGET_SCF_BIDI_OP;
 
+       if (se_cmd->cpuid != WORK_CPU_UNBOUND)
+               flags |= TARGET_SCF_USE_CPUID;
+
        sess = cmd->sess;
        if (!sess) {
                pr_err("Unable to locate struct qla_tgt_sess from qla_tgt_cmd\n");
@@ -465,13 +486,25 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
 static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
 {
        struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
+       unsigned long flags;
 
        /*
         * Ensure that the complete FCP WRITE payload has been received.
         * Otherwise return an exception via CHECK_CONDITION status.
         */
        cmd->cmd_in_wq = 0;
-       cmd->cmd_flags |= BIT_11;
+
+       spin_lock_irqsave(&cmd->cmd_lock, flags);
+       cmd->cmd_flags |= CMD_FLAG_DATA_WORK;
+       if (cmd->aborted) {
+               cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE;
+               spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+
+               tcm_qla2xxx_free_cmd(cmd);
+               return;
+       }
+       spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+
        cmd->vha->tgt_counters.qla_core_ret_ctio++;
        if (!cmd->write_data_transferred) {
                /*
@@ -546,6 +579,20 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
        struct qla_tgt_cmd *cmd = container_of(se_cmd,
                                struct qla_tgt_cmd, se_cmd);
 
+       if (cmd->aborted) {
+               /* Cmd can loop during Q-full.  tcm_qla2xxx_aborted_task
+                * can get ahead of this cmd. tcm_qla2xxx_aborted_task
+                * already kick start the free.
+                */
+               pr_debug("queue_data_in aborted cmd[%p] refcount %d "
+                       "transport_state %x, t_state %x, se_cmd_flags %x\n",
+                       cmd,cmd->se_cmd.cmd_kref.refcount.counter,
+                       cmd->se_cmd.transport_state,
+                       cmd->se_cmd.t_state,
+                       cmd->se_cmd.se_cmd_flags);
+               return 0;
+       }
+
        cmd->cmd_flags |= BIT_4;
        cmd->bufflen = se_cmd->data_length;
        cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
@@ -637,11 +684,34 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
        qlt_xmit_tm_rsp(mcmd);
 }
 
+
+#define DATA_WORK_NOT_FREE(_flags) \
+       (( _flags & (CMD_FLAG_DATA_WORK|CMD_FLAG_DATA_WORK_FREE)) == \
+        CMD_FLAG_DATA_WORK)
 static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
 {
        struct qla_tgt_cmd *cmd = container_of(se_cmd,
                                struct qla_tgt_cmd, se_cmd);
-       qlt_abort_cmd(cmd);
+       unsigned long flags;
+
+       if (qlt_abort_cmd(cmd))
+               return;
+
+       spin_lock_irqsave(&cmd->cmd_lock, flags);
+       if ((cmd->state == QLA_TGT_STATE_NEW)||
+               ((cmd->state == QLA_TGT_STATE_DATA_IN) &&
+                DATA_WORK_NOT_FREE(cmd->cmd_flags)) ) {
+
+               cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE;
+               spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+               /* Cmd have not reached firmware.
+                * Use this trigger to free it. */
+               tcm_qla2xxx_free_cmd(cmd);
+               return;
+       }
+       spin_unlock_irqrestore(&cmd->cmd_lock, flags);
+       return;
+
 }
 
 static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
index 47b9d13f97b880033c20144968cf715c8af41623..bbfbfd9e5aa391ff65d5e31859f31765bb5b77c3 100644 (file)
@@ -205,6 +205,8 @@ static struct {
        {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC},
        {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
        {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
+       {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
+       {"Marvell", "91xx Config", "1.01", BLIST_SKIP_VPD_PAGES},
        {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
        {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
        {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
index fa6b2c4eb7a2b1dc620bcf22db3abf1001a7f3d3..8c6e31874171b47459232d74f882328cdb967efb 100644 (file)
@@ -1344,6 +1344,7 @@ scsi_prep_return(struct request_queue *q, struct request *req, int ret)
 
        switch (ret) {
        case BLKPREP_KILL:
+       case BLKPREP_INVALID:
                req->errors = DID_NO_CONNECT << 16;
                /* release the command and kill it */
                if (req->special) {
index 4f18a851e2c7f7de25e590e9a6f93750150e5f37..00bc7218a7f80f06a139a7743b5a2c51331f68f0 100644 (file)
@@ -1272,16 +1272,18 @@ static void __scsi_remove_target(struct scsi_target *starget)
 void scsi_remove_target(struct device *dev)
 {
        struct Scsi_Host *shost = dev_to_shost(dev->parent);
-       struct scsi_target *starget;
+       struct scsi_target *starget, *last_target = NULL;
        unsigned long flags;
 
 restart:
        spin_lock_irqsave(shost->host_lock, flags);
        list_for_each_entry(starget, &shost->__targets, siblings) {
-               if (starget->state == STARGET_DEL)
+               if (starget->state == STARGET_DEL ||
+                   starget == last_target)
                        continue;
                if (starget->dev.parent == dev || &starget->dev == dev) {
                        kref_get(&starget->reap_ref);
+                       last_target = starget;
                        spin_unlock_irqrestore(shost->host_lock, flags);
                        __scsi_remove_target(starget);
                        scsi_target_reap(starget);
index bb669d32ccd0daee203a69840313fcb9cf343ee0..d749da765df141d7aa66ef2a31e591f6cbc94fed 100644 (file)
@@ -761,7 +761,7 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd)
                break;
 
        default:
-               ret = BLKPREP_KILL;
+               ret = BLKPREP_INVALID;
                goto out;
        }
 
@@ -839,7 +839,7 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
        int ret;
 
        if (sdkp->device->no_write_same)
-               return BLKPREP_KILL;
+               return BLKPREP_INVALID;
 
        BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
 
index 55627d097873a85780a878e32b32c20e6c4a9524..292c04eec9ad4b56518afc243d92b37602a3f456 100644 (file)
@@ -42,6 +42,7 @@
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_transport_fc.h>
+#include <scsi/scsi_transport.h>
 
 /*
  * All wire protocol details (storage protocol between the guest and the host)
@@ -477,19 +478,18 @@ struct hv_host_device {
 struct storvsc_scan_work {
        struct work_struct work;
        struct Scsi_Host *host;
-       uint lun;
+       u8 lun;
+       u8 tgt_id;
 };
 
 static void storvsc_device_scan(struct work_struct *work)
 {
        struct storvsc_scan_work *wrk;
-       uint lun;
        struct scsi_device *sdev;
 
        wrk = container_of(work, struct storvsc_scan_work, work);
-       lun = wrk->lun;
 
-       sdev = scsi_device_lookup(wrk->host, 0, 0, lun);
+       sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun);
        if (!sdev)
                goto done;
        scsi_rescan_device(&sdev->sdev_gendev);
@@ -540,7 +540,7 @@ static void storvsc_remove_lun(struct work_struct *work)
        if (!scsi_host_get(wrk->host))
                goto done;
 
-       sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun);
+       sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun);
 
        if (sdev) {
                scsi_remove_device(sdev);
@@ -940,6 +940,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
 
        wrk->host = host;
        wrk->lun = vm_srb->lun;
+       wrk->tgt_id = vm_srb->target_id;
        INIT_WORK(&wrk->work, process_err_fn);
        schedule_work(&wrk->work);
 }
@@ -1770,6 +1771,11 @@ static int __init storvsc_drv_init(void)
        fc_transport_template = fc_attach_transport(&fc_transport_functions);
        if (!fc_transport_template)
                return -ENODEV;
+
+       /*
+        * Install Hyper-V specific timeout handler.
+        */
+       fc_transport_template->eh_timed_out = storvsc_eh_timed_out;
 #endif
 
        ret = vmbus_driver_register(&storvsc_drv);
index 91a003011acfacb277e892b47c99771ceae80ffa..a9bac3bf20de14e541a22608fcb1542cad0f6d5f 100644 (file)
@@ -34,7 +34,7 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
 
 static int __init sh_pm_runtime_init(void)
 {
-       if (IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
+       if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
                if (!of_find_compatible_node(NULL, NULL,
                                             "renesas,cpg-mstp-clocks"))
                        return 0;
index aebad36391c93b36658c52222e761366c111216f..8feac599e9ab4bfe886b8da89960f04ed32c1aba 100644 (file)
@@ -1571,6 +1571,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
 
        as->use_cs_gpios = true;
        if (atmel_spi_is_v2(as) &&
+           pdev->dev.of_node &&
            !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
                as->use_cs_gpios = false;
                master->num_chipselect = 4;
index 7de6f8472a8100656884647ad5447be94604e7bb..ecc73c0a97cf5ebf0d2a6c623cf3ce1ac311e62b 100644 (file)
@@ -73,8 +73,8 @@
 
 /* Bitfields in CNTL1 */
 #define BCM2835_AUX_SPI_CNTL1_CSHIGH   0x00000700
-#define BCM2835_AUX_SPI_CNTL1_IDLE     0x00000080
-#define BCM2835_AUX_SPI_CNTL1_TXEMPTY  0x00000040
+#define BCM2835_AUX_SPI_CNTL1_TXEMPTY  0x00000080
+#define BCM2835_AUX_SPI_CNTL1_IDLE     0x00000040
 #define BCM2835_AUX_SPI_CNTL1_MSBF_IN  0x00000002
 #define BCM2835_AUX_SPI_CNTL1_KEEP_IN  0x00000001
 
index 7fd6a4c009d25d8ebfd3f739bd72220f1701320a..7cb0c1921495959dcb6c919c3cb9f1811a5e90bb 100644 (file)
@@ -84,7 +84,7 @@ struct fsl_espi_transfer {
 /* SPCOM register values */
 #define SPCOM_CS(x)            ((x) << 30)
 #define SPCOM_TRANLEN(x)       ((x) << 0)
-#define        SPCOM_TRANLEN_MAX       0xFFFF  /* Max transaction length */
+#define        SPCOM_TRANLEN_MAX       0x10000 /* Max transaction length */
 
 #define AUTOSUSPEND_TIMEOUT 2000
 
@@ -233,7 +233,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
        reinit_completion(&mpc8xxx_spi->done);
 
        /* Set SPCOM[CS] and SPCOM[TRANLEN] field */
-       if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
+       if (t->len > SPCOM_TRANLEN_MAX) {
                dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
                                " beyond the SPCOM[TRANLEN] field\n", t->len);
                return -EINVAL;
index d98c33cb64f9b4825998eb1faa2316b1e4796a7d..6a4ff27f4357eb229815c18b535327487f2df580 100644 (file)
@@ -929,7 +929,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
                                        tx->sgl, tx->nents, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (!desc_tx)
-                       goto no_dma;
+                       goto tx_nodma;
 
                desc_tx->callback = spi_imx_dma_tx_callback;
                desc_tx->callback_param = (void *)spi_imx;
@@ -941,7 +941,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
                                        rx->sgl, rx->nents, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                if (!desc_rx)
-                       goto no_dma;
+                       goto rx_nodma;
 
                desc_rx->callback = spi_imx_dma_rx_callback;
                desc_rx->callback_param = (void *)spi_imx;
@@ -1008,7 +1008,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 
        return ret;
 
-no_dma:
+rx_nodma:
+       dmaengine_terminate_all(master->dma_tx);
+tx_nodma:
        pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
                     dev_driver_string(&master->dev),
                     dev_name(&master->dev));
index 894616f687b0f314168bc17e77d14b7e477a4ec8..cf4bb36bee25c9bdf8ad39a570ceb61fda3a7421 100644 (file)
@@ -761,6 +761,7 @@ static int spi_test_run_iter(struct spi_device *spi,
                test.iterate_transfer_mask = 1;
 
        /* count number of transfers with tx/rx_buf != NULL */
+       rx_count = tx_count = 0;
        for (i = 0; i < test.transfer_count; i++) {
                if (test.transfers[i].tx_buf)
                        tx_count++;
index 7273820275e90c86ddee32b796187d2b940a5c27..0caa3c8bef46c46e0ed66bf89f518cc5c5236449 100644 (file)
@@ -1490,6 +1490,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
        return status;
 
 disable_pm:
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+       pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 free_master:
        spi_master_put(master);
@@ -1501,6 +1503,7 @@ static int omap2_mcspi_remove(struct platform_device *pdev)
        struct spi_master *master = platform_get_drvdata(pdev);
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
+       pm_runtime_dont_use_autosuspend(mcspi->dev);
        pm_runtime_put_sync(mcspi->dev);
        pm_runtime_disable(&pdev->dev);
 
index 3ec7e65a3ffa524efb6e95d98bbc6916592d2a18..db49af90217e3f62cc6f8e3dcf1ec713a732abb2 100644 (file)
@@ -147,7 +147,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video)
        mutex_lock(&mdev->graph_mutex);
        ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev);
        if (ret) {
-               mutex_unlock(&video->lock);
+               mutex_unlock(&mdev->graph_mutex);
                return -ENOMEM;
        }
        media_entity_graph_walk_start(&graph, entity);
index 3327c49674d37d1a362f706eb30d55d7128d60a5..713c63d9681b3cf4e413cb50f93cd466adb8520c 100644 (file)
@@ -898,7 +898,7 @@ static ssize_t unmap_zeroes_data_store(struct config_item *item,
        da->unmap_zeroes_data = flag;
        pr_debug("dev[%p]: SE Device Thin Provisioning LBPRZ bit: %d\n",
                 da->da_dev, flag);
-       return 0;
+       return count;
 }
 
 /*
index cacd97a8cbd02d32509b0a590ff2c40b59be36b1..da457e25717a6099842e883f4291515dcacf344a 100644 (file)
@@ -828,6 +828,50 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
        return dev;
 }
 
+/*
+ * Check if the underlying struct block_device request_queue supports
+ * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
+ * in ATA and we need to set TPE=1
+ */
+bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
+                                      struct request_queue *q, int block_size)
+{
+       if (!blk_queue_discard(q))
+               return false;
+
+       attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
+                                                               block_size;
+       /*
+        * Currently hardcoded to 1 in Linux/SCSI code..
+        */
+       attrib->max_unmap_block_desc_count = 1;
+       attrib->unmap_granularity = q->limits.discard_granularity / block_size;
+       attrib->unmap_granularity_alignment = q->limits.discard_alignment /
+                                                               block_size;
+       attrib->unmap_zeroes_data = q->limits.discard_zeroes_data;
+       return true;
+}
+EXPORT_SYMBOL(target_configure_unmap_from_queue);
+
+/*
+ * Convert from blocksize advertised to the initiator to the 512 byte
+ * units unconditionally used by the Linux block layer.
+ */
+sector_t target_to_linux_sector(struct se_device *dev, sector_t lb)
+{
+       switch (dev->dev_attrib.block_size) {
+       case 4096:
+               return lb << 3;
+       case 2048:
+               return lb << 2;
+       case 1024:
+               return lb << 1;
+       default:
+               return lb;
+       }
+}
+EXPORT_SYMBOL(target_to_linux_sector);
+
 int target_configure_device(struct se_device *dev)
 {
        struct se_hba *hba = dev->se_hba;
index e3195700211a3ebc38192391bf6488ed6ae86099..75f0f08b2a34f32d0b2bfdd35fa40f027e74ae75 100644 (file)
@@ -160,25 +160,11 @@ static int fd_configure_device(struct se_device *dev)
                        " block_device blocks: %llu logical_block_size: %d\n",
                        dev_size, div_u64(dev_size, fd_dev->fd_block_size),
                        fd_dev->fd_block_size);
-               /*
-                * Check if the underlying struct block_device request_queue supports
-                * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
-                * in ATA and we need to set TPE=1
-                */
-               if (blk_queue_discard(q)) {
-                       dev->dev_attrib.max_unmap_lba_count =
-                               q->limits.max_discard_sectors;
-                       /*
-                        * Currently hardcoded to 1 in Linux/SCSI code..
-                        */
-                       dev->dev_attrib.max_unmap_block_desc_count = 1;
-                       dev->dev_attrib.unmap_granularity =
-                               q->limits.discard_granularity >> 9;
-                       dev->dev_attrib.unmap_granularity_alignment =
-                               q->limits.discard_alignment;
+
+               if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
+                                                     fd_dev->fd_block_size))
                        pr_debug("IFILE: BLOCK Discard support available,"
-                                       " disabled by default\n");
-               }
+                                " disabled by default\n");
                /*
                 * Enable write same emulation for IBLOCK and use 0xFFFF as
                 * the smaller WRITE_SAME(10) only has a two-byte block count.
@@ -490,9 +476,12 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
        if (S_ISBLK(inode->i_mode)) {
                /* The backend is block device, use discard */
                struct block_device *bdev = inode->i_bdev;
+               struct se_device *dev = cmd->se_dev;
 
-               ret = blkdev_issue_discard(bdev, lba,
-                               nolb, GFP_KERNEL, 0);
+               ret = blkdev_issue_discard(bdev,
+                                          target_to_linux_sector(dev, lba),
+                                          target_to_linux_sector(dev,  nolb),
+                                          GFP_KERNEL, 0);
                if (ret < 0) {
                        pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",
                                ret);
index 5a2899f9f50b6e4b88730f9db76bf085f97b2b88..abe4eb997a842240f8b76875cc7cfbb7f55dbe0f 100644 (file)
@@ -121,29 +121,11 @@ static int iblock_configure_device(struct se_device *dev)
        dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
        dev->dev_attrib.hw_queue_depth = q->nr_requests;
 
-       /*
-        * Check if the underlying struct block_device request_queue supports
-        * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
-        * in ATA and we need to set TPE=1
-        */
-       if (blk_queue_discard(q)) {
-               dev->dev_attrib.max_unmap_lba_count =
-                               q->limits.max_discard_sectors;
-
-               /*
-                * Currently hardcoded to 1 in Linux/SCSI code..
-                */
-               dev->dev_attrib.max_unmap_block_desc_count = 1;
-               dev->dev_attrib.unmap_granularity =
-                               q->limits.discard_granularity >> 9;
-               dev->dev_attrib.unmap_granularity_alignment =
-                               q->limits.discard_alignment;
-               dev->dev_attrib.unmap_zeroes_data =
-                               q->limits.discard_zeroes_data;
-
+       if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
+                                             dev->dev_attrib.hw_block_size))
                pr_debug("IBLOCK: BLOCK Discard support available,"
-                               " disabled by default\n");
-       }
+                        " disabled by default\n");
+
        /*
         * Enable write same emulation for IBLOCK and use 0xFFFF as
         * the smaller WRITE_SAME(10) only has a two-byte block count.
@@ -415,9 +397,13 @@ static sense_reason_t
 iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
 {
        struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
+       struct se_device *dev = cmd->se_dev;
        int ret;
 
-       ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0);
+       ret = blkdev_issue_discard(bdev,
+                                  target_to_linux_sector(dev, lba),
+                                  target_to_linux_sector(dev,  nolb),
+                                  GFP_KERNEL, 0);
        if (ret < 0) {
                pr_err("blkdev_issue_discard() failed: %d\n", ret);
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -433,8 +419,10 @@ iblock_execute_write_same(struct se_cmd *cmd)
        struct scatterlist *sg;
        struct bio *bio;
        struct bio_list list;
-       sector_t block_lba = cmd->t_task_lba;
-       sector_t sectors = sbc_get_write_same_sectors(cmd);
+       struct se_device *dev = cmd->se_dev;
+       sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba);
+       sector_t sectors = target_to_linux_sector(dev,
+                                       sbc_get_write_same_sectors(cmd));
 
        if (cmd->prot_op) {
                pr_err("WRITE_SAME: Protection information with IBLOCK"
@@ -648,12 +636,12 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                  enum dma_data_direction data_direction)
 {
        struct se_device *dev = cmd->se_dev;
+       sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba);
        struct iblock_req *ibr;
        struct bio *bio, *bio_start;
        struct bio_list list;
        struct scatterlist *sg;
        u32 sg_num = sgl_nents;
-       sector_t block_lba;
        unsigned bio_cnt;
        int rw = 0;
        int i;
@@ -679,24 +667,6 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                rw = READ;
        }
 
-       /*
-        * Convert the blocksize advertised to the initiator to the 512 byte
-        * units unconditionally used by the Linux block layer.
-        */
-       if (dev->dev_attrib.block_size == 4096)
-               block_lba = (cmd->t_task_lba << 3);
-       else if (dev->dev_attrib.block_size == 2048)
-               block_lba = (cmd->t_task_lba << 2);
-       else if (dev->dev_attrib.block_size == 1024)
-               block_lba = (cmd->t_task_lba << 1);
-       else if (dev->dev_attrib.block_size == 512)
-               block_lba = cmd->t_task_lba;
-       else {
-               pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
-                               " %u\n", dev->dev_attrib.block_size);
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-       }
-
        ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
        if (!ibr)
                goto fail;
index dae0750c2032bd87430ab99609d475a615e691db..db4412fe6b8a3f9ba73d46fadb11dcf1bf40980b 100644 (file)
@@ -141,7 +141,6 @@ void        transport_dump_vpd_proto_id(struct t10_vpd *, unsigned char *, int);
 int    transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int);
 int    transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int);
 int    transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
-bool   target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
 void   transport_clear_lun_ref(struct se_lun *);
 void   transport_send_task_abort(struct se_cmd *);
 sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
index fcdcb117c60da36e546370ecfd7e973f17b5d4ec..82a663ba98009fb5f286a88651c9b3a54cf68bbb 100644 (file)
@@ -68,23 +68,25 @@ void core_tmr_release_req(struct se_tmr_req *tmr)
 
        if (dev) {
                spin_lock_irqsave(&dev->se_tmr_lock, flags);
-               list_del(&tmr->tmr_list);
+               list_del_init(&tmr->tmr_list);
                spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
        }
 
        kfree(tmr);
 }
 
-static void core_tmr_handle_tas_abort(
-       struct se_node_acl *tmr_nacl,
-       struct se_cmd *cmd,
-       int tas)
+static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
 {
-       bool remove = true;
+       unsigned long flags;
+       bool remove = true, send_tas;
        /*
         * TASK ABORTED status (TAS) bit support
         */
-       if ((tmr_nacl && (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) {
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       send_tas = (cmd->transport_state & CMD_T_TAS);
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
+       if (send_tas) {
                remove = false;
                transport_send_task_abort(cmd);
        }
@@ -107,6 +109,46 @@ static int target_check_cdb_and_preempt(struct list_head *list,
        return 1;
 }
 
+static bool __target_check_io_state(struct se_cmd *se_cmd,
+                                   struct se_session *tmr_sess, int tas)
+{
+       struct se_session *sess = se_cmd->se_sess;
+
+       assert_spin_locked(&sess->sess_cmd_lock);
+       WARN_ON_ONCE(!irqs_disabled());
+       /*
+        * If command already reached CMD_T_COMPLETE state within
+        * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown,
+        * this se_cmd has been passed to fabric driver and will
+        * not be aborted.
+        *
+        * Otherwise, obtain a local se_cmd->cmd_kref now for TMR
+        * ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as
+        * long as se_cmd->cmd_kref is still active unless zero.
+        */
+       spin_lock(&se_cmd->t_state_lock);
+       if (se_cmd->transport_state & (CMD_T_COMPLETE | CMD_T_FABRIC_STOP)) {
+               pr_debug("Attempted to abort io tag: %llu already complete or"
+                       " fabric stop, skipping\n", se_cmd->tag);
+               spin_unlock(&se_cmd->t_state_lock);
+               return false;
+       }
+       if (sess->sess_tearing_down || se_cmd->cmd_wait_set) {
+               pr_debug("Attempted to abort io tag: %llu already shutdown,"
+                       " skipping\n", se_cmd->tag);
+               spin_unlock(&se_cmd->t_state_lock);
+               return false;
+       }
+       se_cmd->transport_state |= CMD_T_ABORTED;
+
+       if ((tmr_sess != se_cmd->se_sess) && tas)
+               se_cmd->transport_state |= CMD_T_TAS;
+
+       spin_unlock(&se_cmd->t_state_lock);
+
+       return kref_get_unless_zero(&se_cmd->cmd_kref);
+}
+
 void core_tmr_abort_task(
        struct se_device *dev,
        struct se_tmr_req *tmr,
@@ -130,34 +172,22 @@ void core_tmr_abort_task(
                if (tmr->ref_task_tag != ref_tag)
                        continue;
 
-               if (!kref_get_unless_zero(&se_cmd->cmd_kref))
-                       continue;
-
                printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
                        se_cmd->se_tfo->get_fabric_name(), ref_tag);
 
-               spin_lock(&se_cmd->t_state_lock);
-               if (se_cmd->transport_state & CMD_T_COMPLETE) {
-                       printk("ABORT_TASK: ref_tag: %llu already complete,"
-                              " skipping\n", ref_tag);
-                       spin_unlock(&se_cmd->t_state_lock);
+               if (!__target_check_io_state(se_cmd, se_sess, 0)) {
                        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
-
                        target_put_sess_cmd(se_cmd);
-
                        goto out;
                }
-               se_cmd->transport_state |= CMD_T_ABORTED;
-               spin_unlock(&se_cmd->t_state_lock);
-
                list_del_init(&se_cmd->se_cmd_list);
                spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 
                cancel_work_sync(&se_cmd->work);
                transport_wait_for_tasks(se_cmd);
 
-               target_put_sess_cmd(se_cmd);
                transport_cmd_finish_abort(se_cmd, true);
+               target_put_sess_cmd(se_cmd);
 
                printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
                                " ref_tag: %llu\n", ref_tag);
@@ -178,9 +208,11 @@ static void core_tmr_drain_tmr_list(
        struct list_head *preempt_and_abort_list)
 {
        LIST_HEAD(drain_tmr_list);
+       struct se_session *sess;
        struct se_tmr_req *tmr_p, *tmr_pp;
        struct se_cmd *cmd;
        unsigned long flags;
+       bool rc;
        /*
         * Release all pending and outgoing TMRs aside from the received
         * LUN_RESET tmr..
@@ -206,17 +238,39 @@ static void core_tmr_drain_tmr_list(
                if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
                        continue;
 
+               sess = cmd->se_sess;
+               if (WARN_ON_ONCE(!sess))
+                       continue;
+
+               spin_lock(&sess->sess_cmd_lock);
                spin_lock(&cmd->t_state_lock);
-               if (!(cmd->transport_state & CMD_T_ACTIVE)) {
+               if (!(cmd->transport_state & CMD_T_ACTIVE) ||
+                    (cmd->transport_state & CMD_T_FABRIC_STOP)) {
                        spin_unlock(&cmd->t_state_lock);
+                       spin_unlock(&sess->sess_cmd_lock);
                        continue;
                }
                if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) {
                        spin_unlock(&cmd->t_state_lock);
+                       spin_unlock(&sess->sess_cmd_lock);
                        continue;
                }
+               if (sess->sess_tearing_down || cmd->cmd_wait_set) {
+                       spin_unlock(&cmd->t_state_lock);
+                       spin_unlock(&sess->sess_cmd_lock);
+                       continue;
+               }
+               cmd->transport_state |= CMD_T_ABORTED;
                spin_unlock(&cmd->t_state_lock);
 
+               rc = kref_get_unless_zero(&cmd->cmd_kref);
+               if (!rc) {
+                       printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n");
+                       spin_unlock(&sess->sess_cmd_lock);
+                       continue;
+               }
+               spin_unlock(&sess->sess_cmd_lock);
+
                list_move_tail(&tmr_p->tmr_list, &drain_tmr_list);
        }
        spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
@@ -230,20 +284,26 @@ static void core_tmr_drain_tmr_list(
                        (preempt_and_abort_list) ? "Preempt" : "", tmr_p,
                        tmr_p->function, tmr_p->response, cmd->t_state);
 
+               cancel_work_sync(&cmd->work);
+               transport_wait_for_tasks(cmd);
+
                transport_cmd_finish_abort(cmd, 1);
+               target_put_sess_cmd(cmd);
        }
 }
 
 static void core_tmr_drain_state_list(
        struct se_device *dev,
        struct se_cmd *prout_cmd,
-       struct se_node_acl *tmr_nacl,
+       struct se_session *tmr_sess,
        int tas,
        struct list_head *preempt_and_abort_list)
 {
        LIST_HEAD(drain_task_list);
+       struct se_session *sess;
        struct se_cmd *cmd, *next;
        unsigned long flags;
+       int rc;
 
        /*
         * Complete outstanding commands with TASK_ABORTED SAM status.
@@ -282,6 +342,16 @@ static void core_tmr_drain_state_list(
                if (prout_cmd == cmd)
                        continue;
 
+               sess = cmd->se_sess;
+               if (WARN_ON_ONCE(!sess))
+                       continue;
+
+               spin_lock(&sess->sess_cmd_lock);
+               rc = __target_check_io_state(cmd, tmr_sess, tas);
+               spin_unlock(&sess->sess_cmd_lock);
+               if (!rc)
+                       continue;
+
                list_move_tail(&cmd->state_list, &drain_task_list);
                cmd->state_active = false;
        }
@@ -289,7 +359,7 @@ static void core_tmr_drain_state_list(
 
        while (!list_empty(&drain_task_list)) {
                cmd = list_entry(drain_task_list.next, struct se_cmd, state_list);
-               list_del(&cmd->state_list);
+               list_del_init(&cmd->state_list);
 
                pr_debug("LUN_RESET: %s cmd: %p"
                        " ITT/CmdSN: 0x%08llx/0x%08x, i_state: %d, t_state: %d"
@@ -313,16 +383,11 @@ static void core_tmr_drain_state_list(
                 * loop above, but we do it down here given that
                 * cancel_work_sync may block.
                 */
-               if (cmd->t_state == TRANSPORT_COMPLETE)
-                       cancel_work_sync(&cmd->work);
-
-               spin_lock_irqsave(&cmd->t_state_lock, flags);
-               target_stop_cmd(cmd, &flags);
-
-               cmd->transport_state |= CMD_T_ABORTED;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+               cancel_work_sync(&cmd->work);
+               transport_wait_for_tasks(cmd);
 
-               core_tmr_handle_tas_abort(tmr_nacl, cmd, tas);
+               core_tmr_handle_tas_abort(cmd, tas);
+               target_put_sess_cmd(cmd);
        }
 }
 
@@ -334,6 +399,7 @@ int core_tmr_lun_reset(
 {
        struct se_node_acl *tmr_nacl = NULL;
        struct se_portal_group *tmr_tpg = NULL;
+       struct se_session *tmr_sess = NULL;
        int tas;
         /*
         * TASK_ABORTED status bit, this is configurable via ConfigFS
@@ -352,8 +418,9 @@ int core_tmr_lun_reset(
         * or struct se_device passthrough..
         */
        if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) {
-               tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
-               tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
+               tmr_sess = tmr->task_cmd->se_sess;
+               tmr_nacl = tmr_sess->se_node_acl;
+               tmr_tpg = tmr_sess->se_tpg;
                if (tmr_nacl && tmr_tpg) {
                        pr_debug("LUN_RESET: TMR caller fabric: %s"
                                " initiator port %s\n",
@@ -366,7 +433,7 @@ int core_tmr_lun_reset(
                dev->transport->name, tas);
 
        core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
-       core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas,
+       core_tmr_drain_state_list(dev, prout_cmd, tmr_sess, tas,
                                preempt_and_abort_list);
 
        /*
index 9f3608e10f25a0ea2c1cf71b419596d558e7f31b..867bc6d0a68a3ecfbd1aab610f01ff73614b3305 100644 (file)
@@ -534,9 +534,6 @@ void transport_deregister_session(struct se_session *se_sess)
 }
 EXPORT_SYMBOL(transport_deregister_session);
 
-/*
- * Called with cmd->t_state_lock held.
- */
 static void target_remove_from_state_list(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
@@ -561,10 +558,6 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       if (write_pending)
-               cmd->t_state = TRANSPORT_WRITE_PENDING;
-
        if (remove_from_lists) {
                target_remove_from_state_list(cmd);
 
@@ -574,6 +567,10 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
                cmd->se_lun = NULL;
        }
 
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       if (write_pending)
+               cmd->t_state = TRANSPORT_WRITE_PENDING;
+
        /*
         * Determine if frontend context caller is requesting the stopping of
         * this command for frontend exceptions.
@@ -627,6 +624,8 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
 
 void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 {
+       bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF);
+
        if (cmd->se_cmd_flags & SCF_SE_LUN_CMD)
                transport_lun_remove_cmd(cmd);
        /*
@@ -638,7 +637,7 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 
        if (transport_cmd_check_stop_to_fabric(cmd))
                return;
-       if (remove)
+       if (remove && ack_kref)
                transport_put_cmd(cmd);
 }
 
@@ -693,20 +692,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
                        success = 1;
        }
 
-       /*
-        * See if we are waiting to complete for an exception condition.
-        */
-       if (cmd->transport_state & CMD_T_REQUEST_STOP) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               complete(&cmd->task_stop_comp);
-               return;
-       }
-
        /*
         * Check for case where an explicit ABORT_TASK has been received
         * and transport_wait_for_tasks() will be waiting for completion..
         */
-       if (cmd->transport_state & CMD_T_ABORTED &&
+       if (cmd->transport_state & CMD_T_ABORTED ||
            cmd->transport_state & CMD_T_STOP) {
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                complete_all(&cmd->t_transport_stop_comp);
@@ -721,10 +711,10 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
        cmd->transport_state |= (CMD_T_COMPLETE | CMD_T_ACTIVE);
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       if (cmd->cpuid == -1)
-               queue_work(target_completion_wq, &cmd->work);
-       else
+       if (cmd->se_cmd_flags & SCF_USE_CPUID)
                queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work);
+       else
+               queue_work(target_completion_wq, &cmd->work);
 }
 EXPORT_SYMBOL(target_complete_cmd);
 
@@ -1203,7 +1193,6 @@ void transport_init_se_cmd(
        INIT_LIST_HEAD(&cmd->state_list);
        init_completion(&cmd->t_transport_stop_comp);
        init_completion(&cmd->cmd_wait_comp);
-       init_completion(&cmd->task_stop_comp);
        spin_lock_init(&cmd->t_state_lock);
        kref_init(&cmd->cmd_kref);
        cmd->transport_state = CMD_T_DEV_ACTIVE;
@@ -1437,6 +1426,12 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
         */
        transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
                                data_length, data_dir, task_attr, sense);
+
+       if (flags & TARGET_SCF_USE_CPUID)
+               se_cmd->se_cmd_flags |= SCF_USE_CPUID;
+       else
+               se_cmd->cpuid = WORK_CPU_UNBOUND;
+
        if (flags & TARGET_SCF_UNKNOWN_SIZE)
                se_cmd->unknown_data_length = 1;
        /*
@@ -1634,33 +1629,6 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
 }
 EXPORT_SYMBOL(target_submit_tmr);
 
-/*
- * If the cmd is active, request it to be stopped and sleep until it
- * has completed.
- */
-bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
-       __releases(&cmd->t_state_lock)
-       __acquires(&cmd->t_state_lock)
-{
-       bool was_active = false;
-
-       if (cmd->transport_state & CMD_T_BUSY) {
-               cmd->transport_state |= CMD_T_REQUEST_STOP;
-               spin_unlock_irqrestore(&cmd->t_state_lock, *flags);
-
-               pr_debug("cmd %p waiting to complete\n", cmd);
-               wait_for_completion(&cmd->task_stop_comp);
-               pr_debug("cmd %p stopped successfully\n", cmd);
-
-               spin_lock_irqsave(&cmd->t_state_lock, *flags);
-               cmd->transport_state &= ~CMD_T_REQUEST_STOP;
-               cmd->transport_state &= ~CMD_T_BUSY;
-               was_active = true;
-       }
-
-       return was_active;
-}
-
 /*
  * Handle SAM-esque emulation for generic transport request failures.
  */
@@ -1859,19 +1827,21 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
        return true;
 }
 
+static int __transport_check_aborted_status(struct se_cmd *, int);
+
 void target_execute_cmd(struct se_cmd *cmd)
 {
-       /*
-        * If the received CDB has aleady been aborted stop processing it here.
-        */
-       if (transport_check_aborted_status(cmd, 1))
-               return;
-
        /*
         * Determine if frontend context caller is requesting the stopping of
         * this command for frontend exceptions.
+        *
+        * If the received CDB has aleady been aborted stop processing it here.
         */
        spin_lock_irq(&cmd->t_state_lock);
+       if (__transport_check_aborted_status(cmd, 1)) {
+               spin_unlock_irq(&cmd->t_state_lock);
+               return;
+       }
        if (cmd->transport_state & CMD_T_STOP) {
                pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
                        __func__, __LINE__, cmd->tag);
@@ -2222,20 +2192,14 @@ static inline void transport_free_pages(struct se_cmd *cmd)
 }
 
 /**
- * transport_release_cmd - free a command
- * @cmd:       command to free
+ * transport_put_cmd - release a reference to a command
+ * @cmd:       command to release
  *
- * This routine unconditionally frees a command, and reference counting
- * or list removal must be done in the caller.
+ * This routine releases our reference to the command and frees it if possible.
  */
-static int transport_release_cmd(struct se_cmd *cmd)
+static int transport_put_cmd(struct se_cmd *cmd)
 {
        BUG_ON(!cmd->se_tfo);
-
-       if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
-               core_tmr_release_req(cmd->se_tmr_req);
-       if (cmd->t_task_cdb != cmd->__t_task_cdb)
-               kfree(cmd->t_task_cdb);
        /*
         * If this cmd has been setup with target_get_sess_cmd(), drop
         * the kref and call ->release_cmd() in kref callback.
@@ -2243,18 +2207,6 @@ static int transport_release_cmd(struct se_cmd *cmd)
        return target_put_sess_cmd(cmd);
 }
 
-/**
- * transport_put_cmd - release a reference to a command
- * @cmd:       command to release
- *
- * This routine releases our reference to the command and frees it if possible.
- */
-static int transport_put_cmd(struct se_cmd *cmd)
-{
-       transport_free_pages(cmd);
-       return transport_release_cmd(cmd);
-}
-
 void *transport_kmap_data_sg(struct se_cmd *cmd)
 {
        struct scatterlist *sg = cmd->t_data_sg;
@@ -2450,34 +2402,58 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
        }
 }
 
-int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
+static bool
+__transport_wait_for_tasks(struct se_cmd *, bool, bool *, bool *,
+                          unsigned long *flags);
+
+static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas)
 {
        unsigned long flags;
+
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       __transport_wait_for_tasks(cmd, true, aborted, tas, &flags);
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+}
+
+int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
+{
        int ret = 0;
+       bool aborted = false, tas = false;
 
        if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
                if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
-                        transport_wait_for_tasks(cmd);
+                       target_wait_free_cmd(cmd, &aborted, &tas);
 
-               ret = transport_release_cmd(cmd);
+               if (!aborted || tas)
+                       ret = transport_put_cmd(cmd);
        } else {
                if (wait_for_tasks)
-                       transport_wait_for_tasks(cmd);
+                       target_wait_free_cmd(cmd, &aborted, &tas);
                /*
                 * Handle WRITE failure case where transport_generic_new_cmd()
                 * has already added se_cmd to state_list, but fabric has
                 * failed command before I/O submission.
                 */
-               if (cmd->state_active) {
-                       spin_lock_irqsave(&cmd->t_state_lock, flags);
+               if (cmd->state_active)
                        target_remove_from_state_list(cmd);
-                       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               }
 
                if (cmd->se_lun)
                        transport_lun_remove_cmd(cmd);
 
-               ret = transport_put_cmd(cmd);
+               if (!aborted || tas)
+                       ret = transport_put_cmd(cmd);
+       }
+       /*
+        * If the task has been internally aborted due to TMR ABORT_TASK
+        * or LUN_RESET, target_core_tmr.c is responsible for performing
+        * the remaining calls to target_put_sess_cmd(), and not the
+        * callers of this function.
+        */
+       if (aborted) {
+               pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag);
+               wait_for_completion(&cmd->cmd_wait_comp);
+               cmd->se_tfo->release_cmd(cmd);
+               ret = 1;
        }
        return ret;
 }
@@ -2517,26 +2493,46 @@ out:
 }
 EXPORT_SYMBOL(target_get_sess_cmd);
 
+static void target_free_cmd_mem(struct se_cmd *cmd)
+{
+       transport_free_pages(cmd);
+
+       if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
+               core_tmr_release_req(cmd->se_tmr_req);
+       if (cmd->t_task_cdb != cmd->__t_task_cdb)
+               kfree(cmd->t_task_cdb);
+}
+
 static void target_release_cmd_kref(struct kref *kref)
 {
        struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
        struct se_session *se_sess = se_cmd->se_sess;
        unsigned long flags;
+       bool fabric_stop;
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        if (list_empty(&se_cmd->se_cmd_list)) {
                spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+               target_free_cmd_mem(se_cmd);
                se_cmd->se_tfo->release_cmd(se_cmd);
                return;
        }
-       if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
+
+       spin_lock(&se_cmd->t_state_lock);
+       fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
+       spin_unlock(&se_cmd->t_state_lock);
+
+       if (se_cmd->cmd_wait_set || fabric_stop) {
+               list_del_init(&se_cmd->se_cmd_list);
                spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+               target_free_cmd_mem(se_cmd);
                complete(&se_cmd->cmd_wait_comp);
                return;
        }
-       list_del(&se_cmd->se_cmd_list);
+       list_del_init(&se_cmd->se_cmd_list);
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 
+       target_free_cmd_mem(se_cmd);
        se_cmd->se_tfo->release_cmd(se_cmd);
 }
 
@@ -2548,6 +2544,7 @@ int target_put_sess_cmd(struct se_cmd *se_cmd)
        struct se_session *se_sess = se_cmd->se_sess;
 
        if (!se_sess) {
+               target_free_cmd_mem(se_cmd);
                se_cmd->se_tfo->release_cmd(se_cmd);
                return 1;
        }
@@ -2564,6 +2561,7 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
 {
        struct se_cmd *se_cmd;
        unsigned long flags;
+       int rc;
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        if (se_sess->sess_tearing_down) {
@@ -2573,8 +2571,15 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
        se_sess->sess_tearing_down = 1;
        list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
 
-       list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list)
-               se_cmd->cmd_wait_set = 1;
+       list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) {
+               rc = kref_get_unless_zero(&se_cmd->cmd_kref);
+               if (rc) {
+                       se_cmd->cmd_wait_set = 1;
+                       spin_lock(&se_cmd->t_state_lock);
+                       se_cmd->transport_state |= CMD_T_FABRIC_STOP;
+                       spin_unlock(&se_cmd->t_state_lock);
+               }
+       }
 
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 }
@@ -2587,15 +2592,25 @@ void target_wait_for_sess_cmds(struct se_session *se_sess)
 {
        struct se_cmd *se_cmd, *tmp_cmd;
        unsigned long flags;
+       bool tas;
 
        list_for_each_entry_safe(se_cmd, tmp_cmd,
                                &se_sess->sess_wait_list, se_cmd_list) {
-               list_del(&se_cmd->se_cmd_list);
+               list_del_init(&se_cmd->se_cmd_list);
 
                pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
                        " %d\n", se_cmd, se_cmd->t_state,
                        se_cmd->se_tfo->get_cmd_state(se_cmd));
 
+               spin_lock_irqsave(&se_cmd->t_state_lock, flags);
+               tas = (se_cmd->transport_state & CMD_T_TAS);
+               spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
+
+               if (!target_put_sess_cmd(se_cmd)) {
+                       if (tas)
+                               target_put_sess_cmd(se_cmd);
+               }
+
                wait_for_completion(&se_cmd->cmd_wait_comp);
                pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d"
                        " fabric state: %d\n", se_cmd, se_cmd->t_state,
@@ -2617,53 +2632,75 @@ void transport_clear_lun_ref(struct se_lun *lun)
        wait_for_completion(&lun->lun_ref_comp);
 }
 
-/**
- * transport_wait_for_tasks - wait for completion to occur
- * @cmd:       command to wait
- *
- * Called from frontend fabric context to wait for storage engine
- * to pause and/or release frontend generated struct se_cmd.
- */
-bool transport_wait_for_tasks(struct se_cmd *cmd)
+static bool
+__transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop,
+                          bool *aborted, bool *tas, unsigned long *flags)
+       __releases(&cmd->t_state_lock)
+       __acquires(&cmd->t_state_lock)
 {
-       unsigned long flags;
 
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       assert_spin_locked(&cmd->t_state_lock);
+       WARN_ON_ONCE(!irqs_disabled());
+
+       if (fabric_stop)
+               cmd->transport_state |= CMD_T_FABRIC_STOP;
+
+       if (cmd->transport_state & CMD_T_ABORTED)
+               *aborted = true;
+
+       if (cmd->transport_state & CMD_T_TAS)
+               *tas = true;
+
        if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) &&
-           !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+           !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
                return false;
-       }
 
        if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) &&
-           !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+           !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
                return false;
-       }
 
-       if (!(cmd->transport_state & CMD_T_ACTIVE)) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       if (!(cmd->transport_state & CMD_T_ACTIVE))
+               return false;
+
+       if (fabric_stop && *aborted)
                return false;
-       }
 
        cmd->transport_state |= CMD_T_STOP;
 
-       pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d, t_state: %d, CMD_T_STOP\n",
-               cmd, cmd->tag, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
+       pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d,"
+                " t_state: %d, CMD_T_STOP\n", cmd, cmd->tag,
+                cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
 
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       spin_unlock_irqrestore(&cmd->t_state_lock, *flags);
 
        wait_for_completion(&cmd->t_transport_stop_comp);
 
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       spin_lock_irqsave(&cmd->t_state_lock, *flags);
        cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP);
 
-       pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->t_transport_stop_comp) for ITT: 0x%08llx\n",
-               cmd->tag);
+       pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->"
+                "t_transport_stop_comp) for ITT: 0x%08llx\n", cmd->tag);
 
+       return true;
+}
+
+/**
+ * transport_wait_for_tasks - wait for completion to occur
+ * @cmd:       command to wait
+ *
+ * Called from frontend fabric context to wait for storage engine
+ * to pause and/or release frontend generated struct se_cmd.
+ */
+bool transport_wait_for_tasks(struct se_cmd *cmd)
+{
+       unsigned long flags;
+       bool ret, aborted = false, tas = false;
+
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       ret = __transport_wait_for_tasks(cmd, false, &aborted, &tas, &flags);
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       return true;
+       return ret;
 }
 EXPORT_SYMBOL(transport_wait_for_tasks);
 
@@ -2845,28 +2882,49 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
 }
 EXPORT_SYMBOL(transport_send_check_condition_and_sense);
 
-int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
+static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status)
+       __releases(&cmd->t_state_lock)
+       __acquires(&cmd->t_state_lock)
 {
+       assert_spin_locked(&cmd->t_state_lock);
+       WARN_ON_ONCE(!irqs_disabled());
+
        if (!(cmd->transport_state & CMD_T_ABORTED))
                return 0;
-
        /*
         * If cmd has been aborted but either no status is to be sent or it has
         * already been sent, just return
         */
-       if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS))
+       if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) {
+               if (send_status)
+                       cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
                return 1;
+       }
 
-       pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08llx\n",
-                cmd->t_task_cdb[0], cmd->tag);
+       pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB:"
+               " 0x%02x ITT: 0x%08llx\n", cmd->t_task_cdb[0], cmd->tag);
 
        cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS;
        cmd->scsi_status = SAM_STAT_TASK_ABORTED;
        trace_target_cmd_complete(cmd);
+
+       spin_unlock_irq(&cmd->t_state_lock);
        cmd->se_tfo->queue_status(cmd);
+       spin_lock_irq(&cmd->t_state_lock);
 
        return 1;
 }
+
+int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
+{
+       int ret;
+
+       spin_lock_irq(&cmd->t_state_lock);
+       ret = __transport_check_aborted_status(cmd, send_status);
+       spin_unlock_irq(&cmd->t_state_lock);
+
+       return ret;
+}
 EXPORT_SYMBOL(transport_check_aborted_status);
 
 void transport_send_task_abort(struct se_cmd *cmd)
@@ -2888,11 +2946,17 @@ void transport_send_task_abort(struct se_cmd *cmd)
         */
        if (cmd->data_direction == DMA_TO_DEVICE) {
                if (cmd->se_tfo->write_pending_status(cmd) != 0) {
-                       cmd->transport_state |= CMD_T_ABORTED;
+                       spin_lock_irqsave(&cmd->t_state_lock, flags);
+                       if (cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS) {
+                               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+                               goto send_abort;
+                       }
                        cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
+                       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                        return;
                }
        }
+send_abort:
        cmd->scsi_status = SAM_STAT_TASK_ABORTED;
 
        transport_lun_remove_cmd(cmd);
@@ -2909,8 +2973,17 @@ static void target_tmr_work(struct work_struct *work)
        struct se_cmd *cmd = container_of(work, struct se_cmd, work);
        struct se_device *dev = cmd->se_dev;
        struct se_tmr_req *tmr = cmd->se_tmr_req;
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       if (cmd->transport_state & CMD_T_ABORTED) {
+               tmr->response = TMR_FUNCTION_REJECTED;
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+               goto check_stop;
+       }
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
        switch (tmr->function) {
        case TMR_ABORT_TASK:
                core_tmr_abort_task(dev, tmr, cmd->se_sess);
@@ -2943,9 +3016,17 @@ static void target_tmr_work(struct work_struct *work)
                break;
        }
 
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       if (cmd->transport_state & CMD_T_ABORTED) {
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+               goto check_stop;
+       }
        cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
        cmd->se_tfo->queue_tm_rsp(cmd);
 
+check_stop:
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
index dd600e5ead719ba95d41ae0b3b4eeed8a9161eab..94f5154ac788594e4a223147f02c20642ec842df 100644 (file)
@@ -903,7 +903,7 @@ static int tcmu_configure_device(struct se_device *dev)
        info->version = __stringify(TCMU_MAILBOX_VERSION);
 
        info->mem[0].name = "tcm-user command & data buffer";
-       info->mem[0].addr = (phys_addr_t) udev->mb_addr;
+       info->mem[0].addr = (phys_addr_t)(uintptr_t)udev->mb_addr;
        info->mem[0].size = TCMU_RING_SIZE;
        info->mem[0].memtype = UIO_MEM_VIRTUAL;
 
index 8cc4ac64a91c36347b9307addb88ae99d545d2b7..7c92c09be21386c3d60ff41b76a6694234c93432 100644 (file)
@@ -195,7 +195,7 @@ config IMX_THERMAL
          passive trip is crossed.
 
 config SPEAR_THERMAL
-       bool "SPEAr thermal sensor driver"
+       tristate "SPEAr thermal sensor driver"
        depends on PLAT_SPEAR || COMPILE_TEST
        depends on OF
        help
@@ -237,8 +237,8 @@ config DOVE_THERMAL
          framework.
 
 config DB8500_THERMAL
-       bool "DB8500 thermal management"
-       depends on ARCH_U8500
+       tristate "DB8500 thermal management"
+       depends on MFD_DB8500_PRCMU
        default y
        help
          Adds DB8500 thermal management implementation according to the thermal
index e3fbc5a5d88f166930e8633e671348614d00dd4d..6ceac4f2d4b227d52045632992568d08ea158c5b 100644 (file)
@@ -377,26 +377,28 @@ static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device,
  * get_load() - get load for a cpu since last updated
  * @cpufreq_device:    &struct cpufreq_cooling_device for this cpu
  * @cpu:       cpu number
+ * @cpu_idx:   index of the cpu in cpufreq_device->allowed_cpus
  *
  * Return: The average load of cpu @cpu in percentage since this
  * function was last called.
  */
-static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu)
+static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu,
+                   int cpu_idx)
 {
        u32 load;
        u64 now, now_idle, delta_time, delta_idle;
 
        now_idle = get_cpu_idle_time(cpu, &now, 0);
-       delta_idle = now_idle - cpufreq_device->time_in_idle[cpu];
-       delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu];
+       delta_idle = now_idle - cpufreq_device->time_in_idle[cpu_idx];
+       delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu_idx];
 
        if (delta_time <= delta_idle)
                load = 0;
        else
                load = div64_u64(100 * (delta_time - delta_idle), delta_time);
 
-       cpufreq_device->time_in_idle[cpu] = now_idle;
-       cpufreq_device->time_in_idle_timestamp[cpu] = now;
+       cpufreq_device->time_in_idle[cpu_idx] = now_idle;
+       cpufreq_device->time_in_idle_timestamp[cpu_idx] = now;
 
        return load;
 }
@@ -598,7 +600,7 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
                u32 load;
 
                if (cpu_online(cpu))
-                       load = get_load(cpufreq_device, cpu);
+                       load = get_load(cpufreq_device, cpu, i);
                else
                        load = 0;
 
index be4eedcb839ac22158fe180c2abc37df712d9511..9043f8f918529bd600eda1bbffe3bdf91f036ef4 100644 (file)
@@ -475,14 +475,10 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
 
        sensor_np = of_node_get(dev->of_node);
 
-       for_each_child_of_node(np, child) {
+       for_each_available_child_of_node(np, child) {
                struct of_phandle_args sensor_specs;
                int ret, id;
 
-               /* Check whether child is enabled or not */
-               if (!of_device_is_available(child))
-                       continue;
-
                /* For now, thermal framework supports only 1 sensor per zone */
                ret = of_parse_phandle_with_args(child, "thermal-sensors",
                                                 "#thermal-sensor-cells",
@@ -881,16 +877,12 @@ int __init of_parse_thermal_zones(void)
                return 0; /* Run successfully on systems without thermal DT */
        }
 
-       for_each_child_of_node(np, child) {
+       for_each_available_child_of_node(np, child) {
                struct thermal_zone_device *zone;
                struct thermal_zone_params *tzp;
                int i, mask = 0;
                u32 prop;
 
-               /* Check whether child is enabled or not */
-               if (!of_device_is_available(child))
-                       continue;
-
                tz = thermal_of_build_thermal_zone(child);
                if (IS_ERR(tz)) {
                        pr_err("failed to build thermal zone %s: %ld\n",
@@ -968,13 +960,9 @@ void of_thermal_destroy_zones(void)
                return;
        }
 
-       for_each_child_of_node(np, child) {
+       for_each_available_child_of_node(np, child) {
                struct thermal_zone_device *zone;
 
-               /* Check whether child is enabled or not */
-               if (!of_device_is_available(child))
-                       continue;
-
                zone = thermal_zone_get_zone_by_name(child->name);
                if (IS_ERR(zone))
                        continue;
index 44b9c485157d8c6e624548ee7c7cfccacea241d9..0e735acea33afc7b8e747857b57046647d50e7d9 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reboot.h>
@@ -75,8 +76,10 @@ struct rcar_thermal_priv {
 #define rcar_has_irq_support(priv)     ((priv)->common->base)
 #define rcar_id_to_shift(priv)         ((priv)->id * 8)
 
+#define USE_OF_THERMAL 1
 static const struct of_device_id rcar_thermal_dt_ids[] = {
        { .compatible = "renesas,rcar-thermal", },
+       { .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL },
        {},
 };
 MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
@@ -200,9 +203,9 @@ err_out_unlock:
        return ret;
 }
 
-static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
+static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv,
+                                        int *temp)
 {
-       struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
        int tmp;
        int ret;
 
@@ -226,6 +229,20 @@ static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
        return 0;
 }
 
+static int rcar_thermal_of_get_temp(void *data, int *temp)
+{
+       struct rcar_thermal_priv *priv = data;
+
+       return rcar_thermal_get_current_temp(priv, temp);
+}
+
+static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
+{
+       struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
+
+       return rcar_thermal_get_current_temp(priv, temp);
+}
+
 static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
                                      int trip, enum thermal_trip_type *type)
 {
@@ -282,6 +299,10 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone,
        return 0;
 }
 
+static const struct thermal_zone_of_device_ops rcar_thermal_zone_of_ops = {
+       .get_temp       = rcar_thermal_of_get_temp,
+};
+
 static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
        .get_temp       = rcar_thermal_get_temp,
        .get_trip_type  = rcar_thermal_get_trip_type,
@@ -318,14 +339,20 @@ static void rcar_thermal_work(struct work_struct *work)
 
        priv = container_of(work, struct rcar_thermal_priv, work.work);
 
-       rcar_thermal_get_temp(priv->zone, &cctemp);
+       ret = rcar_thermal_get_current_temp(priv, &cctemp);
+       if (ret < 0)
+               return;
+
        ret = rcar_thermal_update_temp(priv);
        if (ret < 0)
                return;
 
        rcar_thermal_irq_enable(priv);
 
-       rcar_thermal_get_temp(priv->zone, &nctemp);
+       ret = rcar_thermal_get_current_temp(priv, &nctemp);
+       if (ret < 0)
+               return;
+
        if (nctemp != cctemp)
                thermal_zone_device_update(priv->zone);
 }
@@ -403,6 +430,8 @@ static int rcar_thermal_probe(struct platform_device *pdev)
        struct rcar_thermal_priv *priv;
        struct device *dev = &pdev->dev;
        struct resource *res, *irq;
+       const struct of_device_id *of_id = of_match_device(rcar_thermal_dt_ids, dev);
+       unsigned long of_data = (unsigned long)of_id->data;
        int mres = 0;
        int i;
        int ret = -ENODEV;
@@ -463,7 +492,13 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                if (ret < 0)
                        goto error_unregister;
 
-               priv->zone = thermal_zone_device_register("rcar_thermal",
+               if (of_data == USE_OF_THERMAL)
+                       priv->zone = thermal_zone_of_sensor_register(
+                                               dev, i, priv,
+                                               &rcar_thermal_zone_of_ops);
+               else
+                       priv->zone = thermal_zone_device_register(
+                                               "rcar_thermal",
                                                1, 0, priv,
                                                &rcar_thermal_zone_ops, NULL, 0,
                                                idle);
index 534dd913666283fa13eecfaeb8823ea3d55ac0c8..81b35aace9de0439c4dd76c4c4c0d91597d3b3f3 100644 (file)
@@ -54,8 +54,7 @@ static struct thermal_zone_device_ops ops = {
        .get_temp = thermal_get_temp,
 };
 
-#ifdef CONFIG_PM
-static int spear_thermal_suspend(struct device *dev)
+static int __maybe_unused spear_thermal_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
@@ -72,7 +71,7 @@ static int spear_thermal_suspend(struct device *dev)
        return 0;
 }
 
-static int spear_thermal_resume(struct device *dev)
+static int __maybe_unused spear_thermal_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
@@ -94,7 +93,6 @@ static int spear_thermal_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(spear_thermal_pm_ops, spear_thermal_suspend,
                spear_thermal_resume);
index b3110040164ae64fa29e66fae2d7f5bd4d7d139f..2348fa6137070e19c19d97a5dc436b1a0b762441 100644 (file)
@@ -681,7 +681,14 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
 /* this is called once with whichever end is closed last */
 static void pty_unix98_shutdown(struct tty_struct *tty)
 {
-       devpts_kill_index(tty->driver_data, tty->index);
+       struct inode *ptmx_inode;
+
+       if (tty->driver->subtype == PTY_TYPE_MASTER)
+               ptmx_inode = tty->driver_data;
+       else
+               ptmx_inode = tty->link->driver_data;
+       devpts_kill_index(ptmx_inode, tty->index);
+       devpts_del_ref(ptmx_inode);
 }
 
 static const struct tty_operations ptm_unix98_ops = {
@@ -773,6 +780,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)
        set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
        tty->driver_data = inode;
 
+       /*
+        * In the case where all references to ptmx inode are dropped and we
+        * still have /dev/tty opened pointing to the master/slave pair (ptmx
+        * is closed/released before /dev/tty), we must make sure that the inode
+        * is still valid when we call the final pty_unix98_shutdown, thus we
+        * hold an additional reference to the ptmx inode. For the same /dev/tty
+        * last close case, we also need to make sure the super_block isn't
+        * destroyed (devpts instance unmounted), before /dev/tty is closed and
+        * on its release devpts_kill_index is called.
+        */
+       devpts_add_ref(inode);
+
        tty_add_file(tty, filp);
 
        slave_inode = devpts_pty_new(inode,
index e71ec78fc11ea1ab074486c8876fa855337564fb..7cd6f9a9054212d905e808bcfba2d76d676aaae2 100644 (file)
@@ -1941,6 +1941,7 @@ pci_wch_ch38x_setup(struct serial_private *priv,
 #define PCIE_VENDOR_ID_WCH             0x1c00
 #define PCIE_DEVICE_ID_WCH_CH382_2S1P  0x3250
 #define PCIE_DEVICE_ID_WCH_CH384_4S    0x3470
+#define PCIE_DEVICE_ID_WCH_CH382_2S    0x3253
 
 #define PCI_VENDOR_ID_PERICOM                  0x12D8
 #define PCI_DEVICE_ID_PERICOM_PI7C9X7951       0x7951
@@ -2637,6 +2638,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_wch_ch353_setup,
        },
+       /* WCH CH382 2S card (16850 clone) */
+       {
+               .vendor         = PCIE_VENDOR_ID_WCH,
+               .device         = PCIE_DEVICE_ID_WCH_CH382_2S,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_wch_ch38x_setup,
+       },
        /* WCH CH382 2S1P card (16850 clone) */
        {
                .vendor         = PCIE_VENDOR_ID_WCH,
@@ -2955,6 +2964,7 @@ enum pci_board_num_t {
        pbn_fintek_4,
        pbn_fintek_8,
        pbn_fintek_12,
+       pbn_wch382_2,
        pbn_wch384_4,
        pbn_pericom_PI7C9X7951,
        pbn_pericom_PI7C9X7952,
@@ -3775,6 +3785,13 @@ static struct pciserial_board pci_boards[] = {
                .base_baud      = 115200,
                .first_offset   = 0x40,
        },
+       [pbn_wch382_2] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 115200,
+               .uart_offset    = 8,
+               .first_offset   = 0xC0,
+       },
        [pbn_wch384_4] = {
                .flags          = FL_BASE0,
                .num_ports      = 4,
@@ -5574,6 +5591,10 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID,
                0, 0, pbn_b0_bt_2_115200 },
 
+       {       PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_wch382_2 },
+
        {       PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
                PCI_ANY_ID, PCI_ANY_ID,
                0, 0, pbn_wch384_4 },
index b645f9228ed77b90ac6d4791e1b0ab27056a066b..fa49eb1e2fa2429f1c162d1464d06fb727a91d1c 100644 (file)
@@ -1165,7 +1165,7 @@ serial_omap_type(struct uart_port *port)
 
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
-static void wait_for_xmitr(struct uart_omap_port *up)
+static void __maybe_unused wait_for_xmitr(struct uart_omap_port *up)
 {
        unsigned int status, tmout = 10000;
 
@@ -1343,7 +1343,7 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up)
 
 /* Enable or disable the rs485 support */
 static int
-serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
+serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
 {
        struct uart_omap_port *up = to_uart_omap_port(port);
        unsigned int mode;
@@ -1356,8 +1356,12 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
        up->ier = 0;
        serial_out(up, UART_IER, 0);
 
+       /* Clamp the delays to [0, 100ms] */
+       rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
+       rs485->delay_rts_after_send  = min(rs485->delay_rts_after_send, 100U);
+
        /* store new config */
-       port->rs485 = *rs485conf;
+       port->rs485 = *rs485;
 
        /*
         * Just as a precaution, only allow rs485
index 5cec01c75691a6b7ee58ea65346c05572db1bab1..a7eacef1bd2216ef697c12d046cb8975f9fefb20 100644 (file)
@@ -2066,13 +2066,12 @@ retry_open:
                if (tty) {
                        mutex_unlock(&tty_mutex);
                        retval = tty_lock_interruptible(tty);
+                       tty_kref_put(tty);  /* drop kref from tty_driver_lookup_tty() */
                        if (retval) {
                                if (retval == -EINTR)
                                        retval = -ERESTARTSYS;
                                goto err_unref;
                        }
-                       /* safe to drop the kref from tty_driver_lookup_tty() */
-                       tty_kref_put(tty);
                        retval = tty_reopen(tty);
                        if (retval < 0) {
                                tty_unlock(tty);
index d2f3c4cd697f5cd2bae639fd4d88009af5e2733b..dfa9ec03fa8e06dfe03a6e0ae04c62a2ac774103 100644 (file)
@@ -21,10 +21,15 @@ EXPORT_SYMBOL(tty_lock);
 
 int tty_lock_interruptible(struct tty_struct *tty)
 {
+       int ret;
+
        if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
                return -EIO;
        tty_kref_get(tty);
-       return mutex_lock_interruptible(&tty->legacy_mutex);
+       ret = mutex_lock_interruptible(&tty->legacy_mutex);
+       if (ret)
+               tty_kref_put(tty);
+       return ret;
 }
 
 void __lockfunc tty_unlock(struct tty_struct *tty)
index b59195edf63634a3be94bcd3dc9ede6d87699185..b635ab67490de3a93a9c0df0f17848376ae1d947 100644 (file)
@@ -85,8 +85,8 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
 
        /* register a nop PHY */
        ci->phy = usb_phy_generic_register();
-       if (!ci->phy)
-               return -ENOMEM;
+       if (IS_ERR(ci->phy))
+               return PTR_ERR(ci->phy);
 
        memset(res, 0, sizeof(res));
        res[0].start    = pci_resource_start(pdev, 0);
index a4f7db2e18ddc295fc4ff1a0cad99bc1ff8b04bd..df47110bad2d6f277b3893bf48657ecfde165fcf 100644 (file)
@@ -100,6 +100,9 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
        if (sscanf(buf, "%u", &mode) != 1)
                return -EINVAL;
 
+       if (mode > 255)
+               return -EBADRQC;
+
        pm_runtime_get_sync(ci->dev);
        spin_lock_irqsave(&ci->lock, flags);
        ret = hw_port_test_set(ci, mode);
index 45f86da1d6d37b4650ddfaf216879195ca9c6542..03b6743461d15de129a2d7908e851db450111d3c 100644 (file)
@@ -158,7 +158,7 @@ static void ci_otg_work(struct work_struct *work)
 int ci_hdrc_otg_init(struct ci_hdrc *ci)
 {
        INIT_WORK(&ci->work, ci_otg_work);
-       ci->wq = create_singlethread_workqueue("ci_otg");
+       ci->wq = create_freezable_workqueue("ci_otg");
        if (!ci->wq) {
                dev_err(ci->dev, "can't create workqueue\n");
                return -ENODEV;
index 350dcd9af5d86eb2181e6cc8f77f25a33f712cce..51b436918f7892b1249c7ec1b19dad515a9a5755 100644 (file)
@@ -5401,6 +5401,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
        }
 
        bos = udev->bos;
+       udev->bos = NULL;
 
        for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
@@ -5493,11 +5494,8 @@ done:
        usb_set_usb2_hardware_lpm(udev, 1);
        usb_unlocked_enable_lpm(udev);
        usb_enable_ltm(udev);
-       /* release the new BOS descriptor allocated  by hub_port_init() */
-       if (udev->bos != bos) {
-               usb_release_bos_descriptor(udev);
-               udev->bos = bos;
-       }
+       usb_release_bos_descriptor(udev);
+       udev->bos = bos;
        return 0;
 
 re_enumerate:
index fd95ba6ec317fdacb13478d84c4157656893740c..f0decc0d69b5197d183c29ec16882a8fcc18208e 100644 (file)
@@ -1,5 +1,6 @@
 config USB_DWC2
        tristate "DesignWare USB2 DRD Core Support"
+       depends on HAS_DMA
        depends on USB || USB_GADGET
        help
          Say Y here if your system has a Dual Role Hi-Speed USB
index e991d55914db649804a6357821f42e78355e6e5b..46c4ba75dc2afdb744bd32fbf047949ff50ec1fd 100644 (file)
@@ -619,6 +619,12 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
                         __func__, hsotg->dr_mode);
                break;
        }
+
+       /*
+        * NOTE: This is required for some rockchip soc based
+        * platforms.
+        */
+       msleep(50);
 }
 
 /*
index 36606fc33c0d31f0ed52d85bc626f3fe29e36099..a41274aa52adc5f8e1119544a90e8f79c421c2b5 100644 (file)
@@ -1174,14 +1174,11 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
        failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc,
                                                     halt_status, n_bytes,
                                                     xfer_done);
-       if (*xfer_done && urb->status != -EINPROGRESS)
-               failed = 1;
-
-       if (failed) {
+       if (failed || (*xfer_done && urb->status != -EINPROGRESS)) {
                dwc2_host_complete(hsotg, qtd, urb->status);
                dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
-               dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n",
-                        failed, *xfer_done, urb->status);
+               dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n",
+                        failed, *xfer_done);
                return failed;
        }
 
@@ -1236,21 +1233,23 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
 
        list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) {
                int i;
+               int qtd_desc_count;
 
                qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry);
                xfer_done = 0;
+               qtd_desc_count = qtd->n_desc;
 
-               for (i = 0; i < qtd->n_desc; i++) {
+               for (i = 0; i < qtd_desc_count; i++) {
                        if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd,
                                                       desc_num, halt_status,
-                                                      &xfer_done)) {
-                               qtd = NULL;
-                               break;
-                       }
+                                                      &xfer_done))
+                               goto stop_scan;
+
                        desc_num++;
                }
        }
 
+stop_scan:
        if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) {
                /*
                 * Resetting the data toggle for bulk and interrupt endpoints
@@ -1258,7 +1257,7 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
                 */
                if (halt_status == DWC2_HC_XFER_STALL)
                        qh->data_toggle = DWC2_HC_PID_DATA0;
-               else if (qtd)
+               else
                        dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
        }
 
index f8253803a0507543f617af6e2aacc266b43762de..cadba8b13c4837d3e7a3432a3909d69239a70c5d 100644 (file)
@@ -525,11 +525,19 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
        u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT;
 
        if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) {
+               if (WARN(!chan || !chan->qh,
+                        "chan->qh must be specified for non-control eps\n"))
+                       return;
+
                if (pid == TSIZ_SC_MC_PID_DATA0)
                        chan->qh->data_toggle = DWC2_HC_PID_DATA0;
                else
                        chan->qh->data_toggle = DWC2_HC_PID_DATA1;
        } else {
+               if (WARN(!qtd,
+                        "qtd must be specified for control eps\n"))
+                       return;
+
                if (pid == TSIZ_SC_MC_PID_DATA0)
                        qtd->data_toggle = DWC2_HC_PID_DATA0;
                else
index 29130682e547e568fb92e32734dbf0141a5e1bef..e4f8b90d9627f9baed5fe4f7fd6dcac7963f49f5 100644 (file)
@@ -856,7 +856,6 @@ struct dwc3 {
        unsigned                pullups_connected:1;
        unsigned                resize_fifos:1;
        unsigned                setup_packet_pending:1;
-       unsigned                start_config_issued:1;
        unsigned                three_stage_setup:1;
        unsigned                usb3_lpm_capable:1;
 
index 3a9354abcb68bfc6e9d27cc64c7155d54dec04e0..8d6b75c2f53b2e0d0991ca3dddc784f6dccecadb 100644 (file)
@@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        int ret;
        u32 reg;
 
-       dwc->start_config_issued = false;
        cfg = le16_to_cpu(ctrl->wValue);
 
        switch (state) {
@@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
                dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
                ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
                break;
-       case USB_REQ_SET_INTERFACE:
-               dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
-               dwc->start_config_issued = false;
-               /* Fall through */
        default:
                dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
index 7d1dd82a95ac7325c3da0b45d0d855a31f7f9965..2363bad45af865dd2e7ee0c28e009fff1ae7a7d5 100644 (file)
@@ -385,24 +385,66 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
        dep->trb_pool_dma = 0;
 }
 
+static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep);
+
+/**
+ * dwc3_gadget_start_config - Configure EP resources
+ * @dwc: pointer to our controller context structure
+ * @dep: endpoint that is being enabled
+ *
+ * The assignment of transfer resources cannot perfectly follow the
+ * data book due to the fact that the controller driver does not have
+ * all knowledge of the configuration in advance. It is given this
+ * information piecemeal by the composite gadget framework after every
+ * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook
+ * programming model in this scenario can cause errors. For two
+ * reasons:
+ *
+ * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION
+ * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of
+ * multiple interfaces.
+ *
+ * 2) The databook does not mention doing more DEPXFERCFG for new
+ * endpoint on alt setting (8.1.6).
+ *
+ * The following simplified method is used instead:
+ *
+ * All hardware endpoints can be assigned a transfer resource and this
+ * setting will stay persistent until either a core reset or
+ * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and
+ * do DEPXFERCFG for every hardware endpoint as well. We are
+ * guaranteed that there are as many transfer resources as endpoints.
+ *
+ * This function is called for each endpoint when it is being enabled
+ * but is triggered only when called for EP0-out, which always happens
+ * first, and which should only happen in one of the above conditions.
+ */
 static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
        struct dwc3_gadget_ep_cmd_params params;
        u32                     cmd;
+       int                     i;
+       int                     ret;
+
+       if (dep->number)
+               return 0;
 
        memset(&params, 0x00, sizeof(params));
+       cmd = DWC3_DEPCMD_DEPSTARTCFG;
 
-       if (dep->number != 1) {
-               cmd = DWC3_DEPCMD_DEPSTARTCFG;
-               /* XferRscIdx == 0 for ep0 and 2 for the remaining */
-               if (dep->number > 1) {
-                       if (dwc->start_config_issued)
-                               return 0;
-                       dwc->start_config_issued = true;
-                       cmd |= DWC3_DEPCMD_PARAM(2);
-               }
+       ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
+       if (ret)
+               return ret;
 
-               return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
+       for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) {
+               struct dwc3_ep *dep = dwc->eps[i];
+
+               if (!dep)
+                       continue;
+
+               ret = dwc3_gadget_set_xfer_resource(dwc, dep);
+               if (ret)
+                       return ret;
        }
 
        return 0;
@@ -516,10 +558,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
                struct dwc3_trb *trb_st_hw;
                struct dwc3_trb *trb_link;
 
-               ret = dwc3_gadget_set_xfer_resource(dwc, dep);
-               if (ret)
-                       return ret;
-
                dep->endpoint.desc = desc;
                dep->comp_desc = comp_desc;
                dep->type = usb_endpoint_type(desc);
@@ -1636,8 +1674,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        }
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
-       dwc->start_config_issued = false;
-
        /* Start with SuperSpeed Default */
        dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
@@ -2237,7 +2273,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
        dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
        dwc3_disconnect_gadget(dwc);
-       dwc->start_config_issued = false;
 
        dwc->gadget.speed = USB_SPEED_UNKNOWN;
        dwc->setup_packet_pending = false;
@@ -2288,7 +2323,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 
        dwc3_stop_active_transfers(dwc);
        dwc3_clear_stall_all_ep(dwc);
-       dwc->start_config_issued = false;
 
        /* Reset device address to zero */
        reg = dwc3_readl(dwc->regs, DWC3_DCFG);
index 7e179f81d05cae3e91fd8b976a1f2665e3958cc3..87fb0fd6aaabea260758ba338769d6be70472740 100644 (file)
@@ -130,7 +130,8 @@ struct dev_data {
                                        setup_can_stall : 1,
                                        setup_out_ready : 1,
                                        setup_out_error : 1,
-                                       setup_abort : 1;
+                                       setup_abort : 1,
+                                       gadget_registered : 1;
        unsigned                        setup_wLength;
 
        /* the rest is basically write-once */
@@ -1179,7 +1180,8 @@ dev_release (struct inode *inode, struct file *fd)
 
        /* closing ep0 === shutdown all */
 
-       usb_gadget_unregister_driver (&gadgetfs_driver);
+       if (dev->gadget_registered)
+               usb_gadget_unregister_driver (&gadgetfs_driver);
 
        /* at this point "good" hardware has disconnected the
         * device from USB; the host won't see it any more.
@@ -1847,6 +1849,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                 * kick in after the ep0 descriptor is closed.
                 */
                value = len;
+               dev->gadget_registered = true;
        }
        return value;
 
index 53c0692f1b096eef837624bda521a11ad3181fc4..93d28cb00b76f15de7f281f465a1c791aa7edbbe 100644 (file)
@@ -2340,7 +2340,7 @@ static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
 {
        struct qe_udc *udc;
        struct device_node *np = ofdev->dev.of_node;
-       unsigned int tmp_addr = 0;
+       unsigned long tmp_addr = 0;
        struct usb_device_para __iomem *usbpram;
        unsigned int i;
        u64 size;
index 4dff60d34f732097752e59360e0edcf7e5eb90b4..0d32052bf16f90d5e1ace964cedd484c14a6f65d 100644 (file)
@@ -369,9 +369,20 @@ static inline void set_max_speed(struct net2280_ep *ep, u32 max)
        static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80,
                                          0x50, 0x20, 0x70, 0x40, 0x90 };
 
-       if (ep->dev->enhanced_mode)
+       if (ep->dev->enhanced_mode) {
                reg = ep_enhanced[ep->num];
-       else{
+               switch (ep->dev->gadget.speed) {
+               case USB_SPEED_SUPER:
+                       reg += 2;
+                       break;
+               case USB_SPEED_FULL:
+                       reg += 1;
+                       break;
+               case USB_SPEED_HIGH:
+               default:
+                       break;
+               }
+       } else {
                reg = (ep->num + 1) * 0x10;
                if (ep->dev->gadget.speed != USB_SPEED_HIGH)
                        reg += 1;
index fd73a3ea07c20e4cac1100be1883dce5ea81c033..b86a6f03592ec9e1d42f5bdc813b83c1297b6e52 100644 (file)
@@ -413,9 +413,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
                if (!driver->udc_name || strcmp(driver->udc_name,
                                                dev_name(&udc->dev)) == 0) {
                        ret = udc_bind_to_driver(udc, driver);
+                       if (ret != -EPROBE_DEFER)
+                               list_del(&driver->pending);
                        if (ret)
                                goto err4;
-                       list_del(&driver->pending);
                        break;
                }
        }
index 795a45b1b25bacb016552b4d0635166965ebfce6..58487a4735218518ce50326750ca8718aaa2a516 100644 (file)
@@ -662,7 +662,7 @@ static int musb_tx_dma_set_mode_mentor(struct dma_controller *dma,
                csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
                csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
        }
-       channel->desired_mode = mode;
+       channel->desired_mode = *mode;
        musb_writew(epio, MUSB_TXCSR, csr);
 
        return 0;
@@ -2003,10 +2003,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
                                qh->offset,
                                urb->transfer_buffer_length);
 
-                       done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh,
-                                                             urb, xfer_len,
-                                                             iso_err);
-                       if (done)
+                       if (musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, urb,
+                                                          xfer_len, iso_err))
                                goto finish;
                        else
                                dev_err(musb->controller, "error: rx_dma failed\n");
index 970a30e155cb51bfd1d15126d8cdc65f9adf579c..72b387d592c278eafb5a73e519482b405d921e39 100644 (file)
@@ -757,14 +757,8 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
        otg->host = host;
        dev_dbg(otg->usb_phy->dev, "host driver registered w/ tranceiver\n");
 
-       /*
-        * Kick the state machine work, if peripheral is not supported
-        * or peripheral is already registered with us.
-        */
-       if (motg->pdata->mode == USB_DR_MODE_HOST || otg->gadget) {
-               pm_runtime_get_sync(otg->usb_phy->dev);
-               schedule_work(&motg->sm_work);
-       }
+       pm_runtime_get_sync(otg->usb_phy->dev);
+       schedule_work(&motg->sm_work);
 
        return 0;
 }
@@ -827,14 +821,8 @@ static int msm_otg_set_peripheral(struct usb_otg *otg,
        dev_dbg(otg->usb_phy->dev,
                "peripheral driver registered w/ tranceiver\n");
 
-       /*
-        * Kick the state machine work, if host is not supported
-        * or host is already registered with us.
-        */
-       if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL || otg->host) {
-               pm_runtime_get_sync(otg->usb_phy->dev);
-               schedule_work(&motg->sm_work);
-       }
+       pm_runtime_get_sync(otg->usb_phy->dev);
+       schedule_work(&motg->sm_work);
 
        return 0;
 }
index f612dda9c9778aaf78da02d7422f2d73a14818c2..56ecb8b5115dd66b8d0db52849e9738e127a2afa 100644 (file)
@@ -475,22 +475,6 @@ config USB_SERIAL_MOS7840
          To compile this driver as a module, choose M here: the
          module will be called mos7840.  If unsure, choose N.
 
-config USB_SERIAL_MXUPORT11
-       tristate "USB Moxa UPORT 11x0 Serial Driver"
-       ---help---
-         Say Y here if you want to use a MOXA UPort 11x0 Serial hub.
-
-         This driver supports:
-
-         - UPort 1110  : 1 port RS-232 USB to Serial Hub.
-         - UPort 1130  : 1 port RS-422/485 USB to Serial Hub.
-         - UPort 1130I : 1 port RS-422/485 USB to Serial Hub with Isolation.
-         - UPort 1150  : 1 port RS-232/422/485 USB to Serial Hub.
-         - UPort 1150I : 1 port RS-232/422/485 USB to Serial Hub with Isolation.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mxu11x0.
-
 config USB_SERIAL_MXUPORT
        tristate "USB Moxa UPORT Serial Driver"
        ---help---
index f3fa5e53702d869faa08cb7c2b05e03beae85390..349d9df0895f5afc4139b046383362bc46348739 100644 (file)
@@ -38,7 +38,6 @@ obj-$(CONFIG_USB_SERIAL_METRO)                        += metro-usb.o
 obj-$(CONFIG_USB_SERIAL_MOS7720)               += mos7720.o
 obj-$(CONFIG_USB_SERIAL_MOS7840)               += mos7840.o
 obj-$(CONFIG_USB_SERIAL_MXUPORT)               += mxuport.o
-obj-$(CONFIG_USB_SERIAL_MXUPORT11)             += mxu11x0.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)                        += navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTICON)               += opticon.o
index 987813b8a7f91e27b6a582a44ca88254dbd49c13..73a366de5102ada85dbf9539c75a9bb70ddaf4fd 100644 (file)
@@ -163,6 +163,9 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
        { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+       { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
+       { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
+       { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
        { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
        { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
        { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
diff --git a/drivers/usb/serial/mxu11x0.c b/drivers/usb/serial/mxu11x0.c
deleted file mode 100644 (file)
index 6196073..0000000
+++ /dev/null
@@ -1,1006 +0,0 @@
-/*
- * USB Moxa UPORT 11x0 Serial Driver
- *
- * Copyright (C) 2007 MOXA Technologies Co., Ltd.
- * Copyright (C) 2015 Mathieu Othacehe <m.othacehe@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- *
- * Supports the following Moxa USB to serial converters:
- *  UPort 1110,  1 port RS-232 USB to Serial Hub.
- *  UPort 1130,  1 port RS-422/485 USB to Serial Hub.
- *  UPort 1130I, 1 port RS-422/485 USB to Serial Hub with isolation
- *    protection.
- *  UPort 1150,  1 port RS-232/422/485 USB to Serial Hub.
- *  UPort 1150I, 1 port RS-232/422/485 USB to Serial Hub with isolation
- *  protection.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/jiffies.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-/* Vendor and product ids */
-#define MXU1_VENDOR_ID                         0x110a
-#define MXU1_1110_PRODUCT_ID                   0x1110
-#define MXU1_1130_PRODUCT_ID                   0x1130
-#define MXU1_1150_PRODUCT_ID                   0x1150
-#define MXU1_1151_PRODUCT_ID                   0x1151
-#define MXU1_1131_PRODUCT_ID                   0x1131
-
-/* Commands */
-#define MXU1_GET_VERSION                       0x01
-#define MXU1_GET_PORT_STATUS                   0x02
-#define MXU1_GET_PORT_DEV_INFO                 0x03
-#define MXU1_GET_CONFIG                                0x04
-#define MXU1_SET_CONFIG                                0x05
-#define MXU1_OPEN_PORT                         0x06
-#define MXU1_CLOSE_PORT                                0x07
-#define MXU1_START_PORT                                0x08
-#define MXU1_STOP_PORT                         0x09
-#define MXU1_TEST_PORT                         0x0A
-#define MXU1_PURGE_PORT                                0x0B
-#define MXU1_RESET_EXT_DEVICE                  0x0C
-#define MXU1_GET_OUTQUEUE                      0x0D
-#define MXU1_WRITE_DATA                                0x80
-#define MXU1_READ_DATA                         0x81
-#define MXU1_REQ_TYPE_CLASS                    0x82
-
-/* Module identifiers */
-#define MXU1_I2C_PORT                          0x01
-#define MXU1_IEEE1284_PORT                     0x02
-#define MXU1_UART1_PORT                                0x03
-#define MXU1_UART2_PORT                                0x04
-#define MXU1_RAM_PORT                          0x05
-
-/* Modem status */
-#define MXU1_MSR_DELTA_CTS                     0x01
-#define MXU1_MSR_DELTA_DSR                     0x02
-#define MXU1_MSR_DELTA_RI                      0x04
-#define MXU1_MSR_DELTA_CD                      0x08
-#define MXU1_MSR_CTS                           0x10
-#define MXU1_MSR_DSR                           0x20
-#define MXU1_MSR_RI                            0x40
-#define MXU1_MSR_CD                            0x80
-#define MXU1_MSR_DELTA_MASK                    0x0F
-#define MXU1_MSR_MASK                          0xF0
-
-/* Line status */
-#define MXU1_LSR_OVERRUN_ERROR                 0x01
-#define MXU1_LSR_PARITY_ERROR                  0x02
-#define MXU1_LSR_FRAMING_ERROR                 0x04
-#define MXU1_LSR_BREAK                         0x08
-#define MXU1_LSR_ERROR                         0x0F
-#define MXU1_LSR_RX_FULL                       0x10
-#define MXU1_LSR_TX_EMPTY                      0x20
-
-/* Modem control */
-#define MXU1_MCR_LOOP                          0x04
-#define MXU1_MCR_DTR                           0x10
-#define MXU1_MCR_RTS                           0x20
-
-/* Mask settings */
-#define MXU1_UART_ENABLE_RTS_IN                        0x0001
-#define MXU1_UART_DISABLE_RTS                  0x0002
-#define MXU1_UART_ENABLE_PARITY_CHECKING       0x0008
-#define MXU1_UART_ENABLE_DSR_OUT               0x0010
-#define MXU1_UART_ENABLE_CTS_OUT               0x0020
-#define MXU1_UART_ENABLE_X_OUT                 0x0040
-#define MXU1_UART_ENABLE_XA_OUT                        0x0080
-#define MXU1_UART_ENABLE_X_IN                  0x0100
-#define MXU1_UART_ENABLE_DTR_IN                        0x0800
-#define MXU1_UART_DISABLE_DTR                  0x1000
-#define MXU1_UART_ENABLE_MS_INTS               0x2000
-#define MXU1_UART_ENABLE_AUTO_START_DMA                0x4000
-#define MXU1_UART_SEND_BREAK_SIGNAL            0x8000
-
-/* Parity */
-#define MXU1_UART_NO_PARITY                    0x00
-#define MXU1_UART_ODD_PARITY                   0x01
-#define MXU1_UART_EVEN_PARITY                  0x02
-#define MXU1_UART_MARK_PARITY                  0x03
-#define MXU1_UART_SPACE_PARITY                 0x04
-
-/* Stop bits */
-#define MXU1_UART_1_STOP_BITS                  0x00
-#define MXU1_UART_1_5_STOP_BITS                        0x01
-#define MXU1_UART_2_STOP_BITS                  0x02
-
-/* Bits per character */
-#define MXU1_UART_5_DATA_BITS                  0x00
-#define MXU1_UART_6_DATA_BITS                  0x01
-#define MXU1_UART_7_DATA_BITS                  0x02
-#define MXU1_UART_8_DATA_BITS                  0x03
-
-/* Operation modes */
-#define MXU1_UART_232                          0x00
-#define MXU1_UART_485_RECEIVER_DISABLED                0x01
-#define MXU1_UART_485_RECEIVER_ENABLED         0x02
-
-/* Pipe transfer mode and timeout */
-#define MXU1_PIPE_MODE_CONTINUOUS              0x01
-#define MXU1_PIPE_MODE_MASK                    0x03
-#define MXU1_PIPE_TIMEOUT_MASK                 0x7C
-#define MXU1_PIPE_TIMEOUT_ENABLE               0x80
-
-/* Config struct */
-struct mxu1_uart_config {
-       __be16  wBaudRate;
-       __be16  wFlags;
-       u8      bDataBits;
-       u8      bParity;
-       u8      bStopBits;
-       char    cXon;
-       char    cXoff;
-       u8      bUartMode;
-} __packed;
-
-/* Purge modes */
-#define MXU1_PURGE_OUTPUT                      0x00
-#define MXU1_PURGE_INPUT                       0x80
-
-/* Read/Write data */
-#define MXU1_RW_DATA_ADDR_SFR                  0x10
-#define MXU1_RW_DATA_ADDR_IDATA                        0x20
-#define MXU1_RW_DATA_ADDR_XDATA                        0x30
-#define MXU1_RW_DATA_ADDR_CODE                 0x40
-#define MXU1_RW_DATA_ADDR_GPIO                 0x50
-#define MXU1_RW_DATA_ADDR_I2C                  0x60
-#define MXU1_RW_DATA_ADDR_FLASH                        0x70
-#define MXU1_RW_DATA_ADDR_DSP                  0x80
-
-#define MXU1_RW_DATA_UNSPECIFIED               0x00
-#define MXU1_RW_DATA_BYTE                      0x01
-#define MXU1_RW_DATA_WORD                      0x02
-#define MXU1_RW_DATA_DOUBLE_WORD               0x04
-
-struct mxu1_write_data_bytes {
-       u8      bAddrType;
-       u8      bDataType;
-       u8      bDataCounter;
-       __be16  wBaseAddrHi;
-       __be16  wBaseAddrLo;
-       u8      bData[0];
-} __packed;
-
-/* Interrupt codes */
-#define MXU1_CODE_HARDWARE_ERROR               0xFF
-#define MXU1_CODE_DATA_ERROR                   0x03
-#define MXU1_CODE_MODEM_STATUS                 0x04
-
-static inline int mxu1_get_func_from_code(unsigned char code)
-{
-       return code & 0x0f;
-}
-
-/* Download firmware max packet size */
-#define MXU1_DOWNLOAD_MAX_PACKET_SIZE          64
-
-/* Firmware image header */
-struct mxu1_firmware_header {
-       __le16 wLength;
-       u8 bCheckSum;
-} __packed;
-
-#define MXU1_UART_BASE_ADDR        0xFFA0
-#define MXU1_UART_OFFSET_MCR       0x0004
-
-#define MXU1_BAUD_BASE              923077
-
-#define MXU1_TRANSFER_TIMEOUT      2
-#define MXU1_DOWNLOAD_TIMEOUT       1000
-#define MXU1_DEFAULT_CLOSING_WAIT   4000 /* in .01 secs */
-
-struct mxu1_port {
-       u8 msr;
-       u8 mcr;
-       u8 uart_mode;
-       spinlock_t spinlock; /* Protects msr */
-       struct mutex mutex; /* Protects mcr */
-       bool send_break;
-};
-
-struct mxu1_device {
-       u16 mxd_model;
-};
-
-static const struct usb_device_id mxu1_idtable[] = {
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1110_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1130_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) },
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, mxu1_idtable);
-
-/* Write the given buffer out to the control pipe.  */
-static int mxu1_send_ctrl_data_urb(struct usb_serial *serial,
-                                  u8 request,
-                                  u16 value, u16 index,
-                                  void *data, size_t size)
-{
-       int status;
-
-       status = usb_control_msg(serial->dev,
-                                usb_sndctrlpipe(serial->dev, 0),
-                                request,
-                                (USB_DIR_OUT | USB_TYPE_VENDOR |
-                                 USB_RECIP_DEVICE), value, index,
-                                data, size,
-                                USB_CTRL_SET_TIMEOUT);
-       if (status < 0) {
-               dev_err(&serial->interface->dev,
-                       "%s - usb_control_msg failed: %d\n",
-                       __func__, status);
-               return status;
-       }
-
-       if (status != size) {
-               dev_err(&serial->interface->dev,
-                       "%s - short write (%d / %zd)\n",
-                       __func__, status, size);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/* Send a vendor request without any data */
-static int mxu1_send_ctrl_urb(struct usb_serial *serial,
-                             u8 request, u16 value, u16 index)
-{
-       return mxu1_send_ctrl_data_urb(serial, request, value, index,
-                                      NULL, 0);
-}
-
-static int mxu1_download_firmware(struct usb_serial *serial,
-                                 const struct firmware *fw_p)
-{
-       int status = 0;
-       int buffer_size;
-       int pos;
-       int len;
-       int done;
-       u8 cs = 0;
-       u8 *buffer;
-       struct usb_device *dev = serial->dev;
-       struct mxu1_firmware_header *header;
-       unsigned int pipe;
-
-       pipe = usb_sndbulkpipe(dev, serial->port[0]->bulk_out_endpointAddress);
-
-       buffer_size = fw_p->size + sizeof(*header);
-       buffer = kmalloc(buffer_size, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       memcpy(buffer, fw_p->data, fw_p->size);
-       memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
-
-       for (pos = sizeof(*header); pos < buffer_size; pos++)
-               cs = (u8)(cs + buffer[pos]);
-
-       header = (struct mxu1_firmware_header *)buffer;
-       header->wLength = cpu_to_le16(buffer_size - sizeof(*header));
-       header->bCheckSum = cs;
-
-       dev_dbg(&dev->dev, "%s - downloading firmware\n", __func__);
-
-       for (pos = 0; pos < buffer_size; pos += done) {
-               len = min(buffer_size - pos, MXU1_DOWNLOAD_MAX_PACKET_SIZE);
-
-               status = usb_bulk_msg(dev, pipe, buffer + pos, len, &done,
-                               MXU1_DOWNLOAD_TIMEOUT);
-               if (status)
-                       break;
-       }
-
-       kfree(buffer);
-
-       if (status) {
-               dev_err(&dev->dev, "failed to download firmware: %d\n", status);
-               return status;
-       }
-
-       msleep_interruptible(100);
-       usb_reset_device(dev);
-
-       dev_dbg(&dev->dev, "%s - download successful\n", __func__);
-
-       return 0;
-}
-
-static int mxu1_port_probe(struct usb_serial_port *port)
-{
-       struct mxu1_port *mxport;
-       struct mxu1_device *mxdev;
-
-       if (!port->interrupt_in_urb) {
-               dev_err(&port->dev, "no interrupt urb\n");
-               return -ENODEV;
-       }
-
-       mxport = kzalloc(sizeof(struct mxu1_port), GFP_KERNEL);
-       if (!mxport)
-               return -ENOMEM;
-
-       spin_lock_init(&mxport->spinlock);
-       mutex_init(&mxport->mutex);
-
-       mxdev = usb_get_serial_data(port->serial);
-
-       switch (mxdev->mxd_model) {
-       case MXU1_1110_PRODUCT_ID:
-       case MXU1_1150_PRODUCT_ID:
-       case MXU1_1151_PRODUCT_ID:
-               mxport->uart_mode = MXU1_UART_232;
-               break;
-       case MXU1_1130_PRODUCT_ID:
-       case MXU1_1131_PRODUCT_ID:
-               mxport->uart_mode = MXU1_UART_485_RECEIVER_DISABLED;
-               break;
-       }
-
-       usb_set_serial_port_data(port, mxport);
-
-       port->port.closing_wait =
-                       msecs_to_jiffies(MXU1_DEFAULT_CLOSING_WAIT * 10);
-       port->port.drain_delay = 1;
-
-       return 0;
-}
-
-static int mxu1_port_remove(struct usb_serial_port *port)
-{
-       struct mxu1_port *mxport;
-
-       mxport = usb_get_serial_port_data(port);
-       kfree(mxport);
-
-       return 0;
-}
-
-static int mxu1_startup(struct usb_serial *serial)
-{
-       struct mxu1_device *mxdev;
-       struct usb_device *dev = serial->dev;
-       struct usb_host_interface *cur_altsetting;
-       char fw_name[32];
-       const struct firmware *fw_p = NULL;
-       int err;
-
-       dev_dbg(&serial->interface->dev, "%s - product 0x%04X, num configurations %d, configuration value %d\n",
-               __func__, le16_to_cpu(dev->descriptor.idProduct),
-               dev->descriptor.bNumConfigurations,
-               dev->actconfig->desc.bConfigurationValue);
-
-       /* create device structure */
-       mxdev = kzalloc(sizeof(struct mxu1_device), GFP_KERNEL);
-       if (!mxdev)
-               return -ENOMEM;
-
-       usb_set_serial_data(serial, mxdev);
-
-       mxdev->mxd_model = le16_to_cpu(dev->descriptor.idProduct);
-
-       cur_altsetting = serial->interface->cur_altsetting;
-
-       /* if we have only 1 configuration, download firmware */
-       if (cur_altsetting->desc.bNumEndpoints == 1) {
-
-               snprintf(fw_name,
-                        sizeof(fw_name),
-                        "moxa/moxa-%04x.fw",
-                        mxdev->mxd_model);
-
-               err = request_firmware(&fw_p, fw_name, &serial->interface->dev);
-               if (err) {
-                       dev_err(&serial->interface->dev, "failed to request firmware: %d\n",
-                               err);
-                       goto err_free_mxdev;
-               }
-
-               err = mxu1_download_firmware(serial, fw_p);
-               if (err)
-                       goto err_release_firmware;
-
-               /* device is being reset */
-               err = -ENODEV;
-               goto err_release_firmware;
-       }
-
-       return 0;
-
-err_release_firmware:
-       release_firmware(fw_p);
-err_free_mxdev:
-       kfree(mxdev);
-
-       return err;
-}
-
-static void mxu1_release(struct usb_serial *serial)
-{
-       struct mxu1_device *mxdev;
-
-       mxdev = usb_get_serial_data(serial);
-       kfree(mxdev);
-}
-
-static int mxu1_write_byte(struct usb_serial_port *port, u32 addr,
-                          u8 mask, u8 byte)
-{
-       int status;
-       size_t size;
-       struct mxu1_write_data_bytes *data;
-
-       dev_dbg(&port->dev, "%s - addr 0x%08X, mask 0x%02X, byte 0x%02X\n",
-               __func__, addr, mask, byte);
-
-       size = sizeof(struct mxu1_write_data_bytes) + 2;
-       data = kzalloc(size, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       data->bAddrType = MXU1_RW_DATA_ADDR_XDATA;
-       data->bDataType = MXU1_RW_DATA_BYTE;
-       data->bDataCounter = 1;
-       data->wBaseAddrHi = cpu_to_be16(addr >> 16);
-       data->wBaseAddrLo = cpu_to_be16(addr);
-       data->bData[0] = mask;
-       data->bData[1] = byte;
-
-       status = mxu1_send_ctrl_data_urb(port->serial, MXU1_WRITE_DATA, 0,
-                                        MXU1_RAM_PORT, data, size);
-       if (status < 0)
-               dev_err(&port->dev, "%s - failed: %d\n", __func__, status);
-
-       kfree(data);
-
-       return status;
-}
-
-static int mxu1_set_mcr(struct usb_serial_port *port, unsigned int mcr)
-{
-       int status;
-
-       status = mxu1_write_byte(port,
-                                MXU1_UART_BASE_ADDR + MXU1_UART_OFFSET_MCR,
-                                MXU1_MCR_RTS | MXU1_MCR_DTR | MXU1_MCR_LOOP,
-                                mcr);
-       return status;
-}
-
-static void mxu1_set_termios(struct tty_struct *tty,
-                            struct usb_serial_port *port,
-                            struct ktermios *old_termios)
-{
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       struct mxu1_uart_config *config;
-       tcflag_t cflag, iflag;
-       speed_t baud;
-       int status;
-       unsigned int mcr;
-
-       cflag = tty->termios.c_cflag;
-       iflag = tty->termios.c_iflag;
-
-       if (old_termios &&
-           !tty_termios_hw_change(&tty->termios, old_termios) &&
-           tty->termios.c_iflag == old_termios->c_iflag) {
-               dev_dbg(&port->dev, "%s - nothing to change\n", __func__);
-               return;
-       }
-
-       dev_dbg(&port->dev,
-               "%s - cflag 0x%08x, iflag 0x%08x\n", __func__, cflag, iflag);
-
-       if (old_termios) {
-               dev_dbg(&port->dev, "%s - old cflag 0x%08x, old iflag 0x%08x\n",
-                       __func__,
-                       old_termios->c_cflag,
-                       old_termios->c_iflag);
-       }
-
-       config = kzalloc(sizeof(*config), GFP_KERNEL);
-       if (!config)
-               return;
-
-       /* these flags must be set */
-       config->wFlags |= MXU1_UART_ENABLE_MS_INTS;
-       config->wFlags |= MXU1_UART_ENABLE_AUTO_START_DMA;
-       if (mxport->send_break)
-               config->wFlags |= MXU1_UART_SEND_BREAK_SIGNAL;
-       config->bUartMode = mxport->uart_mode;
-
-       switch (C_CSIZE(tty)) {
-       case CS5:
-               config->bDataBits = MXU1_UART_5_DATA_BITS;
-               break;
-       case CS6:
-               config->bDataBits = MXU1_UART_6_DATA_BITS;
-               break;
-       case CS7:
-               config->bDataBits = MXU1_UART_7_DATA_BITS;
-               break;
-       default:
-       case CS8:
-               config->bDataBits = MXU1_UART_8_DATA_BITS;
-               break;
-       }
-
-       if (C_PARENB(tty)) {
-               config->wFlags |= MXU1_UART_ENABLE_PARITY_CHECKING;
-               if (C_CMSPAR(tty)) {
-                       if (C_PARODD(tty))
-                               config->bParity = MXU1_UART_MARK_PARITY;
-                       else
-                               config->bParity = MXU1_UART_SPACE_PARITY;
-               } else {
-                       if (C_PARODD(tty))
-                               config->bParity = MXU1_UART_ODD_PARITY;
-                       else
-                               config->bParity = MXU1_UART_EVEN_PARITY;
-               }
-       } else {
-               config->bParity = MXU1_UART_NO_PARITY;
-       }
-
-       if (C_CSTOPB(tty))
-               config->bStopBits = MXU1_UART_2_STOP_BITS;
-       else
-               config->bStopBits = MXU1_UART_1_STOP_BITS;
-
-       if (C_CRTSCTS(tty)) {
-               /* RTS flow control must be off to drop RTS for baud rate B0 */
-               if (C_BAUD(tty) != B0)
-                       config->wFlags |= MXU1_UART_ENABLE_RTS_IN;
-               config->wFlags |= MXU1_UART_ENABLE_CTS_OUT;
-       }
-
-       if (I_IXOFF(tty) || I_IXON(tty)) {
-               config->cXon  = START_CHAR(tty);
-               config->cXoff = STOP_CHAR(tty);
-
-               if (I_IXOFF(tty))
-                       config->wFlags |= MXU1_UART_ENABLE_X_IN;
-
-               if (I_IXON(tty))
-                       config->wFlags |= MXU1_UART_ENABLE_X_OUT;
-       }
-
-       baud = tty_get_baud_rate(tty);
-       if (!baud)
-               baud = 9600;
-       config->wBaudRate = MXU1_BAUD_BASE / baud;
-
-       dev_dbg(&port->dev, "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n",
-               __func__, baud, config->wBaudRate, config->wFlags,
-               config->bDataBits, config->bParity, config->bStopBits,
-               config->cXon, config->cXoff, config->bUartMode);
-
-       cpu_to_be16s(&config->wBaudRate);
-       cpu_to_be16s(&config->wFlags);
-
-       status = mxu1_send_ctrl_data_urb(port->serial, MXU1_SET_CONFIG, 0,
-                                        MXU1_UART1_PORT, config,
-                                        sizeof(*config));
-       if (status)
-               dev_err(&port->dev, "cannot set config: %d\n", status);
-
-       mutex_lock(&mxport->mutex);
-       mcr = mxport->mcr;
-
-       if (C_BAUD(tty) == B0)
-               mcr &= ~(MXU1_MCR_DTR | MXU1_MCR_RTS);
-       else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
-               mcr |= MXU1_MCR_DTR | MXU1_MCR_RTS;
-
-       status = mxu1_set_mcr(port, mcr);
-       if (status)
-               dev_err(&port->dev, "cannot set modem control: %d\n", status);
-       else
-               mxport->mcr = mcr;
-
-       mutex_unlock(&mxport->mutex);
-
-       kfree(config);
-}
-
-static int mxu1_get_serial_info(struct usb_serial_port *port,
-                               struct serial_struct __user *ret_arg)
-{
-       struct serial_struct ret_serial;
-       unsigned cwait;
-
-       if (!ret_arg)
-               return -EFAULT;
-
-       cwait = port->port.closing_wait;
-       if (cwait != ASYNC_CLOSING_WAIT_NONE)
-               cwait = jiffies_to_msecs(cwait) / 10;
-
-       memset(&ret_serial, 0, sizeof(ret_serial));
-
-       ret_serial.type = PORT_16550A;
-       ret_serial.line = port->minor;
-       ret_serial.port = 0;
-       ret_serial.xmit_fifo_size = port->bulk_out_size;
-       ret_serial.baud_base = MXU1_BAUD_BASE;
-       ret_serial.close_delay = 5*HZ;
-       ret_serial.closing_wait = cwait;
-
-       if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int mxu1_set_serial_info(struct usb_serial_port *port,
-                               struct serial_struct __user *new_arg)
-{
-       struct serial_struct new_serial;
-       unsigned cwait;
-
-       if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
-               return -EFAULT;
-
-       cwait = new_serial.closing_wait;
-       if (cwait != ASYNC_CLOSING_WAIT_NONE)
-               cwait = msecs_to_jiffies(10 * new_serial.closing_wait);
-
-       port->port.closing_wait = cwait;
-
-       return 0;
-}
-
-static int mxu1_ioctl(struct tty_struct *tty,
-                     unsigned int cmd, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-
-       switch (cmd) {
-       case TIOCGSERIAL:
-               return mxu1_get_serial_info(port,
-                                           (struct serial_struct __user *)arg);
-       case TIOCSSERIAL:
-               return mxu1_set_serial_info(port,
-                                           (struct serial_struct __user *)arg);
-       }
-
-       return -ENOIOCTLCMD;
-}
-
-static int mxu1_tiocmget(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       unsigned int result;
-       unsigned int msr;
-       unsigned int mcr;
-       unsigned long flags;
-
-       mutex_lock(&mxport->mutex);
-       spin_lock_irqsave(&mxport->spinlock, flags);
-
-       msr = mxport->msr;
-       mcr = mxport->mcr;
-
-       spin_unlock_irqrestore(&mxport->spinlock, flags);
-       mutex_unlock(&mxport->mutex);
-
-       result = ((mcr & MXU1_MCR_DTR)  ? TIOCM_DTR     : 0) |
-                ((mcr & MXU1_MCR_RTS)  ? TIOCM_RTS     : 0) |
-                ((mcr & MXU1_MCR_LOOP) ? TIOCM_LOOP    : 0) |
-                ((msr & MXU1_MSR_CTS)  ? TIOCM_CTS     : 0) |
-                ((msr & MXU1_MSR_CD)   ? TIOCM_CAR     : 0) |
-                ((msr & MXU1_MSR_RI)   ? TIOCM_RI      : 0) |
-                ((msr & MXU1_MSR_DSR)  ? TIOCM_DSR     : 0);
-
-       dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result);
-
-       return result;
-}
-
-static int mxu1_tiocmset(struct tty_struct *tty,
-                        unsigned int set, unsigned int clear)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       int err;
-       unsigned int mcr;
-
-       mutex_lock(&mxport->mutex);
-       mcr = mxport->mcr;
-
-       if (set & TIOCM_RTS)
-               mcr |= MXU1_MCR_RTS;
-       if (set & TIOCM_DTR)
-               mcr |= MXU1_MCR_DTR;
-       if (set & TIOCM_LOOP)
-               mcr |= MXU1_MCR_LOOP;
-
-       if (clear & TIOCM_RTS)
-               mcr &= ~MXU1_MCR_RTS;
-       if (clear & TIOCM_DTR)
-               mcr &= ~MXU1_MCR_DTR;
-       if (clear & TIOCM_LOOP)
-               mcr &= ~MXU1_MCR_LOOP;
-
-       err = mxu1_set_mcr(port, mcr);
-       if (!err)
-               mxport->mcr = mcr;
-
-       mutex_unlock(&mxport->mutex);
-
-       return err;
-}
-
-static void mxu1_break(struct tty_struct *tty, int break_state)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-
-       if (break_state == -1)
-               mxport->send_break = true;
-       else
-               mxport->send_break = false;
-
-       mxu1_set_termios(tty, port, NULL);
-}
-
-static int mxu1_open(struct tty_struct *tty, struct usb_serial_port *port)
-{
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       struct usb_serial *serial = port->serial;
-       int status;
-       u16 open_settings;
-
-       open_settings = (MXU1_PIPE_MODE_CONTINUOUS |
-                        MXU1_PIPE_TIMEOUT_ENABLE |
-                        (MXU1_TRANSFER_TIMEOUT << 2));
-
-       mxport->msr = 0;
-
-       status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-       if (status) {
-               dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
-                       status);
-               return status;
-       }
-
-       if (tty)
-               mxu1_set_termios(tty, port, NULL);
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_OPEN_PORT,
-                                   open_settings, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send open command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_START_PORT,
-                                   0, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send start command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_PURGE_PORT,
-                                   MXU1_PURGE_INPUT, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot clear input buffers: %d\n",
-                       status);
-
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_PURGE_PORT,
-                                   MXU1_PURGE_OUTPUT, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot clear output buffers: %d\n",
-                       status);
-
-               goto unlink_int_urb;
-       }
-
-       /*
-        * reset the data toggle on the bulk endpoints to work around bug in
-        * host controllers where things get out of sync some times
-        */
-       usb_clear_halt(serial->dev, port->write_urb->pipe);
-       usb_clear_halt(serial->dev, port->read_urb->pipe);
-
-       if (tty)
-               mxu1_set_termios(tty, port, NULL);
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_OPEN_PORT,
-                                   open_settings, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send open command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_START_PORT,
-                                   0, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send start command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = usb_serial_generic_open(tty, port);
-       if (status)
-               goto unlink_int_urb;
-
-       return 0;
-
-unlink_int_urb:
-       usb_kill_urb(port->interrupt_in_urb);
-
-       return status;
-}
-
-static void mxu1_close(struct usb_serial_port *port)
-{
-       int status;
-
-       usb_serial_generic_close(port);
-       usb_kill_urb(port->interrupt_in_urb);
-
-       status = mxu1_send_ctrl_urb(port->serial, MXU1_CLOSE_PORT,
-                                   0, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "failed to send close port command: %d\n",
-                       status);
-       }
-}
-
-static void mxu1_handle_new_msr(struct usb_serial_port *port, u8 msr)
-{
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       struct async_icount *icount;
-       unsigned long flags;
-
-       dev_dbg(&port->dev, "%s - msr 0x%02X\n", __func__, msr);
-
-       spin_lock_irqsave(&mxport->spinlock, flags);
-       mxport->msr = msr & MXU1_MSR_MASK;
-       spin_unlock_irqrestore(&mxport->spinlock, flags);
-
-       if (msr & MXU1_MSR_DELTA_MASK) {
-               icount = &port->icount;
-               if (msr & MXU1_MSR_DELTA_CTS)
-                       icount->cts++;
-               if (msr & MXU1_MSR_DELTA_DSR)
-                       icount->dsr++;
-               if (msr & MXU1_MSR_DELTA_CD)
-                       icount->dcd++;
-               if (msr & MXU1_MSR_DELTA_RI)
-                       icount->rng++;
-
-               wake_up_interruptible(&port->port.delta_msr_wait);
-       }
-}
-
-static void mxu1_interrupt_callback(struct urb *urb)
-{
-       struct usb_serial_port *port = urb->context;
-       unsigned char *data = urb->transfer_buffer;
-       int length = urb->actual_length;
-       int function;
-       int status;
-       u8 msr;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               dev_dbg(&port->dev, "%s - urb shutting down: %d\n",
-                       __func__, urb->status);
-               return;
-       default:
-               dev_dbg(&port->dev, "%s - nonzero urb status: %d\n",
-                       __func__, urb->status);
-               goto exit;
-       }
-
-       if (length != 2) {
-               dev_dbg(&port->dev, "%s - bad packet size: %d\n",
-                       __func__, length);
-               goto exit;
-       }
-
-       if (data[0] == MXU1_CODE_HARDWARE_ERROR) {
-               dev_err(&port->dev, "hardware error: %d\n", data[1]);
-               goto exit;
-       }
-
-       function = mxu1_get_func_from_code(data[0]);
-
-       dev_dbg(&port->dev, "%s - function %d, data 0x%02X\n",
-                __func__, function, data[1]);
-
-       switch (function) {
-       case MXU1_CODE_DATA_ERROR:
-               dev_dbg(&port->dev, "%s - DATA ERROR, data 0x%02X\n",
-                        __func__, data[1]);
-               break;
-
-       case MXU1_CODE_MODEM_STATUS:
-               msr = data[1];
-               mxu1_handle_new_msr(port, msr);
-               break;
-
-       default:
-               dev_err(&port->dev, "unknown interrupt code: 0x%02X\n",
-                       data[1]);
-               break;
-       }
-
-exit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status) {
-               dev_err(&port->dev, "resubmit interrupt urb failed: %d\n",
-                       status);
-       }
-}
-
-static struct usb_serial_driver mxu11x0_device = {
-       .driver = {
-               .owner          = THIS_MODULE,
-               .name           = "mxu11x0",
-       },
-       .description            = "MOXA UPort 11x0",
-       .id_table               = mxu1_idtable,
-       .num_ports              = 1,
-       .port_probe             = mxu1_port_probe,
-       .port_remove            = mxu1_port_remove,
-       .attach                 = mxu1_startup,
-       .release                = mxu1_release,
-       .open                   = mxu1_open,
-       .close                  = mxu1_close,
-       .ioctl                  = mxu1_ioctl,
-       .set_termios            = mxu1_set_termios,
-       .tiocmget               = mxu1_tiocmget,
-       .tiocmset               = mxu1_tiocmset,
-       .tiocmiwait             = usb_serial_generic_tiocmiwait,
-       .get_icount             = usb_serial_generic_get_icount,
-       .break_ctl              = mxu1_break,
-       .read_int_callback      = mxu1_interrupt_callback,
-};
-
-static struct usb_serial_driver *const serial_drivers[] = {
-       &mxu11x0_device, NULL
-};
-
-module_usb_serial_driver(serial_drivers, mxu1_idtable);
-
-MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
-MODULE_DESCRIPTION("MOXA UPort 11x0 USB to Serial Hub Driver");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("moxa/moxa-1110.fw");
-MODULE_FIRMWARE("moxa/moxa-1130.fw");
-MODULE_FIRMWARE("moxa/moxa-1131.fw");
-MODULE_FIRMWARE("moxa/moxa-1150.fw");
-MODULE_FIRMWARE("moxa/moxa-1151.fw");
index db86e512e0fcb3af0548eb9907b04ce68db3a8dc..348e19834b83e12e7aafafa9d46374822fe43f7f 100644 (file)
@@ -270,6 +270,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_UE910_V2                 0x1012
 #define TELIT_PRODUCT_LE922_USBCFG0            0x1042
 #define TELIT_PRODUCT_LE922_USBCFG3            0x1043
+#define TELIT_PRODUCT_LE922_USBCFG5            0x1045
 #define TELIT_PRODUCT_LE920                    0x1200
 #define TELIT_PRODUCT_LE910                    0x1201
 
@@ -315,6 +316,7 @@ static void option_instat_callback(struct urb *urb);
 #define TOSHIBA_PRODUCT_G450                   0x0d45
 
 #define ALINK_VENDOR_ID                                0x1e0e
+#define SIMCOM_PRODUCT_SIM7100E                        0x9001 /* Yes, ALINK_VENDOR_ID */
 #define ALINK_PRODUCT_PH300                    0x9100
 #define ALINK_PRODUCT_3GU                      0x9200
 
@@ -607,6 +609,10 @@ static const struct option_blacklist_info zte_1255_blacklist = {
        .reserved = BIT(3) | BIT(4),
 };
 
+static const struct option_blacklist_info simcom_sim7100e_blacklist = {
+       .reserved = BIT(5) | BIT(6),
+};
+
 static const struct option_blacklist_info telit_le910_blacklist = {
        .sendsetup = BIT(0),
        .reserved = BIT(1) | BIT(2),
@@ -1122,9 +1128,13 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
+       { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, 0x6001, 0xff, 0xff, 0xff), /* 4G LTE usb-modem U901 */
+         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1176,6 +1186,8 @@ static const struct usb_device_id option_ids[] = {
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff),
+               .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
                .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
@@ -1645,6 +1657,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
        { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
        { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(ALINK_VENDOR_ID, SIMCOM_PRODUCT_SIM7100E),
+         .driver_info = (kernel_ulong_t)&simcom_sim7100e_blacklist },
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
index 9919d2a9faf278177aacf32c149fda22b00a1d83..1bc6089b90083a05e0ef3e4ff71c0ef752e3831a 100644 (file)
@@ -157,14 +157,17 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x1199, 0x9056)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9060)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9061)},   /* Sierra Wireless Modem */
-       {DEVICE_SWI(0x1199, 0x9070)},   /* Sierra Wireless MC74xx/EM74xx */
-       {DEVICE_SWI(0x1199, 0x9071)},   /* Sierra Wireless MC74xx/EM74xx */
+       {DEVICE_SWI(0x1199, 0x9070)},   /* Sierra Wireless MC74xx */
+       {DEVICE_SWI(0x1199, 0x9071)},   /* Sierra Wireless MC74xx */
+       {DEVICE_SWI(0x1199, 0x9078)},   /* Sierra Wireless EM74xx */
+       {DEVICE_SWI(0x1199, 0x9079)},   /* Sierra Wireless EM74xx */
        {DEVICE_SWI(0x413c, 0x81a2)},   /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a3)},   /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a4)},   /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a8)},   /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a9)},   /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81b1)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
+       {DEVICE_SWI(0x413c, 0x81b3)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
 
        /* Huawei devices */
        {DEVICE_HWI(0x03f0, 0x581d)},   /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
index 2760a7ba3f309d1a344781c2f9a4eb6c3b3ff4aa..8c80a48e32335346e426547fa5007e179ff7cec7 100644 (file)
@@ -446,7 +446,8 @@ static long vfio_pci_ioctl(void *device_data,
                info.num_regions = VFIO_PCI_NUM_REGIONS;
                info.num_irqs = VFIO_PCI_NUM_IRQS;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
                struct pci_dev *pdev = vdev->pdev;
@@ -520,7 +521,8 @@ static long vfio_pci_ioctl(void *device_data,
                        return -EINVAL;
                }
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
                struct vfio_irq_info info;
@@ -555,7 +557,8 @@ static long vfio_pci_ioctl(void *device_data,
                else
                        info.flags |= VFIO_IRQ_INFO_NORESIZE;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_SET_IRQS) {
                struct vfio_irq_set hdr;
index 418cdd9ba3f4841353c5cbdddb345e9363578736..e65b142d34222dd4ba548e46c44017d2b762cf06 100644 (file)
@@ -219,7 +219,8 @@ static long vfio_platform_ioctl(void *device_data,
                info.num_regions = vdev->num_regions;
                info.num_irqs = vdev->num_irqs;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
                struct vfio_region_info info;
@@ -240,7 +241,8 @@ static long vfio_platform_ioctl(void *device_data,
                info.size = vdev->regions[info.index].size;
                info.flags = vdev->regions[info.index].flags;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
                struct vfio_irq_info info;
@@ -259,7 +261,8 @@ static long vfio_platform_ioctl(void *device_data,
                info.flags = vdev->irqs[info.index].flags;
                info.count = vdev->irqs[info.index].count;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_SET_IRQS) {
                struct vfio_irq_set hdr;
index 6f1ea3dddbad9a75dd094d8613fb426742f844e4..75b24e93cedb3da273a589bb129b6ce502b247fd 100644 (file)
@@ -999,7 +999,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 
                info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_IOMMU_MAP_DMA) {
                struct vfio_iommu_type1_dma_map map;
@@ -1032,7 +1033,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
                if (ret)
                        return ret;
 
-               return copy_to_user((void __user *)arg, &unmap, minsz);
+               return copy_to_user((void __user *)arg, &unmap, minsz) ?
+                       -EFAULT : 0;
        }
 
        return -ENOTTY;
index ad2146a9ab2d4b19cca5469402c203ade61e8545..236553e81027c15b089cdf2a0d4378f60e3f8d6a 100644 (file)
@@ -1156,6 +1156,8 @@ int vhost_init_used(struct vhost_virtqueue *vq)
 {
        __virtio16 last_used_idx;
        int r;
+       bool is_le = vq->is_le;
+
        if (!vq->private_data) {
                vq->is_le = virtio_legacy_is_little_endian();
                return 0;
@@ -1165,15 +1167,20 @@ int vhost_init_used(struct vhost_virtqueue *vq)
 
        r = vhost_update_used_flags(vq);
        if (r)
-               return r;
+               goto err;
        vq->signalled_used_valid = false;
-       if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx))
-               return -EFAULT;
+       if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx)) {
+               r = -EFAULT;
+               goto err;
+       }
        r = __get_user(last_used_idx, &vq->used->idx);
        if (r)
-               return r;
+               goto err;
        vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx);
        return 0;
+err:
+       vq->is_le = is_le;
+       return r;
 }
 EXPORT_SYMBOL_GPL(vhost_init_used);
 
index 92f394927f241bef338a293170e4a09b9f45c647..6e92917ba77a97477f32a0426ee914c351867a6b 100644 (file)
@@ -709,6 +709,7 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
        }
 
        if (!err) {
+               ops->cur_blink_jiffies = HZ / 5;
                info->fbcon_par = ops;
 
                if (vc)
@@ -956,6 +957,7 @@ static const char *fbcon_startup(void)
        ops->currcon = -1;
        ops->graphics = 1;
        ops->cur_rotate = -1;
+       ops->cur_blink_jiffies = HZ / 5;
        info->fbcon_par = ops;
        p->con_rotate = initial_rotation;
        set_blitting_type(vc, info);
index 0081725c6b5be62f6c7939d5bc2b4022881f363e..6b2a06d09f2b612ae6fac5252977df0853fc8cf1 100644 (file)
@@ -152,7 +152,7 @@ static void lcdc_write(unsigned int val, unsigned int addr)
 
 struct da8xx_fb_par {
        struct device           *dev;
-       resource_size_t p_palette_base;
+       dma_addr_t              p_palette_base;
        unsigned char *v_palette_base;
        dma_addr_t              vram_phys;
        unsigned long           vram_size;
@@ -1428,7 +1428,7 @@ static int fb_probe(struct platform_device *device)
 
        par->vram_virt = dma_alloc_coherent(NULL,
                                            par->vram_size,
-                                           (resource_size_t *) &par->vram_phys,
+                                           &par->vram_phys,
                                            GFP_KERNEL | GFP_DMA);
        if (!par->vram_virt) {
                dev_err(&device->dev,
@@ -1448,7 +1448,7 @@ static int fb_probe(struct platform_device *device)
 
        /* allocate palette buffer */
        par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE,
-                                                 (resource_size_t *)&par->p_palette_base,
+                                                 &par->p_palette_base,
                                                  GFP_KERNEL | GFP_DMA);
        if (!par->v_palette_base) {
                dev_err(&device->dev,
index 95873f26e39cf6d58fe78b0dce1fdbabcf9c1390..de2f3e793786c77c73923616fb30b0170d1100b1 100644 (file)
@@ -829,8 +829,7 @@ static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
+static int __maybe_unused s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
 {
        struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
 
@@ -843,7 +842,7 @@ static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
        return 0;
 }
 
-static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
+static int __maybe_unused s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
 {
        struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
 
@@ -855,10 +854,6 @@ static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
 
        return 0;
 }
-#else
-#define s6e8ax0_suspend                NULL
-#define s6e8ax0_resume         NULL
-#endif
 
 static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
        .name = "s6e8ax0",
@@ -867,8 +862,8 @@ static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
        .power_on = s6e8ax0_power_on,
        .set_sequence = s6e8ax0_set_sequence,
        .probe = s6e8ax0_probe,
-       .suspend = s6e8ax0_suspend,
-       .resume = s6e8ax0_resume,
+       .suspend = IS_ENABLED(CONFIG_PM) ? s6e8ax0_suspend : NULL,
+       .resume = IS_ENABLED(CONFIG_PM) ? s6e8ax0_resume : NULL,
 };
 
 static int s6e8ax0_init(void)
index cee88603efc9e40195430fe1a745eebefb97ef0b..bb2f1e866020199d31b8ba0b1940cb9e6b87923f 100644 (file)
@@ -902,6 +902,21 @@ static int imxfb_probe(struct platform_device *pdev)
                goto failed_getclock;
        }
 
+       /*
+        * The LCDC controller does not have an enable bit. The
+        * controller starts directly when the clocks are enabled.
+        * If the clocks are enabled when the controller is not yet
+        * programmed with proper register values (enabled at the
+        * bootloader, for example) then it just goes into some undefined
+        * state.
+        * To avoid this issue, let's enable and disable LCDC IPG clock
+        * so that we force some kind of 'reset' to the LCDC block.
+        */
+       ret = clk_prepare_enable(fbi->clk_ipg);
+       if (ret)
+               goto failed_getclock;
+       clk_disable_unprepare(fbi->clk_ipg);
+
        fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(fbi->clk_ahb)) {
                ret = PTR_ERR(fbi->clk_ahb);
index de54a474806504ba9844839267fcc7604422ce3f..b6f83d5df9fdeab329478d5ccfeb78610da9e532 100644 (file)
@@ -503,8 +503,7 @@ static int mmphw_probe(struct platform_device *pdev)
        ctrl->reg_base = devm_ioremap_nocache(ctrl->dev,
                        res->start, resource_size(res));
        if (ctrl->reg_base == NULL) {
-               dev_err(ctrl->dev, "%s: res %x - %x map failed\n", __func__,
-                       res->start, res->end);
+               dev_err(ctrl->dev, "%s: res %pR map failed\n", __func__, res);
                ret = -ENOMEM;
                goto failed;
        }
index c9293aea8ec3502e27ddf6125f07201c16996a7b..a970edc2a6f8c781696ac7b0b6664fd7c4513ffa 100644 (file)
@@ -123,11 +123,11 @@ static int ocfb_setupfb(struct ocfb_dev *fbdev)
 
        /* Horizontal timings */
        ocfb_writereg(fbdev, OCFB_HTIM, (var->hsync_len - 1) << 24 |
-                     (var->right_margin - 1) << 16 | (var->xres - 1));
+                     (var->left_margin - 1) << 16 | (var->xres - 1));
 
        /* Vertical timings */
        ocfb_writereg(fbdev, OCFB_VTIM, (var->vsync_len - 1) << 24 |
-                     (var->lower_margin - 1) << 16 | (var->yres - 1));
+                     (var->upper_margin - 1) << 16 | (var->yres - 1));
 
        /* Total length of frame */
        hlen = var->left_margin + var->right_margin + var->hsync_len +
index c0c11fad4611a72a3712c3ef7471193cb5d8fa5d..7760fc1a2218e9ea9e053caf8db2be27dc8d2952 100644 (file)
@@ -679,7 +679,7 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev)
 
        pci_read_config_dword(pci_dev,
                              notify + offsetof(struct virtio_pci_notify_cap,
-                                               cap.length),
+                                               cap.offset),
                              &notify_offset);
 
        /* We don't know how many VQs we'll map, ahead of the time.
index 0f6d8515ba4f1d06144bb67c12ef26ef4a545da8..80825a7e8e48e1ebd06af14a1bcf208acb733daf 100644 (file)
@@ -1569,6 +1569,17 @@ config WATCHDOG_RIO
          machines.  The watchdog timeout period is normally one minute but
          can be changed with a boot-time parameter.
 
+config WATCHDOG_SUN4V
+       tristate "Sun4v Watchdog support"
+       select WATCHDOG_CORE
+       depends on SPARC64
+       help
+         Say Y here to support the hypervisor watchdog capability embedded
+         in the SPARC sun4v architecture.
+
+         To compile this driver as a module, choose M here. The module will
+         be called sun4v_wdt.
+
 # XTENSA Architecture
 
 # Xen Architecture
index f566753256abbbb74535337d3f9a9cc0442fd78e..f6a6a387c6c71f7a5e9e2cda4cc91ae3f39edf2c 100644 (file)
@@ -179,6 +179,7 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
 
 obj-$(CONFIG_WATCHDOG_RIO)             += riowd.o
 obj-$(CONFIG_WATCHDOG_CP1XXX)          += cpwd.o
+obj-$(CONFIG_WATCHDOG_SUN4V)           += sun4v_wdt.o
 
 # XTENSA Architecture
 
diff --git a/drivers/watchdog/sun4v_wdt.c b/drivers/watchdog/sun4v_wdt.c
new file mode 100644 (file)
index 0000000..1467fe5
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *     sun4v watchdog timer
+ *     (c) Copyright 2016 Oracle Corporation
+ *
+ *     Implement a simple watchdog driver using the built-in sun4v hypervisor
+ *     watchdog support. If time expires, the hypervisor stops or bounces
+ *     the guest domain.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/watchdog.h>
+#include <asm/hypervisor.h>
+#include <asm/mdesc.h>
+
+#define WDT_TIMEOUT                    60
+#define WDT_MAX_TIMEOUT                        31536000
+#define WDT_MIN_TIMEOUT                        1
+#define WDT_DEFAULT_RESOLUTION_MS      1000    /* 1 second */
+
+static unsigned int timeout;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
+       __MODULE_STRING(WDT_TIMEOUT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, S_IRUGO);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+       __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int sun4v_wdt_stop(struct watchdog_device *wdd)
+{
+       sun4v_mach_set_watchdog(0, NULL);
+
+       return 0;
+}
+
+static int sun4v_wdt_ping(struct watchdog_device *wdd)
+{
+       int hverr;
+
+       /*
+        * HV watchdog timer will round up the timeout
+        * passed in to the nearest multiple of the
+        * watchdog resolution in milliseconds.
+        */
+       hverr = sun4v_mach_set_watchdog(wdd->timeout * 1000, NULL);
+       if (hverr == HV_EINVAL)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sun4v_wdt_set_timeout(struct watchdog_device *wdd,
+                                unsigned int timeout)
+{
+       wdd->timeout = timeout;
+
+       return 0;
+}
+
+static const struct watchdog_info sun4v_wdt_ident = {
+       .options =      WDIOF_SETTIMEOUT |
+                       WDIOF_MAGICCLOSE |
+                       WDIOF_KEEPALIVEPING,
+       .identity =     "sun4v hypervisor watchdog",
+       .firmware_version = 0,
+};
+
+static struct watchdog_ops sun4v_wdt_ops = {
+       .owner =        THIS_MODULE,
+       .start =        sun4v_wdt_ping,
+       .stop =         sun4v_wdt_stop,
+       .ping =         sun4v_wdt_ping,
+       .set_timeout =  sun4v_wdt_set_timeout,
+};
+
+static struct watchdog_device wdd = {
+       .info = &sun4v_wdt_ident,
+       .ops = &sun4v_wdt_ops,
+       .min_timeout = WDT_MIN_TIMEOUT,
+       .max_timeout = WDT_MAX_TIMEOUT,
+       .timeout = WDT_TIMEOUT,
+};
+
+static int __init sun4v_wdt_init(void)
+{
+       struct mdesc_handle *handle;
+       u64 node;
+       const u64 *value;
+       int err = 0;
+       unsigned long major = 1, minor = 1;
+
+       /*
+        * There are 2 properties that can be set from the control
+        * domain for the watchdog.
+        * watchdog-resolution
+        * watchdog-max-timeout
+        *
+        * We can expect a handle to be returned otherwise something
+        * serious is wrong. Correct to return -ENODEV here.
+        */
+
+       handle = mdesc_grab();
+       if (!handle)
+               return -ENODEV;
+
+       node = mdesc_node_by_name(handle, MDESC_NODE_NULL, "platform");
+       err = -ENODEV;
+       if (node == MDESC_NODE_NULL)
+               goto out_release;
+
+       /*
+        * This is a safe way to validate if we are on the right
+        * platform.
+        */
+       if (sun4v_hvapi_register(HV_GRP_CORE, major, &minor))
+               goto out_hv_unreg;
+
+       /* Allow value of watchdog-resolution up to 1s (default) */
+       value = mdesc_get_property(handle, node, "watchdog-resolution", NULL);
+       err = -EINVAL;
+       if (value) {
+               if (*value == 0 ||
+                   *value > WDT_DEFAULT_RESOLUTION_MS)
+                       goto out_hv_unreg;
+       }
+
+       value = mdesc_get_property(handle, node, "watchdog-max-timeout", NULL);
+       if (value) {
+               /*
+                * If the property value (in ms) is smaller than
+                * min_timeout, return -EINVAL.
+                */
+               if (*value < wdd.min_timeout * 1000)
+                       goto out_hv_unreg;
+
+               /*
+                * If the property value is smaller than
+                * default max_timeout  then set watchdog max_timeout to
+                * the value of the property in seconds.
+                */
+               if (*value < wdd.max_timeout * 1000)
+                       wdd.max_timeout = *value  / 1000;
+       }
+
+       watchdog_init_timeout(&wdd, timeout, NULL);
+
+       watchdog_set_nowayout(&wdd, nowayout);
+
+       err = watchdog_register_device(&wdd);
+       if (err)
+               goto out_hv_unreg;
+
+       pr_info("initialized (timeout=%ds, nowayout=%d)\n",
+                wdd.timeout, nowayout);
+
+       mdesc_release(handle);
+
+       return 0;
+
+out_hv_unreg:
+       sun4v_hvapi_unregister(HV_GRP_CORE);
+
+out_release:
+       mdesc_release(handle);
+       return err;
+}
+
+static void __exit sun4v_wdt_exit(void)
+{
+       sun4v_hvapi_unregister(HV_GRP_CORE);
+       watchdog_unregister_device(&wdd);
+}
+
+module_init(sun4v_wdt_init);
+module_exit(sun4v_wdt_exit);
+
+MODULE_AUTHOR("Wim Coekaerts <wim.coekaerts@oracle.com>");
+MODULE_DESCRIPTION("sun4v watchdog driver");
+MODULE_LICENSE("GPL");
index 73dafdc494aa8322e037f1d4a9ad4ec5530c5743..fb0221434f814aa49eef41f6aea7a60c86a4c817 100644 (file)
@@ -227,8 +227,9 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
        /*
         * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able
         * to access the BARs where the MSI-X entries reside.
+        * But VF devices are unique in which the PF needs to be checked.
         */
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       pci_read_config_word(pci_physfn(dev), PCI_COMMAND, &cmd);
        if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY))
                return -ENXIO;
 
@@ -332,6 +333,9 @@ void xen_pcibk_do_op(struct work_struct *data)
        struct xen_pcibk_dev_data *dev_data = NULL;
        struct xen_pci_op *op = &pdev->op;
        int test_intx = 0;
+#ifdef CONFIG_PCI_MSI
+       unsigned int nr = 0;
+#endif
 
        *op = pdev->sh_info->op;
        barrier();
@@ -360,6 +364,7 @@ void xen_pcibk_do_op(struct work_struct *data)
                        op->err = xen_pcibk_disable_msi(pdev, dev, op);
                        break;
                case XEN_PCI_OP_enable_msix:
+                       nr = op->value;
                        op->err = xen_pcibk_enable_msix(pdev, dev, op);
                        break;
                case XEN_PCI_OP_disable_msix:
@@ -382,7 +387,7 @@ void xen_pcibk_do_op(struct work_struct *data)
        if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) {
                unsigned int i;
 
-               for (i = 0; i < op->value; i++)
+               for (i = 0; i < nr; i++)
                        pdev->sh_info->op.msix_entries[i].vector =
                                op->msix_entries[i].vector;
        }
index ad4eb1024d1ffb7663db4e770fdd4c5c2663e821..c46ee189466f81ab584282651494fad765a38417 100644 (file)
@@ -848,6 +848,24 @@ static int scsiback_map(struct vscsibk_info *info)
        return scsiback_init_sring(info, ring_ref, evtchn);
 }
 
+/*
+  Check for a translation entry being present
+*/
+static struct v2p_entry *scsiback_chk_translation_entry(
+       struct vscsibk_info *info, struct ids_tuple *v)
+{
+       struct list_head *head = &(info->v2p_entry_lists);
+       struct v2p_entry *entry;
+
+       list_for_each_entry(entry, head, l)
+               if ((entry->v.chn == v->chn) &&
+                   (entry->v.tgt == v->tgt) &&
+                   (entry->v.lun == v->lun))
+                       return entry;
+
+       return NULL;
+}
+
 /*
   Add a new translation entry
 */
@@ -855,9 +873,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
                                          char *phy, struct ids_tuple *v)
 {
        int err = 0;
-       struct v2p_entry *entry;
        struct v2p_entry *new;
-       struct list_head *head = &(info->v2p_entry_lists);
        unsigned long flags;
        char *lunp;
        unsigned long long unpacked_lun;
@@ -917,15 +933,10 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
        spin_lock_irqsave(&info->v2p_lock, flags);
 
        /* Check double assignment to identical virtual ID */
-       list_for_each_entry(entry, head, l) {
-               if ((entry->v.chn == v->chn) &&
-                   (entry->v.tgt == v->tgt) &&
-                   (entry->v.lun == v->lun)) {
-                       pr_warn("Virtual ID is already used. Assignment was not performed.\n");
-                       err = -EEXIST;
-                       goto out;
-               }
-
+       if (scsiback_chk_translation_entry(info, v)) {
+               pr_warn("Virtual ID is already used. Assignment was not performed.\n");
+               err = -EEXIST;
+               goto out;
        }
 
        /* Create a new translation entry and add to the list */
@@ -933,18 +944,18 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
        new->v = *v;
        new->tpg = tpg;
        new->lun = unpacked_lun;
-       list_add_tail(&new->l, head);
+       list_add_tail(&new->l, &info->v2p_entry_lists);
 
 out:
        spin_unlock_irqrestore(&info->v2p_lock, flags);
 
 out_free:
-       mutex_lock(&tpg->tv_tpg_mutex);
-       tpg->tv_tpg_fe_count--;
-       mutex_unlock(&tpg->tv_tpg_mutex);
-
-       if (err)
+       if (err) {
+               mutex_lock(&tpg->tv_tpg_mutex);
+               tpg->tv_tpg_fe_count--;
+               mutex_unlock(&tpg->tv_tpg_mutex);
                kfree(new);
+       }
 
        return err;
 }
@@ -956,39 +967,40 @@ static void __scsiback_del_translation_entry(struct v2p_entry *entry)
 }
 
 /*
-  Delete the translation entry specfied
+  Delete the translation entry specified
 */
 static int scsiback_del_translation_entry(struct vscsibk_info *info,
                                          struct ids_tuple *v)
 {
        struct v2p_entry *entry;
-       struct list_head *head = &(info->v2p_entry_lists);
        unsigned long flags;
+       int ret = 0;
 
        spin_lock_irqsave(&info->v2p_lock, flags);
        /* Find out the translation entry specified */
-       list_for_each_entry(entry, head, l) {
-               if ((entry->v.chn == v->chn) &&
-                   (entry->v.tgt == v->tgt) &&
-                   (entry->v.lun == v->lun)) {
-                       goto found;
-               }
-       }
-
-       spin_unlock_irqrestore(&info->v2p_lock, flags);
-       return 1;
-
-found:
-       /* Delete the translation entry specfied */
-       __scsiback_del_translation_entry(entry);
+       entry = scsiback_chk_translation_entry(info, v);
+       if (entry)
+               __scsiback_del_translation_entry(entry);
+       else
+               ret = -ENOENT;
 
        spin_unlock_irqrestore(&info->v2p_lock, flags);
-       return 0;
+       return ret;
 }
 
 static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state,
                                char *phy, struct ids_tuple *vir, int try)
 {
+       struct v2p_entry *entry;
+       unsigned long flags;
+
+       if (try) {
+               spin_lock_irqsave(&info->v2p_lock, flags);
+               entry = scsiback_chk_translation_entry(info, vir);
+               spin_unlock_irqrestore(&info->v2p_lock, flags);
+               if (entry)
+                       return;
+       }
        if (!scsiback_add_translation_entry(info, phy, vir)) {
                if (xenbus_printf(XBT_NIL, info->dev->nodename, state,
                                  "%d", XenbusStateInitialised)) {
index 9433e46518c8dc8680fd1e5a44d823aa7f65fdb0..912b64edb42b4a016201b4e7d1a695ca25056610 100644 (file)
@@ -188,6 +188,8 @@ static int queue_reply(struct list_head *queue, const void *data, size_t len)
 
        if (len == 0)
                return 0;
+       if (len > XENSTORE_PAYLOAD_MAX)
+               return -EINVAL;
 
        rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
        if (rb == NULL)
index 0548c53f41d51902a4e0ce7b983f7cd365f656f9..22fc7c802d698766fb5b274e686e89df4e0d76d1 100644 (file)
@@ -511,8 +511,6 @@ affs_do_readpage_ofs(struct page *page, unsigned to)
        pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino,
                 page->index, to);
        BUG_ON(to > PAGE_CACHE_SIZE);
-       kmap(page);
-       data = page_address(page);
        bsize = AFFS_SB(sb)->s_data_blksize;
        tmp = page->index << PAGE_CACHE_SHIFT;
        bidx = tmp / bsize;
@@ -524,14 +522,15 @@ affs_do_readpage_ofs(struct page *page, unsigned to)
                        return PTR_ERR(bh);
                tmp = min(bsize - boff, to - pos);
                BUG_ON(pos + tmp > to || tmp > bsize);
+               data = kmap_atomic(page);
                memcpy(data + pos, AFFS_DATA(bh) + boff, tmp);
+               kunmap_atomic(data);
                affs_brelse(bh);
                bidx++;
                pos += tmp;
                boff = 0;
        }
        flush_dcache_page(page);
-       kunmap(page);
        return 0;
 }
 
index 051ea4809c14037fd0b1efffccb12c3909b3e46b..7d914c67a9d07f7ebb8a3f8f0bea8200d739ee9f 100644 (file)
@@ -653,7 +653,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
 
        if ((current->flags & PF_RANDOMIZE) &&
                !(current->personality & ADDR_NO_RANDOMIZE)) {
-               random_variable = (unsigned long) get_random_int();
+               random_variable = get_random_long();
                random_variable &= STACK_RND_MASK;
                random_variable <<= PAGE_SHIFT;
        }
index 39b3a174a4253974b4635bee951e2283cf71b9cf..826b164a4b5b1faa9719aefc9cceccec20eda479 100644 (file)
@@ -1201,7 +1201,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                bdev->bd_disk = disk;
                bdev->bd_queue = disk->queue;
                bdev->bd_contains = bdev;
-               bdev->bd_inode->i_flags = disk->fops->direct_access ? S_DAX : 0;
+               if (IS_ENABLED(CONFIG_BLK_DEV_DAX) && disk->fops->direct_access)
+                       bdev->bd_inode->i_flags = S_DAX;
+               else
+                       bdev->bd_inode->i_flags = 0;
+
                if (!partno) {
                        ret = -ENXIO;
                        bdev->bd_part = disk_get_part(disk, partno);
@@ -1693,13 +1697,24 @@ static int blkdev_releasepage(struct page *page, gfp_t wait)
        return try_to_free_buffers(page);
 }
 
+static int blkdev_writepages(struct address_space *mapping,
+                            struct writeback_control *wbc)
+{
+       if (dax_mapping(mapping)) {
+               struct block_device *bdev = I_BDEV(mapping->host);
+
+               return dax_writeback_mapping_range(mapping, bdev, wbc);
+       }
+       return generic_writepages(mapping, wbc);
+}
+
 static const struct address_space_operations def_blk_aops = {
        .readpage       = blkdev_readpage,
        .readpages      = blkdev_readpages,
        .writepage      = blkdev_writepage,
        .write_begin    = blkdev_write_begin,
        .write_end      = blkdev_write_end,
-       .writepages     = generic_writepages,
+       .writepages     = blkdev_writepages,
        .releasepage    = blkdev_releasepage,
        .direct_IO      = blkdev_direct_IO,
        .is_dirty_writeback = buffer_check_dirty_writeback,
index b90cd3776f8e0a41635ce7cf5447e7b9652e6cca..f6dac40f87ff5d4022559e6701b506589aad0353 100644 (file)
@@ -1406,7 +1406,8 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                        read_extent_buffer(eb, dest + bytes_left,
                                           name_off, name_len);
                if (eb != eb_in) {
-                       btrfs_tree_read_unlock_blocking(eb);
+                       if (!path->skip_locking)
+                               btrfs_tree_read_unlock_blocking(eb);
                        free_extent_buffer(eb);
                }
                ret = btrfs_find_item(fs_root, path, parent, 0,
@@ -1426,9 +1427,10 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                eb = path->nodes[0];
                /* make sure we can use eb after releasing the path */
                if (eb != eb_in) {
-                       atomic_inc(&eb->refs);
-                       btrfs_tree_read_lock(eb);
-                       btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+                       if (!path->skip_locking)
+                               btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+                       path->nodes[0] = NULL;
+                       path->locks[0] = 0;
                }
                btrfs_release_path(path);
                iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
index c473c42d7d6c4d559dbe1587491cd2fb93804145..3346cd8f991032f2457b4c48a8e3440780d53a9a 100644 (file)
@@ -637,11 +637,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        faili = nr_pages - 1;
        cb->nr_pages = nr_pages;
 
-       /* In the parent-locked case, we only locked the range we are
-        * interested in.  In all other cases, we can opportunistically
-        * cache decompressed data that goes beyond the requested range. */
-       if (!(bio_flags & EXTENT_BIO_PARENT_LOCKED))
-               add_ra_bio_pages(inode, em_start + em_len, cb);
+       add_ra_bio_pages(inode, em_start + em_len, cb);
 
        /* include any pages we added in add_ra-bio_pages */
        uncompressed_len = bio->bi_vcnt * PAGE_CACHE_SIZE;
index 0be47e4b813672996b490515ef88af357c40a276..b57daa895cea8340fd7b3ed491bb730196b6b5e6 100644 (file)
@@ -1689,7 +1689,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
  *
  */
 int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
-                                   struct list_head *ins_list)
+                                   struct list_head *ins_list, bool *emitted)
 {
        struct btrfs_dir_item *di;
        struct btrfs_delayed_item *curr, *next;
@@ -1733,6 +1733,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
 
                if (over)
                        return 1;
+               *emitted = true;
        }
        return 0;
 }
index f70119f254216583f3c7317085ec209eceb03d0f..0167853c84aea2d93a8fdd0314342e0a1ef42d1b 100644 (file)
@@ -144,7 +144,7 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
 int btrfs_should_delete_dir_index(struct list_head *del_list,
                                  u64 index);
 int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
-                                   struct list_head *ins_list);
+                                   struct list_head *ins_list, bool *emitted);
 
 /* for init */
 int __init btrfs_delayed_inode_init(void);
index 2e7c97a3f3444aec33a688a4d1f705b0486026cf..392592dc70106e72f61a76b9e2924b5aa99363af 100644 (file)
@@ -2897,12 +2897,11 @@ static int __do_readpage(struct extent_io_tree *tree,
        struct block_device *bdev;
        int ret;
        int nr = 0;
-       int parent_locked = *bio_flags & EXTENT_BIO_PARENT_LOCKED;
        size_t pg_offset = 0;
        size_t iosize;
        size_t disk_io_size;
        size_t blocksize = inode->i_sb->s_blocksize;
-       unsigned long this_bio_flag = *bio_flags & EXTENT_BIO_PARENT_LOCKED;
+       unsigned long this_bio_flag = 0;
 
        set_page_extent_mapped(page);
 
@@ -2942,18 +2941,16 @@ static int __do_readpage(struct extent_io_tree *tree,
                        kunmap_atomic(userpage);
                        set_extent_uptodate(tree, cur, cur + iosize - 1,
                                            &cached, GFP_NOFS);
-                       if (!parent_locked)
-                               unlock_extent_cached(tree, cur,
-                                                    cur + iosize - 1,
-                                                    &cached, GFP_NOFS);
+                       unlock_extent_cached(tree, cur,
+                                            cur + iosize - 1,
+                                            &cached, GFP_NOFS);
                        break;
                }
                em = __get_extent_map(inode, page, pg_offset, cur,
                                      end - cur + 1, get_extent, em_cached);
                if (IS_ERR_OR_NULL(em)) {
                        SetPageError(page);
-                       if (!parent_locked)
-                               unlock_extent(tree, cur, end);
+                       unlock_extent(tree, cur, end);
                        break;
                }
                extent_offset = cur - em->start;
@@ -3038,12 +3035,9 @@ static int __do_readpage(struct extent_io_tree *tree,
 
                        set_extent_uptodate(tree, cur, cur + iosize - 1,
                                            &cached, GFP_NOFS);
-                       if (parent_locked)
-                               free_extent_state(cached);
-                       else
-                               unlock_extent_cached(tree, cur,
-                                                    cur + iosize - 1,
-                                                    &cached, GFP_NOFS);
+                       unlock_extent_cached(tree, cur,
+                                            cur + iosize - 1,
+                                            &cached, GFP_NOFS);
                        cur = cur + iosize;
                        pg_offset += iosize;
                        continue;
@@ -3052,8 +3046,7 @@ static int __do_readpage(struct extent_io_tree *tree,
                if (test_range_bit(tree, cur, cur_end,
                                   EXTENT_UPTODATE, 1, NULL)) {
                        check_page_uptodate(tree, page);
-                       if (!parent_locked)
-                               unlock_extent(tree, cur, cur + iosize - 1);
+                       unlock_extent(tree, cur, cur + iosize - 1);
                        cur = cur + iosize;
                        pg_offset += iosize;
                        continue;
@@ -3063,8 +3056,7 @@ static int __do_readpage(struct extent_io_tree *tree,
                 */
                if (block_start == EXTENT_MAP_INLINE) {
                        SetPageError(page);
-                       if (!parent_locked)
-                               unlock_extent(tree, cur, cur + iosize - 1);
+                       unlock_extent(tree, cur, cur + iosize - 1);
                        cur = cur + iosize;
                        pg_offset += iosize;
                        continue;
@@ -3083,8 +3075,7 @@ static int __do_readpage(struct extent_io_tree *tree,
                        *bio_flags = this_bio_flag;
                } else {
                        SetPageError(page);
-                       if (!parent_locked)
-                               unlock_extent(tree, cur, cur + iosize - 1);
+                       unlock_extent(tree, cur, cur + iosize - 1);
                }
                cur = cur + iosize;
                pg_offset += iosize;
@@ -3213,20 +3204,6 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
        return ret;
 }
 
-int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page,
-                                get_extent_t *get_extent, int mirror_num)
-{
-       struct bio *bio = NULL;
-       unsigned long bio_flags = EXTENT_BIO_PARENT_LOCKED;
-       int ret;
-
-       ret = __do_readpage(tree, page, get_extent, NULL, &bio, mirror_num,
-                           &bio_flags, READ, NULL);
-       if (bio)
-               ret = submit_one_bio(READ, bio, mirror_num, bio_flags);
-       return ret;
-}
-
 static noinline void update_nr_written(struct page *page,
                                      struct writeback_control *wbc,
                                      unsigned long nr_written)
index 0377413bd4b98257eae07d12041d4dce45ac2c4f..880d5292e9721f6f2c59dfd0f85d3f6fd2cde3bb 100644 (file)
@@ -29,7 +29,6 @@
  */
 #define EXTENT_BIO_COMPRESSED 1
 #define EXTENT_BIO_TREE_LOG 2
-#define EXTENT_BIO_PARENT_LOCKED 4
 #define EXTENT_BIO_FLAG_SHIFT 16
 
 /* these are bit numbers for test/set bit */
@@ -210,8 +209,6 @@ static inline int lock_extent(struct extent_io_tree *tree, u64 start, u64 end)
 int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end);
 int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
                          get_extent_t *get_extent, int mirror_num);
-int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page,
-                                get_extent_t *get_extent, int mirror_num);
 int __init extent_io_init(void);
 void extent_io_exit(void);
 
index 5f06eb1f43843055c0373daeb9ad98648865150f..d96f5cf38a2dd2a8e227ad93ff22f7a678611034 100644 (file)
@@ -5717,6 +5717,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        char *name_ptr;
        int name_len;
        int is_curr = 0;        /* ctx->pos points to the current index? */
+       bool emitted;
 
        /* FIXME, use a real flag for deciding about the key type */
        if (root->fs_info->tree_root == root)
@@ -5745,6 +5746,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        if (ret < 0)
                goto err;
 
+       emitted = false;
        while (1) {
                leaf = path->nodes[0];
                slot = path->slots[0];
@@ -5824,6 +5826,7 @@ skip:
 
                        if (over)
                                goto nopos;
+                       emitted = true;
                        di_len = btrfs_dir_name_len(leaf, di) +
                                 btrfs_dir_data_len(leaf, di) + sizeof(*di);
                        di_cur += di_len;
@@ -5836,11 +5839,20 @@ next:
        if (key_type == BTRFS_DIR_INDEX_KEY) {
                if (is_curr)
                        ctx->pos++;
-               ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
+               ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
                if (ret)
                        goto nopos;
        }
 
+       /*
+        * If we haven't emitted any dir entry, we must not touch ctx->pos as
+        * it was was set to the termination value in previous call. We assume
+        * that "." and ".." were emitted if we reach this point and set the
+        * termination value as well for an empty directory.
+        */
+       if (ctx->pos > 2 && !emitted)
+               goto nopos;
+
        /* Reached end of directory/root. Bump pos past the last item. */
        ctx->pos++;
 
@@ -7974,6 +7986,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
 
        kfree(dip);
 
+       dio_bio->bi_error = bio->bi_error;
        dio_end_io(dio_bio, bio->bi_error);
 
        if (io_bio->end_io)
@@ -8028,6 +8041,7 @@ static void btrfs_endio_direct_write(struct bio *bio)
 
        kfree(dip);
 
+       dio_bio->bi_error = bio->bi_error;
        dio_end_io(dio_bio, bio->bi_error);
        bio_put(bio);
 }
index 952172ca7e455633c28a79292d18ebbfd68c4d18..48aee9846329c526260aa09f5751335c351ea1e3 100644 (file)
@@ -2794,24 +2794,29 @@ out:
 static struct page *extent_same_get_page(struct inode *inode, pgoff_t index)
 {
        struct page *page;
-       struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
 
        page = grab_cache_page(inode->i_mapping, index);
        if (!page)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        if (!PageUptodate(page)) {
-               if (extent_read_full_page_nolock(tree, page, btrfs_get_extent,
-                                                0))
-                       return NULL;
+               int ret;
+
+               ret = btrfs_readpage(NULL, page);
+               if (ret)
+                       return ERR_PTR(ret);
                lock_page(page);
                if (!PageUptodate(page)) {
                        unlock_page(page);
                        page_cache_release(page);
-                       return NULL;
+                       return ERR_PTR(-EIO);
+               }
+               if (page->mapping != inode->i_mapping) {
+                       unlock_page(page);
+                       page_cache_release(page);
+                       return ERR_PTR(-EAGAIN);
                }
        }
-       unlock_page(page);
 
        return page;
 }
@@ -2823,17 +2828,31 @@ static int gather_extent_pages(struct inode *inode, struct page **pages,
        pgoff_t index = off >> PAGE_CACHE_SHIFT;
 
        for (i = 0; i < num_pages; i++) {
+again:
                pages[i] = extent_same_get_page(inode, index + i);
-               if (!pages[i])
-                       return -ENOMEM;
+               if (IS_ERR(pages[i])) {
+                       int err = PTR_ERR(pages[i]);
+
+                       if (err == -EAGAIN)
+                               goto again;
+                       pages[i] = NULL;
+                       return err;
+               }
        }
        return 0;
 }
 
-static inline void lock_extent_range(struct inode *inode, u64 off, u64 len)
+static int lock_extent_range(struct inode *inode, u64 off, u64 len,
+                            bool retry_range_locking)
 {
-       /* do any pending delalloc/csum calc on src, one way or
-          another, and lock file content */
+       /*
+        * Do any pending delalloc/csum calculations on inode, one way or
+        * another, and lock file content.
+        * The locking order is:
+        *
+        *   1) pages
+        *   2) range in the inode's io tree
+        */
        while (1) {
                struct btrfs_ordered_extent *ordered;
                lock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
@@ -2851,8 +2870,11 @@ static inline void lock_extent_range(struct inode *inode, u64 off, u64 len)
                unlock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
                if (ordered)
                        btrfs_put_ordered_extent(ordered);
+               if (!retry_range_locking)
+                       return -EAGAIN;
                btrfs_wait_ordered_range(inode, off, len);
        }
+       return 0;
 }
 
 static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2)
@@ -2877,15 +2899,24 @@ static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1,
        unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
 }
 
-static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
-                                    struct inode *inode2, u64 loff2, u64 len)
+static int btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
+                                   struct inode *inode2, u64 loff2, u64 len,
+                                   bool retry_range_locking)
 {
+       int ret;
+
        if (inode1 < inode2) {
                swap(inode1, inode2);
                swap(loff1, loff2);
        }
-       lock_extent_range(inode1, loff1, len);
-       lock_extent_range(inode2, loff2, len);
+       ret = lock_extent_range(inode1, loff1, len, retry_range_locking);
+       if (ret)
+               return ret;
+       ret = lock_extent_range(inode2, loff2, len, retry_range_locking);
+       if (ret)
+               unlock_extent(&BTRFS_I(inode1)->io_tree, loff1,
+                             loff1 + len - 1);
+       return ret;
 }
 
 struct cmp_pages {
@@ -2901,11 +2932,15 @@ static void btrfs_cmp_data_free(struct cmp_pages *cmp)
 
        for (i = 0; i < cmp->num_pages; i++) {
                pg = cmp->src_pages[i];
-               if (pg)
+               if (pg) {
+                       unlock_page(pg);
                        page_cache_release(pg);
+               }
                pg = cmp->dst_pages[i];
-               if (pg)
+               if (pg) {
+                       unlock_page(pg);
                        page_cache_release(pg);
+               }
        }
        kfree(cmp->src_pages);
        kfree(cmp->dst_pages);
@@ -2966,6 +3001,8 @@ static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst,
 
                src_page = cmp->src_pages[i];
                dst_page = cmp->dst_pages[i];
+               ASSERT(PageLocked(src_page));
+               ASSERT(PageLocked(dst_page));
 
                addr = kmap_atomic(src_page);
                dst_addr = kmap_atomic(dst_page);
@@ -3078,14 +3115,46 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
                goto out_unlock;
        }
 
+again:
        ret = btrfs_cmp_data_prepare(src, loff, dst, dst_loff, olen, &cmp);
        if (ret)
                goto out_unlock;
 
        if (same_inode)
-               lock_extent_range(src, same_lock_start, same_lock_len);
+               ret = lock_extent_range(src, same_lock_start, same_lock_len,
+                                       false);
        else
-               btrfs_double_extent_lock(src, loff, dst, dst_loff, len);
+               ret = btrfs_double_extent_lock(src, loff, dst, dst_loff, len,
+                                              false);
+       /*
+        * If one of the inodes has dirty pages in the respective range or
+        * ordered extents, we need to flush dellaloc and wait for all ordered
+        * extents in the range. We must unlock the pages and the ranges in the
+        * io trees to avoid deadlocks when flushing delalloc (requires locking
+        * pages) and when waiting for ordered extents to complete (they require
+        * range locking).
+        */
+       if (ret == -EAGAIN) {
+               /*
+                * Ranges in the io trees already unlocked. Now unlock all
+                * pages before waiting for all IO to complete.
+                */
+               btrfs_cmp_data_free(&cmp);
+               if (same_inode) {
+                       btrfs_wait_ordered_range(src, same_lock_start,
+                                                same_lock_len);
+               } else {
+                       btrfs_wait_ordered_range(src, loff, len);
+                       btrfs_wait_ordered_range(dst, dst_loff, len);
+               }
+               goto again;
+       }
+       ASSERT(ret == 0);
+       if (WARN_ON(ret)) {
+               /* ranges in the io trees already unlocked */
+               btrfs_cmp_data_free(&cmp);
+               return ret;
+       }
 
        /* pass original length for comparison so we stay within i_size */
        ret = btrfs_cmp_data(src, loff, dst, dst_loff, olen, &cmp);
@@ -3795,9 +3864,15 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
                u64 lock_start = min_t(u64, off, destoff);
                u64 lock_len = max_t(u64, off, destoff) + len - lock_start;
 
-               lock_extent_range(src, lock_start, lock_len);
+               ret = lock_extent_range(src, lock_start, lock_len, true);
        } else {
-               btrfs_double_extent_lock(src, off, inode, destoff, len);
+               ret = btrfs_double_extent_lock(src, off, inode, destoff, len,
+                                              true);
+       }
+       ASSERT(ret == 0);
+       if (WARN_ON(ret)) {
+               /* ranges in the io trees already unlocked */
+               goto out_unlock;
        }
 
        ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
index 7cf8509deda7c0ea6e98af02a8ab0acafbe016b2..2c849b08a91b53e0a7f1c475301a77d623cb5293 100644 (file)
@@ -310,8 +310,16 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
                set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
 
                err = btrfs_insert_fs_root(root->fs_info, root);
+               /*
+                * The root might have been inserted already, as before we look
+                * for orphan roots, log replay might have happened, which
+                * triggers a transaction commit and qgroup accounting, which
+                * in turn reads and inserts fs roots while doing backref
+                * walking.
+                */
+               if (err == -EEXIST)
+                       err = 0;
                if (err) {
-                       BUG_ON(err == -EEXIST);
                        btrfs_free_fs_root(root);
                        break;
                }
index c22213789090f975b3680b10e022a1e5f2f9fdb4..19adeb0ef82a397f122682db3a9ba31f56df5f5d 100644 (file)
@@ -1756,6 +1756,10 @@ int ceph_pool_perm_check(struct ceph_inode_info *ci, int need)
        u32 pool;
        int ret, flags;
 
+       /* does not support pool namespace yet */
+       if (ci->i_pool_ns_len)
+               return -EIO;
+
        if (ceph_test_mount_opt(ceph_inode_to_client(&ci->vfs_inode),
                                NOPOOLPERM))
                return 0;
index cdbf8cf3d52c3354569b7c86a709f4ce3fc09e2c..6fe0ad26a7dfc0430da9e9e0fca8c312a4b2bdc0 100644 (file)
@@ -2753,7 +2753,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
                             void *inline_data, int inline_len,
                             struct ceph_buffer *xattr_buf,
                             struct ceph_mds_session *session,
-                            struct ceph_cap *cap, int issued)
+                            struct ceph_cap *cap, int issued,
+                            u32 pool_ns_len)
        __releases(ci->i_ceph_lock)
        __releases(mdsc->snap_rwsem)
 {
@@ -2873,6 +2874,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
        if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
                /* file layout may have changed */
                ci->i_layout = grant->layout;
+               ci->i_pool_ns_len = pool_ns_len;
+
                /* size/truncate_seq? */
                queue_trunc = ceph_fill_file_size(inode, issued,
                                        le32_to_cpu(grant->truncate_seq),
@@ -3411,6 +3414,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        u32  inline_len = 0;
        void *snaptrace;
        size_t snaptrace_len;
+       u32 pool_ns_len = 0;
        void *p, *end;
 
        dout("handle_caps from mds%d\n", mds);
@@ -3463,6 +3467,21 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                p += inline_len;
        }
 
+       if (le16_to_cpu(msg->hdr.version) >= 8) {
+               u64 flush_tid;
+               u32 caller_uid, caller_gid;
+               u32 osd_epoch_barrier;
+               /* version >= 5 */
+               ceph_decode_32_safe(&p, end, osd_epoch_barrier, bad);
+               /* version >= 6 */
+               ceph_decode_64_safe(&p, end, flush_tid, bad);
+               /* version >= 7 */
+               ceph_decode_32_safe(&p, end, caller_uid, bad);
+               ceph_decode_32_safe(&p, end, caller_gid, bad);
+               /* version >= 8 */
+               ceph_decode_32_safe(&p, end, pool_ns_len, bad);
+       }
+
        /* lookup ino */
        inode = ceph_find_inode(sb, vino);
        ci = ceph_inode(inode);
@@ -3518,7 +3537,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                                  &cap, &issued);
                handle_cap_grant(mdsc, inode, h,
                                 inline_version, inline_data, inline_len,
-                                msg->middle, session, cap, issued);
+                                msg->middle, session, cap, issued,
+                                pool_ns_len);
                if (realm)
                        ceph_put_snap_realm(mdsc, realm);
                goto done_unlocked;
@@ -3542,7 +3562,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                issued |= __ceph_caps_dirty(ci);
                handle_cap_grant(mdsc, inode, h,
                                 inline_version, inline_data, inline_len,
-                                msg->middle, session, cap, issued);
+                                msg->middle, session, cap, issued,
+                                pool_ns_len);
                goto done_unlocked;
 
        case CEPH_CAP_OP_FLUSH_ACK:
index fb4ba2e4e2a5fa5c5d62afa3b94f758c7906687b..5849b88bbed3cfc333318574db80ded6305e0d9c 100644 (file)
@@ -396,6 +396,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
        ci->i_symlink = NULL;
 
        memset(&ci->i_dir_layout, 0, sizeof(ci->i_dir_layout));
+       ci->i_pool_ns_len = 0;
 
        ci->i_fragtree = RB_ROOT;
        mutex_init(&ci->i_fragtree_mutex);
@@ -756,6 +757,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
                if (ci->i_layout.fl_pg_pool != info->layout.fl_pg_pool)
                        ci->i_ceph_flags &= ~CEPH_I_POOL_PERM;
                ci->i_layout = info->layout;
+               ci->i_pool_ns_len = iinfo->pool_ns_len;
 
                queue_trunc = ceph_fill_file_size(inode, issued,
                                        le32_to_cpu(info->truncate_seq),
index e7b130a637f9f31a34efd67d6cf5789a8fcdef00..911d64d865f176aa4ce28832207abb8651a4fec8 100644 (file)
@@ -100,6 +100,14 @@ static int parse_reply_info_in(void **p, void *end,
        } else
                info->inline_version = CEPH_INLINE_NONE;
 
+       if (features & CEPH_FEATURE_FS_FILE_LAYOUT_V2) {
+               ceph_decode_32_safe(p, end, info->pool_ns_len, bad);
+               ceph_decode_need(p, end, info->pool_ns_len, bad);
+               *p += info->pool_ns_len;
+       } else {
+               info->pool_ns_len = 0;
+       }
+
        return 0;
 bad:
        return err;
@@ -2298,6 +2306,14 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
                ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
                                  CEPH_CAP_PIN);
 
+       /* deny access to directories with pool_ns layouts */
+       if (req->r_inode && S_ISDIR(req->r_inode->i_mode) &&
+           ceph_inode(req->r_inode)->i_pool_ns_len)
+               return -EIO;
+       if (req->r_locked_dir &&
+           ceph_inode(req->r_locked_dir)->i_pool_ns_len)
+               return -EIO;
+
        /* issue */
        mutex_lock(&mdsc->mutex);
        __register_request(mdsc, req, dir);
index ccf11ef0ca8717f79e6bfc9d6cf806ec359b5e8c..37712ccffcc6b67c2f98a866c9c2be40324bc6ae 100644 (file)
@@ -44,6 +44,7 @@ struct ceph_mds_reply_info_in {
        u64 inline_version;
        u32 inline_len;
        char *inline_data;
+       u32 pool_ns_len;
 };
 
 /*
index 75b7d125ce668a9b3f4f851d2be1c688d6d5f964..9c458eb522458da2364238cef2e92530ace87df9 100644 (file)
@@ -287,6 +287,7 @@ struct ceph_inode_info {
 
        struct ceph_dir_layout i_dir_layout;
        struct ceph_file_layout i_layout;
+       size_t i_pool_ns_len;
        char *i_symlink;
 
        /* for dirs */
index 7dc886c9a78fc428b368a1c911b8c1ad745f48a5..e956cba94338184416c96925690f21493fc61ab6 100644 (file)
@@ -175,7 +175,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
         * string to the length of the original string to allow for worst case.
         */
        md_len = strlen(sb_mountdata) + INET6_ADDRSTRLEN;
-       mountdata = kzalloc(md_len + 1, GFP_KERNEL);
+       mountdata = kzalloc(md_len + sizeof("ip=") + 1, GFP_KERNEL);
        if (mountdata == NULL) {
                rc = -ENOMEM;
                goto compose_mount_options_err;
index afa09fce81515e4caf7500b04c16dfb96a71cfd1..e682b36a210f236561817bd11a799d3a8f57caf2 100644 (file)
@@ -714,7 +714,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 
        ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
        if (!ses->auth_key.response) {
-               rc = ENOMEM;
+               rc = -ENOMEM;
                ses->auth_key.len = 0;
                goto setup_ntlmv2_rsp_ret;
        }
index c48ca13673e37f2eba7c4045f140e6e8b740e499..2eea40353e6086fc808da8c74deeaaf158a43da9 100644 (file)
@@ -1013,7 +1013,6 @@ const struct file_operations cifs_file_strict_ops = {
        .llseek = cifs_llseek,
        .unlocked_ioctl = cifs_ioctl,
        .clone_file_range = cifs_clone_file_range,
-       .clone_file_range = cifs_clone_file_range,
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
 };
index 68c4547528c486f2477a8177692374dd6033e2bf..83aac8ba50b0e168ec5b2a252c8b77daf9c2428b 100644 (file)
  * so that it will fit. We use hash_64 to convert the value to 31 bits, and
  * then add 1, to ensure that we don't end up with a 0 as the value.
  */
-#if BITS_PER_LONG == 64
 static inline ino_t
 cifs_uniqueid_to_ino_t(u64 fileid)
 {
+       if ((sizeof(ino_t)) < (sizeof(u64)))
+               return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
+
        return (ino_t)fileid;
+
 }
-#else
-static inline ino_t
-cifs_uniqueid_to_ino_t(u64 fileid)
-{
-       return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
-}
-#endif
 
 extern struct file_system_type cifs_fs_type;
 extern const struct address_space_operations cifs_addr_ops;
index 90b4f9f7de660a261b5f93322af59282294953fd..76fcb50295a38b63a58a0d3f656d023e02b988a8 100644 (file)
@@ -1396,11 +1396,10 @@ openRetry:
  * current bigbuf.
  */
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+discard_remaining_data(struct TCP_Server_Info *server)
 {
        unsigned int rfclen = get_rfc1002_length(server->smallbuf);
        int remaining = rfclen + 4 - server->total_read;
-       struct cifs_readdata *rdata = mid->callback_data;
 
        while (remaining > 0) {
                int length;
@@ -1414,10 +1413,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                remaining -= length;
        }
 
-       dequeue_mid(mid, rdata->result);
        return 0;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+       int length;
+       struct cifs_readdata *rdata = mid->callback_data;
+
+       length = discard_remaining_data(server);
+       dequeue_mid(mid, rdata->result);
+       return length;
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1446,6 +1455,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                return length;
        server->total_read += length;
 
+       if (server->ops->is_status_pending &&
+           server->ops->is_status_pending(buf, server, 0)) {
+               discard_remaining_data(server);
+               return -1;
+       }
+
        /* Was the SMB read successful? */
        rdata->result = server->ops->map_error(buf, false);
        if (rdata->result != 0) {
index 4fbd92d2e113e69d5e3105235a215a52b2e756e7..a763cd3d9e7c80589df30ddaa9515906c6fa6138 100644 (file)
@@ -2999,8 +2999,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server)
        if (ses_init_buf) {
                ses_init_buf->trailer.session_req.called_len = 32;
 
-               if (server->server_RFC1001_name &&
-                   server->server_RFC1001_name[0] != 0)
+               if (server->server_RFC1001_name[0] != 0)
                        rfc1002mangle(ses_init_buf->trailer.
                                      session_req.called_name,
                                      server->server_RFC1001_name,
index 10f8d5cf5681e26b843c0ac15821eab69e6eeb22..42e1f440eb1e9ae1ca497c7f8127ff58b7988b77 100644 (file)
@@ -1106,21 +1106,25 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
 {
        char *data_offset;
        struct create_context *cc;
-       unsigned int next = 0;
+       unsigned int next;
+       unsigned int remaining;
        char *name;
 
        data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
+       remaining = le32_to_cpu(rsp->CreateContextsLength);
        cc = (struct create_context *)data_offset;
-       do {
-               cc = (struct create_context *)((char *)cc + next);
+       while (remaining >= sizeof(struct create_context)) {
                name = le16_to_cpu(cc->NameOffset) + (char *)cc;
-               if (le16_to_cpu(cc->NameLength) != 4 ||
-                   strncmp(name, "RqLs", 4)) {
-                       next = le32_to_cpu(cc->Next);
-                       continue;
-               }
-               return server->ops->parse_lease_buf(cc, epoch);
-       } while (next != 0);
+               if (le16_to_cpu(cc->NameLength) == 4 &&
+                   strncmp(name, "RqLs", 4) == 0)
+                       return server->ops->parse_lease_buf(cc, epoch);
+
+               next = le32_to_cpu(cc->Next);
+               if (!next)
+                       break;
+               remaining -= next;
+               cc = (struct create_context *)((char *)cc + next);
+       }
 
        return 0;
 }
index fc2e3141138b285321abdbe059e53dfd40162719..711172450da642ccdcf4ac7dcceb7546faf66fad 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -79,15 +79,14 @@ struct page *read_dax_sector(struct block_device *bdev, sector_t n)
 }
 
 /*
- * dax_clear_blocks() is called from within transaction context from XFS,
+ * dax_clear_sectors() is called from within transaction context from XFS,
  * and hence this means the stack from this point must follow GFP_NOFS
  * semantics for all operations.
  */
-int dax_clear_blocks(struct inode *inode, sector_t block, long _size)
+int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size)
 {
-       struct block_device *bdev = inode->i_sb->s_bdev;
        struct blk_dax_ctl dax = {
-               .sector = block << (inode->i_blkbits - 9),
+               .sector = _sector,
                .size = _size,
        };
 
@@ -109,7 +108,7 @@ int dax_clear_blocks(struct inode *inode, sector_t block, long _size)
        wmb_pmem();
        return 0;
 }
-EXPORT_SYMBOL_GPL(dax_clear_blocks);
+EXPORT_SYMBOL_GPL(dax_clear_sectors);
 
 /* the clear_pmem() calls are ordered by a wmb_pmem() in the caller */
 static void dax_new_buf(void __pmem *addr, unsigned size, unsigned first,
@@ -485,11 +484,10 @@ static int dax_writeback_one(struct block_device *bdev,
  * end]. This is required by data integrity operations to ensure file data is
  * on persistent storage prior to completion of the operation.
  */
-int dax_writeback_mapping_range(struct address_space *mapping, loff_t start,
-               loff_t end)
+int dax_writeback_mapping_range(struct address_space *mapping,
+               struct block_device *bdev, struct writeback_control *wbc)
 {
        struct inode *inode = mapping->host;
-       struct block_device *bdev = inode->i_sb->s_bdev;
        pgoff_t start_index, end_index, pmd_index;
        pgoff_t indices[PAGEVEC_SIZE];
        struct pagevec pvec;
@@ -500,8 +498,11 @@ int dax_writeback_mapping_range(struct address_space *mapping, loff_t start,
        if (WARN_ON_ONCE(inode->i_blkbits != PAGE_SHIFT))
                return -EIO;
 
-       start_index = start >> PAGE_CACHE_SHIFT;
-       end_index = end >> PAGE_CACHE_SHIFT;
+       if (!mapping->nrexceptional || wbc->sync_mode != WB_SYNC_ALL)
+               return 0;
+
+       start_index = wbc->range_start >> PAGE_CACHE_SHIFT;
+       end_index = wbc->range_end >> PAGE_CACHE_SHIFT;
        pmd_index = DAX_PMD_INDEX(start_index);
 
        rcu_read_lock();
index 92d5140de8516c642b6ea5af81f0ffe89399a416..2398f9f9433752aa53dbd3af4cfe0f82aba22d99 100644 (file)
@@ -269,9 +269,6 @@ static inline int dname_external(const struct dentry *dentry)
        return dentry->d_name.name != dentry->d_iname;
 }
 
-/*
- * Make sure other CPUs see the inode attached before the type is set.
- */
 static inline void __d_set_inode_and_type(struct dentry *dentry,
                                          struct inode *inode,
                                          unsigned type_flags)
@@ -279,28 +276,18 @@ static inline void __d_set_inode_and_type(struct dentry *dentry,
        unsigned flags;
 
        dentry->d_inode = inode;
-       smp_wmb();
        flags = READ_ONCE(dentry->d_flags);
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        flags |= type_flags;
        WRITE_ONCE(dentry->d_flags, flags);
 }
 
-/*
- * Ideally, we want to make sure that other CPUs see the flags cleared before
- * the inode is detached, but this is really a violation of RCU principles
- * since the ordering suggests we should always set inode before flags.
- *
- * We should instead replace or discard the entire dentry - but that sucks
- * performancewise on mass deletion/rename.
- */
 static inline void __d_clear_type_and_inode(struct dentry *dentry)
 {
        unsigned flags = READ_ONCE(dentry->d_flags);
 
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        WRITE_ONCE(dentry->d_flags, flags);
-       smp_wmb();
        dentry->d_inode = NULL;
 }
 
@@ -370,9 +357,11 @@ static void dentry_unlink_inode(struct dentry * dentry)
        __releases(dentry->d_inode->i_lock)
 {
        struct inode *inode = dentry->d_inode;
+
+       raw_write_seqcount_begin(&dentry->d_seq);
        __d_clear_type_and_inode(dentry);
        hlist_del_init(&dentry->d_u.d_alias);
-       dentry_rcuwalk_invalidate(dentry);
+       raw_write_seqcount_end(&dentry->d_seq);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
        if (!inode->i_nlink)
@@ -1758,8 +1747,9 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        spin_lock(&dentry->d_lock);
        if (inode)
                hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
+       raw_write_seqcount_begin(&dentry->d_seq);
        __d_set_inode_and_type(dentry, inode, add_flags);
-       dentry_rcuwalk_invalidate(dentry);
+       raw_write_seqcount_end(&dentry->d_seq);
        spin_unlock(&dentry->d_lock);
        fsnotify_d_instantiate(dentry, inode);
 }
index 1f107fd513286f0f3e8be601cd715ea0ee5443e8..655f21f991606b5bf2bef600a54b814994dbed98 100644 (file)
@@ -575,6 +575,26 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
        mutex_unlock(&allocated_ptys_lock);
 }
 
+/*
+ * pty code needs to hold extra references in case of last /dev/tty close
+ */
+
+void devpts_add_ref(struct inode *ptmx_inode)
+{
+       struct super_block *sb = pts_sb_from_inode(ptmx_inode);
+
+       atomic_inc(&sb->s_active);
+       ihold(ptmx_inode);
+}
+
+void devpts_del_ref(struct inode *ptmx_inode)
+{
+       struct super_block *sb = pts_sb_from_inode(ptmx_inode);
+
+       iput(ptmx_inode);
+       deactivate_super(sb);
+}
+
 /**
  * devpts_pty_new -- create a new inode in /dev/pts/
  * @ptmx_inode: inode of the master
index 1b2f7ffc8b841fd16cf312874fe8c7d4c0fa0e8e..d6a9012d42ad570f231a1f48c6706c6af8d5a598 100644 (file)
@@ -472,8 +472,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
                dio->io_error = -EIO;
 
        if (dio->is_async && dio->rw == READ && dio->should_dirty) {
-               bio_check_pages_dirty(bio);     /* transfers ownership */
                err = bio->bi_error;
+               bio_check_pages_dirty(bio);     /* transfers ownership */
        } else {
                bio_for_each_segment_all(bvec, bio, i) {
                        struct page *page = bvec->bv_page;
index c424e4813ec8019b5f8a62feb8eb51c6d13f7f97..d48e0d261d78da6e1ce2830e65000e37ed4bd292 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/efi.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/mount.h>
 
 #include "internal.h"
 
@@ -103,9 +104,78 @@ out_free:
        return size;
 }
 
+static int
+efivarfs_ioc_getxflags(struct file *file, void __user *arg)
+{
+       struct inode *inode = file->f_mapping->host;
+       unsigned int i_flags;
+       unsigned int flags = 0;
+
+       i_flags = inode->i_flags;
+       if (i_flags & S_IMMUTABLE)
+               flags |= FS_IMMUTABLE_FL;
+
+       if (copy_to_user(arg, &flags, sizeof(flags)))
+               return -EFAULT;
+       return 0;
+}
+
+static int
+efivarfs_ioc_setxflags(struct file *file, void __user *arg)
+{
+       struct inode *inode = file->f_mapping->host;
+       unsigned int flags;
+       unsigned int i_flags = 0;
+       int error;
+
+       if (!inode_owner_or_capable(inode))
+               return -EACCES;
+
+       if (copy_from_user(&flags, arg, sizeof(flags)))
+               return -EFAULT;
+
+       if (flags & ~FS_IMMUTABLE_FL)
+               return -EOPNOTSUPP;
+
+       if (!capable(CAP_LINUX_IMMUTABLE))
+               return -EPERM;
+
+       if (flags & FS_IMMUTABLE_FL)
+               i_flags |= S_IMMUTABLE;
+
+
+       error = mnt_want_write_file(file);
+       if (error)
+               return error;
+
+       inode_lock(inode);
+       inode_set_flags(inode, i_flags, S_IMMUTABLE);
+       inode_unlock(inode);
+
+       mnt_drop_write_file(file);
+
+       return 0;
+}
+
+long
+efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p)
+{
+       void __user *arg = (void __user *)p;
+
+       switch (cmd) {
+       case FS_IOC_GETFLAGS:
+               return efivarfs_ioc_getxflags(file, arg);
+       case FS_IOC_SETFLAGS:
+               return efivarfs_ioc_setxflags(file, arg);
+       }
+
+       return -ENOTTY;
+}
+
 const struct file_operations efivarfs_file_operations = {
        .open   = simple_open,
        .read   = efivarfs_file_read,
        .write  = efivarfs_file_write,
        .llseek = no_llseek,
+       .unlocked_ioctl = efivarfs_file_ioctl,
 };
index 3381b9da9ee6080881720f0500b71c74ecdf6058..e2ab6d0497f2bb86dee165421487d27e4b64ba0d 100644 (file)
@@ -15,7 +15,8 @@
 #include "internal.h"
 
 struct inode *efivarfs_get_inode(struct super_block *sb,
-                               const struct inode *dir, int mode, dev_t dev)
+                               const struct inode *dir, int mode,
+                               dev_t dev, bool is_removable)
 {
        struct inode *inode = new_inode(sb);
 
@@ -23,6 +24,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb,
                inode->i_ino = get_next_ino();
                inode->i_mode = mode;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               inode->i_flags = is_removable ? 0 : S_IMMUTABLE;
                switch (mode & S_IFMT) {
                case S_IFREG:
                        inode->i_fop = &efivarfs_file_operations;
@@ -102,22 +104,17 @@ static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
 static int efivarfs_create(struct inode *dir, struct dentry *dentry,
                          umode_t mode, bool excl)
 {
-       struct inode *inode;
+       struct inode *inode = NULL;
        struct efivar_entry *var;
        int namelen, i = 0, err = 0;
+       bool is_removable = false;
 
        if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
                return -EINVAL;
 
-       inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
-       if (!inode)
-               return -ENOMEM;
-
        var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
-       if (!var) {
-               err = -ENOMEM;
-               goto out;
-       }
+       if (!var)
+               return -ENOMEM;
 
        /* length of the variable name itself: remove GUID and separator */
        namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1;
@@ -125,6 +122,16 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
        efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
                        &var->var.VendorGuid);
 
+       if (efivar_variable_is_removable(var->var.VendorGuid,
+                                        dentry->d_name.name, namelen))
+               is_removable = true;
+
+       inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0, is_removable);
+       if (!inode) {
+               err = -ENOMEM;
+               goto out;
+       }
+
        for (i = 0; i < namelen; i++)
                var->var.VariableName[i] = dentry->d_name.name[i];
 
@@ -138,7 +145,8 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
 out:
        if (err) {
                kfree(var);
-               iput(inode);
+               if (inode)
+                       iput(inode);
        }
        return err;
 }
index b5ff16addb7ce0984d14d2efe0324be884d20911..b4505188e799b9f5f50b2f792090775fd4244127 100644 (file)
@@ -15,7 +15,8 @@ extern const struct file_operations efivarfs_file_operations;
 extern const struct inode_operations efivarfs_dir_inode_operations;
 extern bool efivarfs_valid_name(const char *str, int len);
 extern struct inode *efivarfs_get_inode(struct super_block *sb,
-                       const struct inode *dir, int mode, dev_t dev);
+                       const struct inode *dir, int mode, dev_t dev,
+                       bool is_removable);
 
 extern struct list_head efivarfs_list;
 
index b8a564f29107b6d38e90b54d99c86f4aa4b96532..dd029d13ea6140f7df1ed99fb2634a9c858f801f 100644 (file)
@@ -118,8 +118,9 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
        struct dentry *dentry, *root = sb->s_root;
        unsigned long size = 0;
        char *name;
-       int len, i;
+       int len;
        int err = -ENOMEM;
+       bool is_removable = false;
 
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
@@ -128,15 +129,17 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
        memcpy(entry->var.VariableName, name16, name_size);
        memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
 
-       len = ucs2_strlen(entry->var.VariableName);
+       len = ucs2_utf8size(entry->var.VariableName);
 
        /* name, plus '-', plus GUID, plus NUL*/
        name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
        if (!name)
                goto fail;
 
-       for (i = 0; i < len; i++)
-               name[i] = entry->var.VariableName[i] & 0xFF;
+       ucs2_as_utf8(name, entry->var.VariableName, len);
+
+       if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
+               is_removable = true;
 
        name[len] = '-';
 
@@ -144,7 +147,8 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
 
        name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
 
-       inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0);
+       inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0,
+                                  is_removable);
        if (!inode)
                goto fail_name;
 
@@ -200,7 +204,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_d_op              = &efivarfs_d_ops;
        sb->s_time_gran         = 1;
 
-       inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
+       inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
        if (!inode)
                return -ENOMEM;
        inode->i_op = &efivarfs_dir_inode_operations;
index 2c88d683cd918d673c83390aea187e763b5aa78e..c1400b109805b8778d8ee947ecad3060539f5ebe 100644 (file)
@@ -80,23 +80,6 @@ static int ext2_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
        return ret;
 }
 
-static int ext2_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct inode *inode = file_inode(vma->vm_file);
-       struct ext2_inode_info *ei = EXT2_I(inode);
-       int ret;
-
-       sb_start_pagefault(inode->i_sb);
-       file_update_time(vma->vm_file);
-       down_read(&ei->dax_sem);
-
-       ret = __dax_mkwrite(vma, vmf, ext2_get_block, NULL);
-
-       up_read(&ei->dax_sem);
-       sb_end_pagefault(inode->i_sb);
-       return ret;
-}
-
 static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma,
                struct vm_fault *vmf)
 {
@@ -124,7 +107,7 @@ static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma,
 static const struct vm_operations_struct ext2_dax_vm_ops = {
        .fault          = ext2_dax_fault,
        .pmd_fault      = ext2_dax_pmd_fault,
-       .page_mkwrite   = ext2_dax_mkwrite,
+       .page_mkwrite   = ext2_dax_fault,
        .pfn_mkwrite    = ext2_dax_pfn_mkwrite,
 };
 
index 338eefda70c6fc4e2055c0165b590febf1295acb..6bd58e6ff038657f75b93857bad455ebdfedfa0f 100644 (file)
@@ -737,8 +737,10 @@ static int ext2_get_blocks(struct inode *inode,
                 * so that it's not found by another thread before it's
                 * initialised
                 */
-               err = dax_clear_blocks(inode, le32_to_cpu(chain[depth-1].key),
-                                               1 << inode->i_blkbits);
+               err = dax_clear_sectors(inode->i_sb->s_bdev,
+                               le32_to_cpu(chain[depth-1].key) <<
+                               (inode->i_blkbits - 9),
+                               1 << inode->i_blkbits);
                if (err) {
                        mutex_unlock(&ei->truncate_mutex);
                        goto cleanup;
@@ -874,6 +876,14 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
 static int
 ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
+#ifdef CONFIG_FS_DAX
+       if (dax_mapping(mapping)) {
+               return dax_writeback_mapping_range(mapping,
+                                                  mapping->host->i_sb->s_bdev,
+                                                  wbc);
+       }
+#endif
+
        return mpage_writepages(mapping, wbc, ext2_get_block);
 }
 
@@ -1296,7 +1306,7 @@ void ext2_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_NOATIME;
        if (flags & EXT2_DIRSYNC_FL)
                inode->i_flags |= S_DIRSYNC;
-       if (test_opt(inode->i_sb, DAX))
+       if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
                inode->i_flags |= S_DAX;
 }
 
index ec0668a60678d215dadc9baa97623ddbd3dbc160..fe1f50fe764ff9238354e2e30491c6e1e6d149b9 100644 (file)
@@ -191,7 +191,6 @@ static int ext4_init_block_bitmap(struct super_block *sb,
        /* If checksum is bad mark all blocks used to prevent allocation
         * essentially implementing a per-group read-only flag. */
        if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
-               ext4_error(sb, "Checksum bad for group %u", block_group);
                grp = ext4_get_group_info(sb, block_group);
                if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
                        percpu_counter_sub(&sbi->s_freeclusters_counter,
@@ -442,14 +441,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
        }
        ext4_lock_group(sb, block_group);
        if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
-
                err = ext4_init_block_bitmap(sb, bh, block_group, desc);
                set_bitmap_uptodate(bh);
                set_buffer_uptodate(bh);
                ext4_unlock_group(sb, block_group);
                unlock_buffer(bh);
-               if (err)
+               if (err) {
+                       ext4_error(sb, "Failed to init block bitmap for group "
+                                  "%u: %d", block_group, err);
                        goto out;
+               }
                goto verify;
        }
        ext4_unlock_group(sb, block_group);
index c8021208a7eb1a98ba32e16a8536146f570d5c4a..38f7562489bbb0ccdea3085bbfcbcf4098210203 100644 (file)
@@ -467,3 +467,59 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size)
                return size;
        return 0;
 }
+
+/*
+ * Validate dentries for encrypted directories to make sure we aren't
+ * potentially caching stale data after a key has been added or
+ * removed.
+ */
+static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       struct inode *dir = d_inode(dentry->d_parent);
+       struct ext4_crypt_info *ci = EXT4_I(dir)->i_crypt_info;
+       int dir_has_key, cached_with_key;
+
+       if (!ext4_encrypted_inode(dir))
+               return 0;
+
+       if (ci && ci->ci_keyring_key &&
+           (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+                                         (1 << KEY_FLAG_REVOKED) |
+                                         (1 << KEY_FLAG_DEAD))))
+               ci = NULL;
+
+       /* this should eventually be an flag in d_flags */
+       cached_with_key = dentry->d_fsdata != NULL;
+       dir_has_key = (ci != NULL);
+
+       /*
+        * If the dentry was cached without the key, and it is a
+        * negative dentry, it might be a valid name.  We can't check
+        * if the key has since been made available due to locking
+        * reasons, so we fail the validation so ext4_lookup() can do
+        * this check.
+        *
+        * We also fail the validation if the dentry was created with
+        * the key present, but we no longer have the key, or vice versa.
+        */
+       if ((!cached_with_key && d_is_negative(dentry)) ||
+           (!cached_with_key && dir_has_key) ||
+           (cached_with_key && !dir_has_key)) {
+#if 0                          /* Revalidation debug */
+               char buf[80];
+               char *cp = simple_dname(dentry, buf, sizeof(buf));
+
+               if (IS_ERR(cp))
+                       cp = (char *) "???";
+               pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata,
+                      cached_with_key, d_is_negative(dentry),
+                      dir_has_key);
+#endif
+               return 0;
+       }
+       return 1;
+}
+
+const struct dentry_operations ext4_encrypted_d_ops = {
+       .d_revalidate = ext4_d_revalidate,
+};
index 1d1bca74f84437172d96c26e648e6ed45e129725..33f5e2a50cf883c43842e1c89a868fcf70c4c2a9 100644 (file)
@@ -111,6 +111,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
        int dir_has_error = 0;
        struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
 
+       if (ext4_encrypted_inode(inode)) {
+               err = ext4_get_encryption_info(inode);
+               if (err && err != -ENOKEY)
+                       return err;
+       }
+
        if (is_dx_dir(inode)) {
                err = ext4_dx_readdir(file, ctx);
                if (err != ERR_BAD_DX_DIR) {
@@ -157,8 +163,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                                        index, 1);
                        file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
                        bh = ext4_bread(NULL, inode, map.m_lblk, 0);
-                       if (IS_ERR(bh))
-                               return PTR_ERR(bh);
+                       if (IS_ERR(bh)) {
+                               err = PTR_ERR(bh);
+                               bh = NULL;
+                               goto errout;
+                       }
                }
 
                if (!bh) {
index 0662b285dc8a71982a54e5895d58d797c7bcf6a4..157b458a69d4b7c334f28b80c37fd5d11c9f0c25 100644 (file)
@@ -2302,6 +2302,7 @@ struct page *ext4_encrypt(struct inode *inode,
 int ext4_decrypt(struct page *page);
 int ext4_encrypted_zeroout(struct inode *inode, ext4_lblk_t lblk,
                           ext4_fsblk_t pblk, ext4_lblk_t len);
+extern const struct dentry_operations ext4_encrypted_d_ops;
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
 int ext4_init_crypto(void);
index 0ffabaf90aa5d19914aaf9e3cbeca44922f15f86..3753ceb0b0dd7b610c8e3ddefe4b992c07416fff 100644 (file)
@@ -3928,7 +3928,7 @@ static int
 convert_initialized_extent(handle_t *handle, struct inode *inode,
                           struct ext4_map_blocks *map,
                           struct ext4_ext_path **ppath, int flags,
-                          unsigned int allocated, ext4_fsblk_t newblock)
+                          unsigned int allocated)
 {
        struct ext4_ext_path *path = *ppath;
        struct ext4_extent *ex;
@@ -4347,7 +4347,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
                            (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
                                allocated = convert_initialized_extent(
                                                handle, inode, map, &path,
-                                               flags, allocated, newblock);
+                                               flags, allocated);
                                goto out2;
                        } else if (!ext4_ext_is_unwritten(ex))
                                goto out;
index 1126436dada19519b97240bcdb42995acae46724..4cd318f31cbeff21979d552cab7390c6df76a5c9 100644 (file)
@@ -262,23 +262,8 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
        return result;
 }
 
-static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       int err;
-       struct inode *inode = file_inode(vma->vm_file);
-
-       sb_start_pagefault(inode->i_sb);
-       file_update_time(vma->vm_file);
-       down_read(&EXT4_I(inode)->i_mmap_sem);
-       err = __dax_mkwrite(vma, vmf, ext4_dax_mmap_get_block, NULL);
-       up_read(&EXT4_I(inode)->i_mmap_sem);
-       sb_end_pagefault(inode->i_sb);
-
-       return err;
-}
-
 /*
- * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite()
+ * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_fault()
  * handler we check for races agaist truncate. Note that since we cycle through
  * i_mmap_sem, we are sure that also any hole punching that began before we
  * were called is finished by now and so if it included part of the file we
@@ -311,7 +296,7 @@ static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma,
 static const struct vm_operations_struct ext4_dax_vm_ops = {
        .fault          = ext4_dax_fault,
        .pmd_fault      = ext4_dax_pmd_fault,
-       .page_mkwrite   = ext4_dax_mkwrite,
+       .page_mkwrite   = ext4_dax_fault,
        .pfn_mkwrite    = ext4_dax_pfn_mkwrite,
 };
 #else
@@ -350,6 +335,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
        struct super_block *sb = inode->i_sb;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct vfsmount *mnt = filp->f_path.mnt;
+       struct inode *dir = filp->f_path.dentry->d_parent->d_inode;
        struct path path;
        char buf[64], *cp;
        int ret;
@@ -393,6 +379,14 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
                if (ext4_encryption_info(inode) == NULL)
                        return -ENOKEY;
        }
+       if (ext4_encrypted_inode(dir) &&
+           !ext4_is_child_context_consistent_with_parent(dir, inode)) {
+               ext4_warning(inode->i_sb,
+                            "Inconsistent encryption contexts: %lu/%lu\n",
+                            (unsigned long) dir->i_ino,
+                            (unsigned long) inode->i_ino);
+               return -EPERM;
+       }
        /*
         * Set up the jbd2_inode if we are opening the inode for
         * writing and the journal is present
index 3fcfd50a2e8a0c05315d823fa1219bea2c87f6c8..acc0ad56bf2f43c5c3a95502342e83a28f8b4148 100644 (file)
@@ -76,7 +76,6 @@ static int ext4_init_inode_bitmap(struct super_block *sb,
        /* If checksum is bad mark all blocks and inodes use to prevent
         * allocation, essentially implementing a per-group read-only flag. */
        if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
-               ext4_error(sb, "Checksum bad for group %u", block_group);
                grp = ext4_get_group_info(sb, block_group);
                if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
                        percpu_counter_sub(&sbi->s_freeclusters_counter,
@@ -191,8 +190,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
                set_buffer_verified(bh);
                ext4_unlock_group(sb, block_group);
                unlock_buffer(bh);
-               if (err)
+               if (err) {
+                       ext4_error(sb, "Failed to init inode bitmap for group "
+                                  "%u: %d", block_group, err);
                        goto out;
+               }
                return bh;
        }
        ext4_unlock_group(sb, block_group);
index 83bc8bfb3bea8eeefed38ca46ae8260779222405..aee960b1af347e3407dd05f5a7095a7af4d8a96e 100644 (file)
@@ -686,6 +686,34 @@ out_sem:
        return retval;
 }
 
+/*
+ * Update EXT4_MAP_FLAGS in bh->b_state. For buffer heads attached to pages
+ * we have to be careful as someone else may be manipulating b_state as well.
+ */
+static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags)
+{
+       unsigned long old_state;
+       unsigned long new_state;
+
+       flags &= EXT4_MAP_FLAGS;
+
+       /* Dummy buffer_head? Set non-atomically. */
+       if (!bh->b_page) {
+               bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | flags;
+               return;
+       }
+       /*
+        * Someone else may be modifying b_state. Be careful! This is ugly but
+        * once we get rid of using bh as a container for mapping information
+        * to pass to / from get_block functions, this can go away.
+        */
+       do {
+               old_state = READ_ONCE(bh->b_state);
+               new_state = (old_state & ~EXT4_MAP_FLAGS) | flags;
+       } while (unlikely(
+                cmpxchg(&bh->b_state, old_state, new_state) != old_state));
+}
+
 /* Maximum number of blocks we map for direct IO at once. */
 #define DIO_MAX_BLOCKS 4096
 
@@ -722,7 +750,7 @@ static int _ext4_get_block(struct inode *inode, sector_t iblock,
                ext4_io_end_t *io_end = ext4_inode_aio(inode);
 
                map_bh(bh, inode->i_sb, map.m_pblk);
-               bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
+               ext4_update_bh_state(bh, map.m_flags);
                if (io_end && io_end->flag & EXT4_IO_END_UNWRITTEN)
                        set_buffer_defer_completion(bh);
                bh->b_size = inode->i_sb->s_blocksize * map.m_len;
@@ -1685,7 +1713,7 @@ int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
                return ret;
 
        map_bh(bh, inode->i_sb, map.m_pblk);
-       bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
+       ext4_update_bh_state(bh, map.m_flags);
 
        if (buffer_unwritten(bh)) {
                /* A delayed write to unwritten bh should be marked
@@ -2450,6 +2478,10 @@ static int ext4_writepages(struct address_space *mapping,
 
        trace_ext4_writepages(inode, wbc);
 
+       if (dax_mapping(mapping))
+               return dax_writeback_mapping_range(mapping, inode->i_sb->s_bdev,
+                                                  wbc);
+
        /*
         * No pages to write? This is mainly a kludge to avoid starting
         * a transaction for special inodes like journal inode on last iput()
@@ -3253,29 +3285,29 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
         * case, we allocate an io_end structure to hook to the iocb.
         */
        iocb->private = NULL;
-       ext4_inode_aio_set(inode, NULL);
-       if (!is_sync_kiocb(iocb)) {
-               io_end = ext4_init_io_end(inode, GFP_NOFS);
-               if (!io_end) {
-                       ret = -ENOMEM;
-                       goto retake_lock;
-               }
-               /*
-                * Grab reference for DIO. Will be dropped in ext4_end_io_dio()
-                */
-               iocb->private = ext4_get_io_end(io_end);
-               /*
-                * we save the io structure for current async direct
-                * IO, so that later ext4_map_blocks() could flag the
-                * io structure whether there is a unwritten extents
-                * needs to be converted when IO is completed.
-                */
-               ext4_inode_aio_set(inode, io_end);
-       }
-
        if (overwrite) {
                get_block_func = ext4_get_block_overwrite;
        } else {
+               ext4_inode_aio_set(inode, NULL);
+               if (!is_sync_kiocb(iocb)) {
+                       io_end = ext4_init_io_end(inode, GFP_NOFS);
+                       if (!io_end) {
+                               ret = -ENOMEM;
+                               goto retake_lock;
+                       }
+                       /*
+                        * Grab reference for DIO. Will be dropped in
+                        * ext4_end_io_dio()
+                        */
+                       iocb->private = ext4_get_io_end(io_end);
+                       /*
+                        * we save the io structure for current async direct
+                        * IO, so that later ext4_map_blocks() could flag the
+                        * io structure whether there is a unwritten extents
+                        * needs to be converted when IO is completed.
+                        */
+                       ext4_inode_aio_set(inode, io_end);
+               }
                get_block_func = ext4_get_block_write;
                dio_flags = DIO_LOCKING;
        }
@@ -4127,7 +4159,7 @@ void ext4_set_inode_flags(struct inode *inode)
                new_fl |= S_NOATIME;
        if (flags & EXT4_DIRSYNC_FL)
                new_fl |= S_DIRSYNC;
-       if (test_opt(inode->i_sb, DAX))
+       if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
                new_fl |= S_DAX;
        inode_set_flags(inode, new_fl,
                        S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX);
index 0f6c36922c2466116d610e8092bd17b64285c29c..eae5917c534e51b2fddf7bcebfa1293ed76a2841 100644 (file)
@@ -208,7 +208,7 @@ static int ext4_ioctl_setflags(struct inode *inode,
 {
        struct ext4_inode_info *ei = EXT4_I(inode);
        handle_t *handle = NULL;
-       int err = EPERM, migrate = 0;
+       int err = -EPERM, migrate = 0;
        struct ext4_iloc iloc;
        unsigned int oldflags, mask, i;
        unsigned int jflag;
@@ -583,6 +583,11 @@ group_extend_out:
                                 "Online defrag not supported with bigalloc");
                        err = -EOPNOTSUPP;
                        goto mext_out;
+               } else if (IS_DAX(inode)) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Online defrag not supported with DAX");
+                       err = -EOPNOTSUPP;
+                       goto mext_out;
                }
 
                err = mnt_want_write_file(filp);
index 61eaf74dca3794b122a9e782e87c568ac99a8a65..4424b7bf8ac64e431a11570e247a1d828634d29e 100644 (file)
@@ -2285,7 +2285,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
        if (group == 0)
                seq_puts(seq, "#group: free  frags first ["
                              " 2^0   2^1   2^2   2^3   2^4   2^5   2^6  "
-                             " 2^7   2^8   2^9   2^10  2^11  2^12  2^13  ]");
+                             " 2^7   2^8   2^9   2^10  2^11  2^12  2^13  ]\n");
 
        i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
                sizeof(struct ext4_group_info);
index fb6f11709ae62b4d0452352422bb6f3f50660ba3..e032a0423e351cabfd6fe6156cdfc9c53ebff216 100644 (file)
@@ -265,11 +265,12 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
        ext4_lblk_t orig_blk_offset, donor_blk_offset;
        unsigned long blocksize = orig_inode->i_sb->s_blocksize;
        unsigned int tmp_data_size, data_size, replaced_size;
-       int err2, jblocks, retries = 0;
+       int i, err2, jblocks, retries = 0;
        int replaced_count = 0;
        int from = data_offset_in_page << orig_inode->i_blkbits;
        int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
        struct super_block *sb = orig_inode->i_sb;
+       struct buffer_head *bh = NULL;
 
        /*
         * It needs twice the amount of ordinary journal buffers because
@@ -380,8 +381,16 @@ data_copy:
        }
        /* Perform all necessary steps similar write_begin()/write_end()
         * but keeping in mind that i_size will not change */
-       *err = __block_write_begin(pagep[0], from, replaced_size,
-                                  ext4_get_block);
+       if (!page_has_buffers(pagep[0]))
+               create_empty_buffers(pagep[0], 1 << orig_inode->i_blkbits, 0);
+       bh = page_buffers(pagep[0]);
+       for (i = 0; i < data_offset_in_page; i++)
+               bh = bh->b_this_page;
+       for (i = 0; i < block_len_in_page; i++) {
+               *err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0);
+               if (*err < 0)
+                       break;
+       }
        if (!*err)
                *err = block_commit_write(pagep[0], from, from + replaced_size);
 
index 06574dd77614a3b1c4396d5bb3c017c681209d00..48e4b8907826eca52a1e94e14bdfdb0fd2240c56 100644 (file)
@@ -1558,6 +1558,24 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
        struct ext4_dir_entry_2 *de;
        struct buffer_head *bh;
 
+       if (ext4_encrypted_inode(dir)) {
+               int res = ext4_get_encryption_info(dir);
+
+               /*
+                * This should be a properly defined flag for
+                * dentry->d_flags when we uplift this to the VFS.
+                * d_fsdata is set to (void *) 1 if if the dentry is
+                * created while the directory was encrypted and we
+                * don't have access to the key.
+                */
+              dentry->d_fsdata = NULL;
+              if (ext4_encryption_info(dir))
+                      dentry->d_fsdata = (void *) 1;
+              d_set_d_op(dentry, &ext4_encrypted_d_ops);
+              if (res && res != -ENOKEY)
+                      return ERR_PTR(res);
+       }
+
        if (dentry->d_name.len > EXT4_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
@@ -1585,11 +1603,15 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
                        return ERR_PTR(-EFSCORRUPTED);
                }
                if (!IS_ERR(inode) && ext4_encrypted_inode(dir) &&
-                   (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-                    S_ISLNK(inode->i_mode)) &&
+                   (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
                    !ext4_is_child_context_consistent_with_parent(dir,
                                                                  inode)) {
+                       int nokey = ext4_encrypted_inode(inode) &&
+                               !ext4_encryption_info(inode);
+
                        iput(inode);
+                       if (nokey)
+                               return ERR_PTR(-ENOKEY);
                        ext4_warning(inode->i_sb,
                                     "Inconsistent encryption contexts: %lu/%lu\n",
                                     (unsigned long) dir->i_ino,
index ad62d7acc31578df85c3b97ac7839295a4454008..34038e3598d59fa2b4bcaf2304d31602e803d5e0 100644 (file)
@@ -198,7 +198,7 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)
        if (flex_gd == NULL)
                goto out3;
 
-       if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data))
+       if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_group_data))
                goto out2;
        flex_gd->count = flexbg_size;
 
index 6915c950e6e8aeefb7c6162e7e7410de98f4e309..5c46ed9f3e14087d4fa7bad553eb360b30fb4fd8 100644 (file)
@@ -223,6 +223,9 @@ static void wb_wait_for_completion(struct backing_dev_info *bdi,
 #define WB_FRN_HIST_MAX_SLOTS  (WB_FRN_HIST_THR_SLOTS / 2 + 1)
                                        /* one round can affect upto 5 slots */
 
+static atomic_t isw_nr_in_flight = ATOMIC_INIT(0);
+static struct workqueue_struct *isw_wq;
+
 void __inode_attach_wb(struct inode *inode, struct page *page)
 {
        struct backing_dev_info *bdi = inode_to_bdi(inode);
@@ -424,6 +427,8 @@ skip_switch:
 
        iput(inode);
        kfree(isw);
+
+       atomic_dec(&isw_nr_in_flight);
 }
 
 static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head)
@@ -433,7 +438,7 @@ static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head)
 
        /* needs to grab bh-unsafe locks, bounce to work item */
        INIT_WORK(&isw->work, inode_switch_wbs_work_fn);
-       schedule_work(&isw->work);
+       queue_work(isw_wq, &isw->work);
 }
 
 /**
@@ -469,7 +474,8 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
 
        /* while holding I_WB_SWITCH, no one else can update the association */
        spin_lock(&inode->i_lock);
-       if (inode->i_state & (I_WB_SWITCH | I_FREEING) ||
+       if (!(inode->i_sb->s_flags & MS_ACTIVE) ||
+           inode->i_state & (I_WB_SWITCH | I_FREEING) ||
            inode_to_wb(inode) == isw->new_wb) {
                spin_unlock(&inode->i_lock);
                goto out_free;
@@ -480,6 +486,8 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
        ihold(inode);
        isw->inode = inode;
 
+       atomic_inc(&isw_nr_in_flight);
+
        /*
         * In addition to synchronizing among switchers, I_WB_SWITCH tells
         * the RCU protected stat update paths to grab the mapping's
@@ -840,6 +848,33 @@ restart:
                wb_put(last_wb);
 }
 
+/**
+ * cgroup_writeback_umount - flush inode wb switches for umount
+ *
+ * This function is called when a super_block is about to be destroyed and
+ * flushes in-flight inode wb switches.  An inode wb switch goes through
+ * RCU and then workqueue, so the two need to be flushed in order to ensure
+ * that all previously scheduled switches are finished.  As wb switches are
+ * rare occurrences and synchronize_rcu() can take a while, perform
+ * flushing iff wb switches are in flight.
+ */
+void cgroup_writeback_umount(void)
+{
+       if (atomic_read(&isw_nr_in_flight)) {
+               synchronize_rcu();
+               flush_workqueue(isw_wq);
+       }
+}
+
+static int __init cgroup_writeback_init(void)
+{
+       isw_wq = alloc_workqueue("inode_switch_wbs", 0, 0);
+       if (!isw_wq)
+               return -ENOMEM;
+       return 0;
+}
+fs_initcall(cgroup_writeback_init);
+
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
 static struct bdi_writeback *
index 506765afa1a3135d1ff9bccc48f06634439fa69e..bb8d67e2740ac70d7c9c87c078429475f9e0b79d 100644 (file)
@@ -376,12 +376,11 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
        struct inode *inode = d_inode(dentry);
        dnode_secno dno;
        int r;
-       int rep = 0;
        int err;
 
        hpfs_lock(dir->i_sb);
        hpfs_adjust_length(name, &len);
-again:
+
        err = -ENOENT;
        de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
        if (!de)
@@ -401,33 +400,9 @@ again:
                hpfs_error(dir->i_sb, "there was error when removing dirent");
                err = -EFSERROR;
                break;
-       case 2:         /* no space for deleting, try to truncate file */
-
+       case 2:         /* no space for deleting */
                err = -ENOSPC;
-               if (rep++)
-                       break;
-
-               dentry_unhash(dentry);
-               if (!d_unhashed(dentry)) {
-                       hpfs_unlock(dir->i_sb);
-                       return -ENOSPC;
-               }
-               if (generic_permission(inode, MAY_WRITE) ||
-                   !S_ISREG(inode->i_mode) ||
-                   get_write_access(inode)) {
-                       d_rehash(dentry);
-               } else {
-                       struct iattr newattrs;
-                       /*pr_info("truncating file before delete.\n");*/
-                       newattrs.ia_size = 0;
-                       newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-                       err = notify_change(dentry, &newattrs, NULL);
-                       put_write_access(inode);
-                       if (!err)
-                               goto again;
-               }
-               hpfs_unlock(dir->i_sb);
-               return -ENOSPC;
+               break;
        default:
                drop_nlink(inode);
                err = 0;
index 9f62db3bcc3efcc9cc678ed0d9bc88152f692ff8..69b8b526c1946c455c8b5ad0c8939542d9c2e82d 100644 (file)
@@ -154,6 +154,12 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        inode->i_rdev = 0;
        inode->dirtied_when = 0;
 
+#ifdef CONFIG_CGROUP_WRITEBACK
+       inode->i_wb_frn_winner = 0;
+       inode->i_wb_frn_avg_time = 0;
+       inode->i_wb_frn_history = 0;
+#endif
+
        if (security_inode_alloc(inode))
                goto out;
        spin_lock_init(&inode->i_lock);
index 3ea36554107fc7740558ac81daa0328c308b2903..8918ac905a3b1face373e3a0ad456c2d3bf6d95b 100644 (file)
@@ -2,10 +2,6 @@
        JFFS2 LOCKING DOCUMENTATION
        ---------------------------
 
-At least theoretically, JFFS2 does not require the Big Kernel Lock
-(BKL), which was always helpfully obtained for it by Linux 2.4 VFS
-code. It has its own locking, as described below.
-
 This document attempts to describe the existing locking rules for
 JFFS2. It is not expected to remain perfectly up to date, but ought to
 be fairly close.
@@ -69,6 +65,7 @@ Ordering constraints:
           any f->sem held.
        2. Never attempt to lock two file mutexes in one thread.
           No ordering rules have been made for doing so.
+       3. Never lock a page cache page with f->sem held.
 
 
        erase_completion_lock spinlock
index 0ae91ad6df2dc916f077495876ec7fe1e47902ed..b288c8ae1236b0f81f271e0fcfcaf5ee246b2933 100644 (file)
@@ -50,7 +50,8 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
 
 
 static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
-                                   struct jffs2_inode_cache *ic)
+                                   struct jffs2_inode_cache *ic,
+                                   int *dir_hardlinks)
 {
        struct jffs2_full_dirent *fd;
 
@@ -69,19 +70,21 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
                        dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
                                  fd->name, fd->ino, ic->ino);
                        jffs2_mark_node_obsolete(c, fd->raw);
+                       /* Clear the ic/raw union so it doesn't cause problems later. */
+                       fd->ic = NULL;
                        continue;
                }
 
+               /* From this point, fd->raw is no longer used so we can set fd->ic */
+               fd->ic = child_ic;
+               child_ic->pino_nlink++;
+               /* If we appear (at this stage) to have hard-linked directories,
+                * set a flag to trigger a scan later */
                if (fd->type == DT_DIR) {
-                       if (child_ic->pino_nlink) {
-                               JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
-                                           fd->name, fd->ino, ic->ino);
-                               /* TODO: What do we do about it? */
-                       } else {
-                               child_ic->pino_nlink = ic->ino;
-                       }
-               } else
-                       child_ic->pino_nlink++;
+                       child_ic->flags |= INO_FLAGS_IS_DIR;
+                       if (child_ic->pino_nlink > 1)
+                               *dir_hardlinks = 1;
+               }
 
                dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
                /* Can't free scan_dents so far. We might need them in pass 2 */
@@ -95,8 +98,7 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
 */
 static int jffs2_build_filesystem(struct jffs2_sb_info *c)
 {
-       int ret;
-       int i;
+       int ret, i, dir_hardlinks = 0;
        struct jffs2_inode_cache *ic;
        struct jffs2_full_dirent *fd;
        struct jffs2_full_dirent *dead_fds = NULL;
@@ -120,7 +122,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
        /* Now scan the directory tree, increasing nlink according to every dirent found. */
        for_each_inode(i, c, ic) {
                if (ic->scan_dents) {
-                       jffs2_build_inode_pass1(c, ic);
+                       jffs2_build_inode_pass1(c, ic, &dir_hardlinks);
                        cond_resched();
                }
        }
@@ -156,6 +158,20 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
        }
 
        dbg_fsbuild("pass 2a complete\n");
+
+       if (dir_hardlinks) {
+               /* If we detected directory hardlinks earlier, *hopefully*
+                * they are gone now because some of the links were from
+                * dead directories which still had some old dirents lying
+                * around and not yet garbage-collected, but which have
+                * been discarded above. So clear the pino_nlink field
+                * in each directory, so that the final scan below can
+                * print appropriate warnings. */
+               for_each_inode(i, c, ic) {
+                       if (ic->flags & INO_FLAGS_IS_DIR)
+                               ic->pino_nlink = 0;
+               }
+       }
        dbg_fsbuild("freeing temporary data structures\n");
 
        /* Finally, we can scan again and free the dirent structs */
@@ -163,6 +179,33 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
                while(ic->scan_dents) {
                        fd = ic->scan_dents;
                        ic->scan_dents = fd->next;
+                       /* We do use the pino_nlink field to count nlink of
+                        * directories during fs build, so set it to the
+                        * parent ino# now. Now that there's hopefully only
+                        * one. */
+                       if (fd->type == DT_DIR) {
+                               if (!fd->ic) {
+                                       /* We'll have complained about it and marked the coresponding
+                                          raw node obsolete already. Just skip it. */
+                                       continue;
+                               }
+
+                               /* We *have* to have set this in jffs2_build_inode_pass1() */
+                               BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR));
+
+                               /* We clear ic->pino_nlink âˆ€ directories' ic *only* if dir_hardlinks
+                                * is set. Otherwise, we know this should never trigger anyway, so
+                                * we don't do the check. And ic->pino_nlink still contains the nlink
+                                * value (which is 1). */
+                               if (dir_hardlinks && fd->ic->pino_nlink) {
+                                       JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n",
+                                                   fd->name, fd->ino, ic->ino, fd->ic->pino_nlink);
+                                       /* Should we unlink it from its previous parent? */
+                               }
+
+                               /* For directories, ic->pino_nlink holds that parent inode # */
+                               fd->ic->pino_nlink = ic->ino;
+                       }
                        jffs2_free_full_dirent(fd);
                }
                ic->scan_dents = NULL;
@@ -241,11 +284,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
 
                        /* Reduce nlink of the child. If it's now zero, stick it on the
                           dead_fds list to be cleaned up later. Else just free the fd */
-
-                       if (fd->type == DT_DIR)
-                               child_ic->pino_nlink = 0;
-                       else
-                               child_ic->pino_nlink--;
+                       child_ic->pino_nlink--;
 
                        if (!child_ic->pino_nlink) {
                                dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
index c5ac5944bc1bd8ef1362e5911656f3bfb68ea70b..cad86bac345305e5c3231589c63051cba0a2da6c 100644 (file)
@@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        struct page *pg;
        struct inode *inode = mapping->host;
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
-       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
-       struct jffs2_raw_inode ri;
-       uint32_t alloc_len = 0;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
-       jffs2_dbg(1, "%s()\n", __func__);
-
-       if (pageofs > inode->i_size) {
-               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-               if (ret)
-                       return ret;
-       }
-
-       mutex_lock(&f->sem);
        pg = grab_cache_page_write_begin(mapping, index, flags);
-       if (!pg) {
-               if (alloc_len)
-                       jffs2_complete_reservation(c);
-               mutex_unlock(&f->sem);
+       if (!pg)
                return -ENOMEM;
-       }
        *pagep = pg;
 
-       if (alloc_len) {
+       jffs2_dbg(1, "%s()\n", __func__);
+
+       if (pageofs > inode->i_size) {
                /* Make new hole frag from old EOF to new page */
+               struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+               struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
+               uint32_t alloc_len;
 
                jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs);
 
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               if (ret)
+                       goto out_page;
+
+               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
+                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -210,10 +205,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
+                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
+               mutex_unlock(&f->sem);
        }
 
        /*
@@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
+               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
+               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
-       mutex_unlock(&f->sem);
        jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
        return ret;
 
 out_page:
        unlock_page(pg);
        page_cache_release(pg);
-       mutex_unlock(&f->sem);
        return ret;
 }
 
index 5a2dec2b064c945aba23acac93dcee2820019d68..95d5880a63ee10fe98ad3520b20890f247e36d0c 100644 (file)
@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
                BUG_ON(start > orig_start);
        }
 
-       /* First, use readpage() to read the appropriate page into the page cache */
-       /* Q: What happens if we actually try to GC the _same_ page for which commit_write()
-        *    triggered garbage collection in the first place?
-        * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the
-        *    page OK. We'll actually write it out again in commit_write, which is a little
-        *    suboptimal, but at least we're correct.
-        */
+       /* The rules state that we must obtain the page lock *before* f->sem, so
+        * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
+        * actually going to *change* so we're safe; we only allow reading.
+        *
+        * It is important to note that jffs2_write_begin() will ensure that its
+        * page is marked Uptodate before allocating space. That means that if we
+        * end up here trying to GC the *same* page that jffs2_write_begin() is
+        * trying to write out, read_cache_page() will not deadlock. */
+       mutex_unlock(&f->sem);
        pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
+       mutex_lock(&f->sem);
 
        if (IS_ERR(pg_ptr)) {
                pr_warn("read_cache_page() returned error: %ld\n",
index fa35ff79ab358fe79c734f54ff51ebcb21ab9f7f..0637271f377012b51f6684622f3a0c604385d474 100644 (file)
@@ -194,6 +194,7 @@ struct jffs2_inode_cache {
 #define INO_STATE_CLEARING     6       /* In clear_inode() */
 
 #define INO_FLAGS_XATTR_CHECKED        0x01    /* has no duplicate xattr_ref */
+#define INO_FLAGS_IS_DIR       0x02    /* is a directory */
 
 #define RAWNODE_CLASS_INODE_CACHE      0
 #define RAWNODE_CLASS_XATTR_DATUM      1
@@ -249,7 +250,10 @@ struct jffs2_readinode_info
 
 struct jffs2_full_dirent
 {
-       struct jffs2_raw_node_ref *raw;
+       union {
+               struct jffs2_raw_node_ref *raw;
+               struct jffs2_inode_cache *ic; /* Just during part of build */
+       };
        struct jffs2_full_dirent *next;
        uint32_t version;
        uint32_t ino; /* == zero for unlink */
index f624d132e01e6f5488fd0d9af13007b015e1e178..9c590e0f66e9c2189f360bf1b742f54f969713aa 100644 (file)
@@ -1712,6 +1712,11 @@ static inline int should_follow_link(struct nameidata *nd, struct path *link,
                return 0;
        if (!follow)
                return 0;
+       /* make sure that d_is_symlink above matches inode */
+       if (nd->flags & LOOKUP_RCU) {
+               if (read_seqcount_retry(&link->dentry->d_seq, seq))
+                       return -ECHILD;
+       }
        return pick_link(nd, link, inode, seq);
 }
 
@@ -1743,11 +1748,11 @@ static int walk_component(struct nameidata *nd, int flags)
                if (err < 0)
                        return err;
 
-               inode = d_backing_inode(path.dentry);
                seq = 0;        /* we are already out of RCU mode */
                err = -ENOENT;
                if (d_is_negative(path.dentry))
                        goto out_path_put;
+               inode = d_backing_inode(path.dentry);
        }
 
        if (flags & WALK_PUT)
@@ -3192,12 +3197,12 @@ retry_lookup:
                return error;
 
        BUG_ON(nd->flags & LOOKUP_RCU);
-       inode = d_backing_inode(path.dentry);
        seq = 0;        /* out of RCU mode, so the value doesn't matter */
        if (unlikely(d_is_negative(path.dentry))) {
                path_to_nameidata(&path, nd);
                return -ENOENT;
        }
+       inode = d_backing_inode(path.dentry);
 finish_lookup:
        if (nd->depth)
                put_link(nd);
@@ -3206,11 +3211,6 @@ finish_lookup:
        if (unlikely(error))
                return error;
 
-       if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
-               path_to_nameidata(&path, nd);
-               return -ELOOP;
-       }
-
        if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
                path_to_nameidata(&path, nd);
        } else {
@@ -3229,6 +3229,10 @@ finish_open:
                return error;
        }
        audit_inode(nd->name, nd->path.dentry, 0);
+       if (unlikely(d_is_symlink(nd->path.dentry)) && !(open_flag & O_PATH)) {
+               error = -ELOOP;
+               goto out;
+       }
        error = -EISDIR;
        if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
                goto out;
@@ -3273,6 +3277,10 @@ opened:
                        goto exit_fput;
        }
 out:
+       if (unlikely(error > 0)) {
+               WARN_ON(1);
+               error = -EINVAL;
+       }
        if (got_write)
                mnt_drop_write(nd->path.mnt);
        path_put(&save_parent);
index c59a59c37f3dabae1211db9efcb963442c013b36..35ab51c04814d67baecf83d3b3627d66fdd79359 100644 (file)
@@ -476,6 +476,7 @@ static void ext_tree_free_commitdata(struct nfs4_layoutcommit_args *arg,
 
                for (i = 0; i < nr_pages; i++)
                        put_page(arg->layoutupdate_pages[i]);
+               vfree(arg->start_p);
                kfree(arg->layoutupdate_pages);
        } else {
                put_page(arg->layoutupdate_page);
@@ -559,10 +560,15 @@ retry:
 
        if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) {
                void *p = start_p, *end = p + arg->layoutupdate_len;
+               struct page *page = NULL;
                int i = 0;
 
-               for ( ; p < end; p += PAGE_SIZE)
-                       arg->layoutupdate_pages[i++] = vmalloc_to_page(p);
+               arg->start_p = start_p;
+               for ( ; p < end; p += PAGE_SIZE) {
+                       page = vmalloc_to_page(p);
+                       arg->layoutupdate_pages[i++] = page;
+                       get_page(page);
+               }
        }
 
        dprintk("%s found %zu ranges\n", __func__, count);
index bd25dc7077f72f5a79dfbf81e27f15a75a85dd92..dff83460e5a63ff0b6578f419a793d70720c3997 100644 (file)
 
 #define NFSDBG_FACILITY NFSDBG_PROC
 
-static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file,
-                               fmode_t fmode)
-{
-       struct nfs_open_context *open;
-       struct nfs_lock_context *lock;
-       int ret;
-
-       open = get_nfs_open_context(nfs_file_open_context(file));
-       lock = nfs_get_lock_context(open);
-       if (IS_ERR(lock)) {
-               put_nfs_open_context(open);
-               return PTR_ERR(lock);
-       }
-
-       ret = nfs4_set_rw_stateid(dst, open, lock, fmode);
-
-       nfs_put_lock_context(lock);
-       put_nfs_open_context(open);
-       return ret;
-}
-
 static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
-                                loff_t offset, loff_t len)
+               struct nfs_lock_context *lock, loff_t offset, loff_t len)
 {
        struct inode *inode = file_inode(filep);
        struct nfs_server *server = NFS_SERVER(inode);
@@ -56,7 +35,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
        msg->rpc_argp = &args;
        msg->rpc_resp = &res;
 
-       status = nfs42_set_rw_stateid(&args.falloc_stateid, filep, FMODE_WRITE);
+       status = nfs4_set_rw_stateid(&args.falloc_stateid, lock->open_context,
+                       lock, FMODE_WRITE);
        if (status)
                return status;
 
@@ -78,15 +58,26 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
 {
        struct nfs_server *server = NFS_SERVER(file_inode(filep));
        struct nfs4_exception exception = { };
+       struct nfs_lock_context *lock;
        int err;
 
+       lock = nfs_get_lock_context(nfs_file_open_context(filep));
+       if (IS_ERR(lock))
+               return PTR_ERR(lock);
+
+       exception.inode = file_inode(filep);
+       exception.state = lock->open_context->state;
+
        do {
-               err = _nfs42_proc_fallocate(msg, filep, offset, len);
-               if (err == -ENOTSUPP)
-                       return -EOPNOTSUPP;
+               err = _nfs42_proc_fallocate(msg, filep, lock, offset, len);
+               if (err == -ENOTSUPP) {
+                       err = -EOPNOTSUPP;
+                       break;
+               }
                err = nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
 
+       nfs_put_lock_context(lock);
        return err;
 }
 
@@ -135,7 +126,8 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
        return err;
 }
 
-static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+static loff_t _nfs42_proc_llseek(struct file *filep,
+               struct nfs_lock_context *lock, loff_t offset, int whence)
 {
        struct inode *inode = file_inode(filep);
        struct nfs42_seek_args args = {
@@ -156,7 +148,8 @@ static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
        if (!nfs_server_capable(inode, NFS_CAP_SEEK))
                return -ENOTSUPP;
 
-       status = nfs42_set_rw_stateid(&args.sa_stateid, filep, FMODE_READ);
+       status = nfs4_set_rw_stateid(&args.sa_stateid, lock->open_context,
+                       lock, FMODE_READ);
        if (status)
                return status;
 
@@ -175,17 +168,28 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 {
        struct nfs_server *server = NFS_SERVER(file_inode(filep));
        struct nfs4_exception exception = { };
+       struct nfs_lock_context *lock;
        loff_t err;
 
+       lock = nfs_get_lock_context(nfs_file_open_context(filep));
+       if (IS_ERR(lock))
+               return PTR_ERR(lock);
+
+       exception.inode = file_inode(filep);
+       exception.state = lock->open_context->state;
+
        do {
-               err = _nfs42_proc_llseek(filep, offset, whence);
+               err = _nfs42_proc_llseek(filep, lock, offset, whence);
                if (err >= 0)
                        break;
-               if (err == -ENOTSUPP)
-                       return -EOPNOTSUPP;
+               if (err == -ENOTSUPP) {
+                       err = -EOPNOTSUPP;
+                       break;
+               }
                err = nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
 
+       nfs_put_lock_context(lock);
        return err;
 }
 
@@ -298,8 +302,9 @@ int nfs42_proc_layoutstats_generic(struct nfs_server *server,
 }
 
 static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
-                            struct file *dst_f, loff_t src_offset,
-                            loff_t dst_offset, loff_t count)
+               struct file *dst_f, struct nfs_lock_context *src_lock,
+               struct nfs_lock_context *dst_lock, loff_t src_offset,
+               loff_t dst_offset, loff_t count)
 {
        struct inode *src_inode = file_inode(src_f);
        struct inode *dst_inode = file_inode(dst_f);
@@ -320,11 +325,13 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
        msg->rpc_argp = &args;
        msg->rpc_resp = &res;
 
-       status = nfs42_set_rw_stateid(&args.src_stateid, src_f, FMODE_READ);
+       status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context,
+                       src_lock, FMODE_READ);
        if (status)
                return status;
 
-       status = nfs42_set_rw_stateid(&args.dst_stateid, dst_f, FMODE_WRITE);
+       status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context,
+                       dst_lock, FMODE_WRITE);
        if (status)
                return status;
 
@@ -349,22 +356,48 @@ int nfs42_proc_clone(struct file *src_f, struct file *dst_f,
        };
        struct inode *inode = file_inode(src_f);
        struct nfs_server *server = NFS_SERVER(file_inode(src_f));
-       struct nfs4_exception exception = { };
-       int err;
+       struct nfs_lock_context *src_lock;
+       struct nfs_lock_context *dst_lock;
+       struct nfs4_exception src_exception = { };
+       struct nfs4_exception dst_exception = { };
+       int err, err2;
 
        if (!nfs_server_capable(inode, NFS_CAP_CLONE))
                return -EOPNOTSUPP;
 
+       src_lock = nfs_get_lock_context(nfs_file_open_context(src_f));
+       if (IS_ERR(src_lock))
+               return PTR_ERR(src_lock);
+
+       src_exception.inode = file_inode(src_f);
+       src_exception.state = src_lock->open_context->state;
+
+       dst_lock = nfs_get_lock_context(nfs_file_open_context(dst_f));
+       if (IS_ERR(dst_lock)) {
+               err = PTR_ERR(dst_lock);
+               goto out_put_src_lock;
+       }
+
+       dst_exception.inode = file_inode(dst_f);
+       dst_exception.state = dst_lock->open_context->state;
+
        do {
-               err = _nfs42_proc_clone(&msg, src_f, dst_f, src_offset,
-                                       dst_offset, count);
+               err = _nfs42_proc_clone(&msg, src_f, dst_f, src_lock, dst_lock,
+                                       src_offset, dst_offset, count);
                if (err == -ENOTSUPP || err == -EOPNOTSUPP) {
                        NFS_SERVER(inode)->caps &= ~NFS_CAP_CLONE;
-                       return -EOPNOTSUPP;
+                       err = -EOPNOTSUPP;
+                       break;
                }
-               err = nfs4_handle_exception(server, err, &exception);
-       } while (exception.retry);
 
-       return err;
+               err2 = nfs4_handle_exception(server, err, &src_exception);
+               err = nfs4_handle_exception(server, err, &dst_exception);
+               if (!err)
+                       err = err2;
+       } while (src_exception.retry || dst_exception.retry);
 
+       nfs_put_lock_context(dst_lock);
+out_put_src_lock:
+       nfs_put_lock_context(src_lock);
+       return err;
 }
index 4bfc33ad05637f58f9f0b675f058fd90085d4271..14881594dd07b9944a494d388722f4acf4b5457a 100644 (file)
@@ -2466,9 +2466,9 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                dentry = d_add_unique(dentry, igrab(state->inode));
                if (dentry == NULL) {
                        dentry = opendata->dentry;
-               } else if (dentry != ctx->dentry) {
+               } else {
                        dput(ctx->dentry);
-                       ctx->dentry = dget(dentry);
+                       ctx->dentry = dentry;
                }
                nfs_set_verifier(dentry,
                                nfs_save_change_attribute(d_inode(opendata->dir)));
index 482b6e94bb37cd1f3abaca235e94d961d9c15cb4..2fa483e6dbe2e4a0e4333bf2d76cfd861073232b 100644 (file)
@@ -252,6 +252,27 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
        }
 }
 
+/*
+ * Mark a pnfs_layout_hdr and all associated layout segments as invalid
+ *
+ * In order to continue using the pnfs_layout_hdr, a full recovery
+ * is required.
+ * Note that caller must hold inode->i_lock.
+ */
+static int
+pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
+               struct list_head *lseg_list)
+{
+       struct pnfs_layout_range range = {
+               .iomode = IOMODE_ANY,
+               .offset = 0,
+               .length = NFS4_MAX_UINT64,
+       };
+
+       set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
+       return pnfs_mark_matching_lsegs_invalid(lo, lseg_list, &range);
+}
+
 static int
 pnfs_iomode_to_fail_bit(u32 iomode)
 {
@@ -554,9 +575,8 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
        spin_lock(&nfsi->vfs_inode.i_lock);
        lo = nfsi->layout;
        if (lo) {
-               lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */
-               pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
                pnfs_get_layout_hdr(lo);
+               pnfs_mark_layout_stateid_invalid(lo, &tmp_list);
                pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED);
                pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED);
                spin_unlock(&nfsi->vfs_inode.i_lock);
@@ -617,11 +637,6 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
 {
        struct pnfs_layout_hdr *lo;
        struct inode *inode;
-       struct pnfs_layout_range range = {
-               .iomode = IOMODE_ANY,
-               .offset = 0,
-               .length = NFS4_MAX_UINT64,
-       };
        LIST_HEAD(lseg_list);
        int ret = 0;
 
@@ -636,11 +651,11 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
 
                spin_lock(&inode->i_lock);
                list_del_init(&lo->plh_bulk_destroy);
-               lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */
-               if (is_bulk_recall)
-                       set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
-               if (pnfs_mark_matching_lsegs_invalid(lo, &lseg_list, &range))
+               if (pnfs_mark_layout_stateid_invalid(lo, &lseg_list)) {
+                       if (is_bulk_recall)
+                               set_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
                        ret = -EAGAIN;
+               }
                spin_unlock(&inode->i_lock);
                pnfs_free_lseg_list(&lseg_list);
                /* Free all lsegs that are attached to commit buckets */
@@ -1738,8 +1753,19 @@ pnfs_set_plh_return_iomode(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode)
        if (lo->plh_return_iomode != 0)
                iomode = IOMODE_ANY;
        lo->plh_return_iomode = iomode;
+       set_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags);
 }
 
+/**
+ * pnfs_mark_matching_lsegs_return - Free or return matching layout segments
+ * @lo: pointer to layout header
+ * @tmp_list: list header to be used with pnfs_free_lseg_list()
+ * @return_range: describe layout segment ranges to be returned
+ *
+ * This function is mainly intended for use by layoutrecall. It attempts
+ * to free the layout segment immediately, or else to mark it for return
+ * as soon as its reference count drops to zero.
+ */
 int
 pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
                                struct list_head *tmp_list,
@@ -1762,12 +1788,11 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
                                lseg, lseg->pls_range.iomode,
                                lseg->pls_range.offset,
                                lseg->pls_range.length);
+                       if (mark_lseg_invalid(lseg, tmp_list))
+                               continue;
+                       remaining++;
                        set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
                        pnfs_set_plh_return_iomode(lo, return_range->iomode);
-                       if (!mark_lseg_invalid(lseg, tmp_list))
-                               remaining++;
-                       set_bit(NFS_LAYOUT_RETURN_REQUESTED,
-                                       &lo->plh_flags);
                }
        return remaining;
 }
index cfcbf114676ed9e5ee439563acc0a407e3541522..7115c5d7d373c63df1512eba5ea90351ea5c7c45 100644 (file)
 #include <linux/fsnotify_backend.h>
 #include "fsnotify.h"
 
+#define FSNOTIFY_REAPER_DELAY  (1)     /* 1 jiffy */
+
 struct srcu_struct fsnotify_mark_srcu;
+static DEFINE_SPINLOCK(destroy_lock);
+static LIST_HEAD(destroy_list);
+
+static void fsnotify_mark_destroy(struct work_struct *work);
+static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy);
 
 void fsnotify_get_mark(struct fsnotify_mark *mark)
 {
@@ -165,19 +172,10 @@ void fsnotify_detach_mark(struct fsnotify_mark *mark)
        atomic_dec(&group->num_marks);
 }
 
-static void
-fsnotify_mark_free_rcu(struct rcu_head *rcu)
-{
-       struct fsnotify_mark    *mark;
-
-       mark = container_of(rcu, struct fsnotify_mark, g_rcu);
-       fsnotify_put_mark(mark);
-}
-
 /*
- * Free fsnotify mark. The freeing is actually happening from a call_srcu
- * callback. Caller must have a reference to the mark or be protected by
- * fsnotify_mark_srcu.
+ * Free fsnotify mark. The freeing is actually happening from a kthread which
+ * first waits for srcu period end. Caller must have a reference to the mark
+ * or be protected by fsnotify_mark_srcu.
  */
 void fsnotify_free_mark(struct fsnotify_mark *mark)
 {
@@ -192,7 +190,11 @@ void fsnotify_free_mark(struct fsnotify_mark *mark)
        mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
        spin_unlock(&mark->lock);
 
-       call_srcu(&fsnotify_mark_srcu, &mark->g_rcu, fsnotify_mark_free_rcu);
+       spin_lock(&destroy_lock);
+       list_add(&mark->g_list, &destroy_list);
+       spin_unlock(&destroy_lock);
+       queue_delayed_work(system_unbound_wq, &reaper_work,
+                               FSNOTIFY_REAPER_DELAY);
 
        /*
         * Some groups like to know that marks are being freed.  This is a
@@ -388,7 +390,12 @@ err:
 
        spin_unlock(&mark->lock);
 
-       call_srcu(&fsnotify_mark_srcu, &mark->g_rcu, fsnotify_mark_free_rcu);
+       spin_lock(&destroy_lock);
+       list_add(&mark->g_list, &destroy_list);
+       spin_unlock(&destroy_lock);
+       queue_delayed_work(system_unbound_wq, &reaper_work,
+                               FSNOTIFY_REAPER_DELAY);
+
        return ret;
 }
 
@@ -491,3 +498,21 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
        atomic_set(&mark->refcnt, 1);
        mark->free_mark = free_mark;
 }
+
+static void fsnotify_mark_destroy(struct work_struct *work)
+{
+       struct fsnotify_mark *mark, *next;
+       struct list_head private_destroy_list;
+
+       spin_lock(&destroy_lock);
+       /* exchange the list head */
+       list_replace_init(&destroy_list, &private_destroy_list);
+       spin_unlock(&destroy_lock);
+
+       synchronize_srcu(&fsnotify_mark_srcu);
+
+       list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) {
+               list_del_init(&mark->g_list);
+               fsnotify_put_mark(mark);
+       }
+}
index 794fd1587f34a3bc210d60770525a02f3cd59aba..cda0361e95a403e887d912174ec296aa4cbb6e4d 100644 (file)
@@ -956,6 +956,7 @@ clean_orphan:
                tmp_ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh,
                                update_isize, end);
                if (tmp_ret < 0) {
+                       ocfs2_inode_unlock(inode, 1);
                        ret = tmp_ret;
                        mlog_errno(ret);
                        brelse(di_bh);
index 6367e1e435c64144a1d9adb94e9c1cfd1f157dfe..c524fdddc7fb1f601d6d06ddb46d0affcca89c08 100644 (file)
@@ -202,6 +202,11 @@ static struct mount *last_dest, *last_source, *dest_master;
 static struct mountpoint *mp;
 static struct hlist_head *list;
 
+static inline bool peers(struct mount *m1, struct mount *m2)
+{
+       return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
+}
+
 static int propagate_one(struct mount *m)
 {
        struct mount *child;
@@ -212,7 +217,7 @@ static int propagate_one(struct mount *m)
        /* skip if mountpoint isn't covered by it */
        if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
                return 0;
-       if (m->mnt_group_id == last_dest->mnt_group_id) {
+       if (peers(m, last_dest)) {
                type = CL_MAKE_SHARED;
        } else {
                struct mount *n, *p;
@@ -223,7 +228,7 @@ static int propagate_one(struct mount *m)
                                        last_source = last_source->mnt_master;
                                        last_dest = last_source->mnt_parent;
                                }
-                               if (n->mnt_group_id != last_dest->mnt_group_id) {
+                               if (!peers(n, last_dest)) {
                                        last_source = last_source->mnt_master;
                                        last_dest = last_source->mnt_parent;
                                }
index 324ec271cc4e64868c34e3ff2f28ac2c0542475e..dadf24e5c95bb7004d105f0773430576bfc57cf5 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/splice.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
+#include <linux/fs.h>
 #include "internal.h"
 
 #include <asm/uaccess.h>
@@ -183,7 +184,7 @@ loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence)
        switch (whence) {
        case SEEK_SET: case SEEK_CUR:
                return generic_file_llseek_size(file, offset, whence,
-                                               ~0ULL, 0);
+                                               OFFSET_MAX, 0);
        default:
                return -EINVAL;
        }
@@ -1532,10 +1533,12 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
 
        if (!(file_in->f_mode & FMODE_READ) ||
            !(file_out->f_mode & FMODE_WRITE) ||
-           (file_out->f_flags & O_APPEND) ||
-           !file_in->f_op->clone_file_range)
+           (file_out->f_flags & O_APPEND))
                return -EBADF;
 
+       if (!file_in->f_op->clone_file_range)
+               return -EOPNOTSUPP;
+
        ret = clone_verify_area(file_in, pos_in, len, false);
        if (ret)
                return ret;
index 1182af8fd5ff3ede7459305440d50178821c061b..74914b1bae70ff09d451450cb596fb3b5639d969 100644 (file)
@@ -415,6 +415,7 @@ void generic_shutdown_super(struct super_block *sb)
                sb->s_flags &= ~MS_ACTIVE;
 
                fsnotify_unmount_inodes(sb);
+               cgroup_writeback_umount();
 
                evict_inodes(sb);
 
index 50311703135bc8c699bcc3d26d0b9aa24b5277f3..66cdb44616d5a0ba79a04f60de5fd835805b6e56 100644 (file)
@@ -286,6 +286,12 @@ int handle_userfault(struct vm_area_struct *vma, unsigned long address,
        if (unlikely(ACCESS_ONCE(ctx->released)))
                goto out;
 
+       /*
+        * We don't do userfault handling for the final child pid update.
+        */
+       if (current->flags & PF_EXITING)
+               goto out;
+
        /*
         * Check that we can return VM_FAULT_RETRY.
         *
index 07d0e47f6a7f1968782b2b31be478a6dd3851656..4861322e28e8da2154f46b7b92cbeda576ee1438 100644 (file)
@@ -940,7 +940,7 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
        bool trusted = capable(CAP_SYS_ADMIN);
        struct simple_xattr *xattr;
        ssize_t remaining_size = size;
-       int err;
+       int err = 0;
 
 #ifdef CONFIG_FS_POSIX_ACL
        if (inode->i_acl) {
@@ -965,11 +965,11 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
 
                err = xattr_list_one(&buffer, &remaining_size, xattr->name);
                if (err)
-                       return err;
+                       break;
        }
        spin_unlock(&xattrs->lock);
 
-       return size - remaining_size;
+       return err ? err : size - remaining_size;
 }
 
 /*
index 379c089fb0514a5a34934b51b790181567a3384f..a9ebabfe7587bf5abbc427e1603fcf012e5ac63c 100644 (file)
@@ -55,7 +55,7 @@ xfs_count_page_state(
        } while ((bh = bh->b_this_page) != head);
 }
 
-STATIC struct block_device *
+struct block_device *
 xfs_find_bdev_for_inode(
        struct inode            *inode)
 {
@@ -1208,6 +1208,10 @@ xfs_vm_writepages(
        struct writeback_control *wbc)
 {
        xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
+       if (dax_mapping(mapping))
+               return dax_writeback_mapping_range(mapping,
+                               xfs_find_bdev_for_inode(mapping->host), wbc);
+
        return generic_writepages(mapping, wbc);
 }
 
index f6ffc9ae5cebeae7ebf8c2cc7c3598c07c4c68f5..a4343c63fb38c60336abbaf8741a75c2a9298a4d 100644 (file)
@@ -62,5 +62,6 @@ int   xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset,
                                 struct buffer_head *map_bh, int create);
 
 extern void xfs_count_page_state(struct page *, int *, int *);
+extern struct block_device *xfs_find_bdev_for_inode(struct inode *);
 
 #endif /* __XFS_AOPS_H__ */
index 45ec9e40150c3dc44bc2268c274472f108ad188b..6c876012b2e53246bf38ca3af8dd2d23861151fe 100644 (file)
@@ -75,7 +75,8 @@ xfs_zero_extent(
        ssize_t         size = XFS_FSB_TO_B(mp, count_fsb);
 
        if (IS_DAX(VFS_I(ip)))
-               return dax_clear_blocks(VFS_I(ip), block, size);
+               return dax_clear_sectors(xfs_find_bdev_for_inode(VFS_I(ip)),
+                               sector, size);
 
        /*
         * let the block layer decide on the fastest method of
index da37beb76f6e67faf90a658d55f49a06c6fc4152..594f7e63b432427fd5b6448afa0a75eb0b71d558 100644 (file)
@@ -4491,7 +4491,7 @@ xlog_recover_process(
         * know precisely what failed.
         */
        if (pass == XLOG_RECOVER_CRCPASS) {
-               if (rhead->h_crc && crc != le32_to_cpu(rhead->h_crc))
+               if (rhead->h_crc && crc != rhead->h_crc)
                        return -EFSBADCRC;
                return 0;
        }
@@ -4502,7 +4502,7 @@ xlog_recover_process(
         * zero CRC check prevents warnings from being emitted when upgrading
         * the kernel from one that does not add CRCs by default.
         */
-       if (crc != le32_to_cpu(rhead->h_crc)) {
+       if (crc != rhead->h_crc) {
                if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
                        xfs_alert(log->l_mp,
                "log record CRC mismatch: found 0x%x, expected 0x%x.",
index 0419485891f2a8eb6125f154f52d7b16c5fb05b4..0f1c6f315cdc5294ca63bac49efbf69a5dfee805 100644 (file)
@@ -75,7 +75,7 @@ typedef u64 __nocast cputime64_t;
  */
 static inline cputime_t timespec_to_cputime(const struct timespec *val)
 {
-       u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
+       u64 ret = (u64)val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
        return (__force cputime_t) ret;
 }
 static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
@@ -91,7 +91,8 @@ static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
  */
 static inline cputime_t timeval_to_cputime(const struct timeval *val)
 {
-       u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_usec * NSEC_PER_USEC;
+       u64 ret = (u64)val->tv_sec * NSEC_PER_SEC +
+                       val->tv_usec * NSEC_PER_USEC;
        return (__force cputime_t) ret;
 }
 static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
index 0b3c0d39ef753053bb26c1b9fb4979e706240a58..c370b261c72004dcafa3dd036920b7b5fe3d01a2 100644 (file)
@@ -239,6 +239,14 @@ extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                            pmd_t *pmdp);
 #endif
 
+#ifndef __HAVE_ARCH_PMDP_HUGE_SPLIT_PREPARE
+static inline void pmdp_huge_split_prepare(struct vm_area_struct *vma,
+                                          unsigned long address, pmd_t *pmdp)
+{
+
+}
+#endif
+
 #ifndef __HAVE_ARCH_PTE_SAME
 static inline int pte_same(pte_t pte_a, pte_t pte_b)
 {
index c65a212db77e7a99b26735c262cb31a9b2504195..c5b4b81a831ba733bee1dc8aba8c9a3bb7341739 100644 (file)
@@ -1166,6 +1166,7 @@ struct drm_connector {
        struct drm_mode_object base;
 
        char *name;
+       int connector_id;
        int connector_type;
        int connector_type_id;
        bool interlace_allowed;
@@ -2047,6 +2048,7 @@ struct drm_mode_config {
        struct list_head fb_list;
 
        int num_connector;
+       struct ida connector_ida;
        struct list_head connector_list;
        int num_encoder;
        struct list_head encoder_list;
@@ -2200,7 +2202,11 @@ int drm_connector_register(struct drm_connector *connector);
 void drm_connector_unregister(struct drm_connector *connector);
 
 extern void drm_connector_cleanup(struct drm_connector *connector);
-extern unsigned int drm_connector_index(struct drm_connector *connector);
+static inline unsigned drm_connector_index(struct drm_connector *connector)
+{
+       return connector->connector_id;
+}
+
 /* helper to unplug all connectors from sysfs for device */
 extern void drm_connector_unplug_all(struct drm_device *dev);
 
index 2af97691e8781382d3b2484d3bffc4eb5a43a247..dec6221e819801a674cde431bb8f9b5c50b23b80 100644 (file)
@@ -403,6 +403,18 @@ static inline int drm_eld_size(const uint8_t *eld)
        return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4;
 }
 
+/**
+ * drm_eld_get_conn_type - Get device type hdmi/dp connected
+ * @eld: pointer to an ELD memory structure
+ *
+ * The caller need to use %DRM_ELD_CONN_TYPE_HDMI or %DRM_ELD_CONN_TYPE_DP to
+ * identify the display type connected.
+ */
+static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
+{
+       return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK;
+}
+
 struct edid *drm_do_get_edid(struct drm_connector *connector,
        int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
                              size_t len),
index 6f45aea49e4ff049a51394f6782a803e32c389eb..0a05b0d36ae74d6c4e4a7e810e442ab2ff2b09bf 100644 (file)
 /* 104 */
 /* 105 */
 #define TEGRA210_CLK_D_AUDIO 106
-/* 107 ( affects abp -> ape) */
+#define TEGRA210_CLK_APB2APE 107
 /* 108 */
 /* 109 */
 /* 110 */
index d2992bfa17063a052a08a106b9105284ce4bfa4a..c1a2f345cbe6146352fff77080019eba5d0fe76e 100644 (file)
@@ -487,8 +487,8 @@ enum ata_tf_protocols {
 };
 
 enum ata_ioctls {
-       ATA_IOC_GET_IO32        = 0x309,
-       ATA_IOC_SET_IO32        = 0x324,
+       ATA_IOC_GET_IO32        = 0x309, /* HDIO_GET_32BIT */
+       ATA_IOC_SET_IO32        = 0x324, /* HDIO_SET_32BIT */
 };
 
 /* core structures */
index 5349e6816cbb075e2b5d6ac57cac1e8fee373438..cb68888241084e33af2d7e11753e048431cf7837 100644 (file)
@@ -310,6 +310,43 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
        bio->bi_flags &= ~(1U << bit);
 }
 
+static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
+{
+       *bv = bio_iovec(bio);
+}
+
+static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
+{
+       struct bvec_iter iter = bio->bi_iter;
+       int idx;
+
+       if (!bio_flagged(bio, BIO_CLONED)) {
+               *bv = bio->bi_io_vec[bio->bi_vcnt - 1];
+               return;
+       }
+
+       if (unlikely(!bio_multiple_segments(bio))) {
+               *bv = bio_iovec(bio);
+               return;
+       }
+
+       bio_advance_iter(bio, &iter, iter.bi_size);
+
+       if (!iter.bi_bvec_done)
+               idx = iter.bi_idx - 1;
+       else    /* in the middle of bvec */
+               idx = iter.bi_idx;
+
+       *bv = bio->bi_io_vec[idx];
+
+       /*
+        * iter.bi_bvec_done records actual length of the last bvec
+        * if this bio ends in the middle of one io vector
+        */
+       if (iter.bi_bvec_done)
+               bv->bv_len = iter.bi_bvec_done;
+}
+
 enum bip_flags {
        BIP_BLOCK_INTEGRITY     = 1 << 0, /* block layer owns integrity data */
        BIP_MAPPED_INTEGRITY    = 1 << 1, /* ref tag has been remapped */
index 29189aeace19df0650c15e374e60724ce77ac917..413c84fbc4edafc582c765630ccb3f3117dbc1fc 100644 (file)
@@ -682,9 +682,12 @@ static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b)
 /*
  * q->prep_rq_fn return values
  */
-#define BLKPREP_OK             0       /* serve it */
-#define BLKPREP_KILL           1       /* fatal error, kill */
-#define BLKPREP_DEFER          2       /* leave on queue */
+enum {
+       BLKPREP_OK,             /* serve it */
+       BLKPREP_KILL,           /* fatal error, kill, return -EIO */
+       BLKPREP_DEFER,          /* leave on queue */
+       BLKPREP_INVALID,        /* invalid command, kill, return -EREMOTEIO */
+};
 
 extern unsigned long blk_max_low_pfn, blk_max_pfn;
 
@@ -892,7 +895,7 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
-       if (unlikely(rq->cmd_type == REQ_TYPE_BLOCK_PC))
+       if (unlikely(rq->cmd_type != REQ_TYPE_FS))
                return q->limits.max_hw_sectors;
 
        if (!q->limits.chunk_sectors || (rq->cmd_flags & REQ_DISCARD))
@@ -1369,6 +1372,13 @@ static inline void put_dev_sector(Sector p)
        page_cache_release(p.v);
 }
 
+static inline bool __bvec_gap_to_prev(struct request_queue *q,
+                               struct bio_vec *bprv, unsigned int offset)
+{
+       return offset ||
+               ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
+}
+
 /*
  * Check if adding a bio_vec after bprv with offset would create a gap in
  * the SG list. Most drivers don't care about this, but some do.
@@ -1378,18 +1388,22 @@ static inline bool bvec_gap_to_prev(struct request_queue *q,
 {
        if (!queue_virt_boundary(q))
                return false;
-       return offset ||
-               ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
+       return __bvec_gap_to_prev(q, bprv, offset);
 }
 
 static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
                         struct bio *next)
 {
-       if (!bio_has_data(prev))
-               return false;
+       if (bio_has_data(prev) && queue_virt_boundary(q)) {
+               struct bio_vec pb, nb;
+
+               bio_get_last_bvec(prev, &pb);
+               bio_get_first_bvec(next, &nb);
 
-       return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
-                               next->bi_io_vec[0].bv_offset);
+               return __bvec_gap_to_prev(q, &pb, nb.bv_offset);
+       }
+
+       return false;
 }
 
 static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
index c1ef6f14e7be7f1317e34a0deac61fcb80511eef..15151f3c41202c6b6229475affb654ae0bab272d 100644 (file)
@@ -75,6 +75,7 @@
 #define CEPH_FEATURE_CRUSH_TUNABLES5   (1ULL<<58) /* chooseleaf stable mode */
 // duplicated since it was introduced at the same time as CEPH_FEATURE_CRUSH_TUNABLES5
 #define CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING   (1ULL<<58) /* New, v7 encoding */
+#define CEPH_FEATURE_FS_FILE_LAYOUT_V2       (1ULL<<58) /* file_layout_t */
 
 /*
  * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature
index 7f540f7f588d8c8461af975a5ebd21a08e6cf14b..789471dba6fb30f15c752fbca46ddbefe5bfe850 100644 (file)
@@ -127,6 +127,12 @@ struct cgroup_subsys_state {
         */
        u64 serial_nr;
 
+       /*
+        * Incremented by online self and children.  Used to guarantee that
+        * parents are not offlined before their children.
+        */
+       atomic_t online_cnt;
+
        /* percpu_ref killing and RCU release */
        struct rcu_head rcu_head;
        struct work_struct destroy_work;
index 00b042c49ccdac7af3262a399d33dacc88c83e25..48f5aab117ae12625d041cd18555031e87c178fc 100644 (file)
@@ -144,7 +144,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
  */
 #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
 #define __trace_if(cond) \
-       if (__builtin_constant_p((cond)) ? !!(cond) :                   \
+       if (__builtin_constant_p(!!(cond)) ? !!(cond) :                 \
        ({                                                              \
                int ______r;                                            \
                static struct ftrace_branch_data                        \
index 85a868ccb4931d374a1ee9fb4e4036bb84399561..fea160ee5803fd121d0493f622e240b4c35da480 100644 (file)
@@ -137,6 +137,8 @@ static inline void set_mems_allowed(nodemask_t nodemask)
        task_unlock(current);
 }
 
+extern void cpuset_post_attach_flush(void);
+
 #else /* !CONFIG_CPUSETS */
 
 static inline bool cpusets_enabled(void) { return false; }
@@ -243,6 +245,10 @@ static inline bool read_mems_allowed_retry(unsigned int seq)
        return false;
 }
 
+static inline void cpuset_post_attach_flush(void)
+{
+}
+
 #endif /* !CONFIG_CPUSETS */
 
 #endif /* _LINUX_CPUSET_H */
index 818e45078929b94af5780a8c91f0e84d82da8e0c..636dd59ab505c6633ae3184b9c283cad06ab893f 100644 (file)
@@ -7,7 +7,7 @@
 
 ssize_t dax_do_io(struct kiocb *, struct inode *, struct iov_iter *, loff_t,
                  get_block_t, dio_iodone_t, int flags);
-int dax_clear_blocks(struct inode *, sector_t block, long size);
+int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size);
 int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t);
 int dax_truncate_page(struct inode *, loff_t from, get_block_t);
 int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t,
@@ -52,6 +52,8 @@ static inline bool dax_mapping(struct address_space *mapping)
 {
        return mapping->host && IS_DAX(mapping->host);
 }
-int dax_writeback_mapping_range(struct address_space *mapping, loff_t start,
-               loff_t end);
+
+struct writeback_control;
+int dax_writeback_mapping_range(struct address_space *mapping,
+               struct block_device *bdev, struct writeback_control *wbc);
 #endif
index 7781ce11050353a44cd7a3982c97949651956103..c4b5f4b3f8f8bba5af054b2b22e5c2c6fcf72b89 100644 (file)
@@ -409,9 +409,7 @@ static inline bool d_mountpoint(const struct dentry *dentry)
  */
 static inline unsigned __d_entry_type(const struct dentry *dentry)
 {
-       unsigned type = READ_ONCE(dentry->d_flags);
-       smp_rmb();
-       return type & DCACHE_ENTRY_TYPE;
+       return dentry->d_flags & DCACHE_ENTRY_TYPE;
 }
 
 static inline bool d_is_miss(const struct dentry *dentry)
index 251a2090a55444cec55ce4f04510b6ef83a69cfb..e0ee0b3000b2da107c975137165fc989777d8a58 100644 (file)
@@ -19,6 +19,8 @@
 
 int devpts_new_index(struct inode *ptmx_inode);
 void devpts_kill_index(struct inode *ptmx_inode, int idx);
+void devpts_add_ref(struct inode *ptmx_inode);
+void devpts_del_ref(struct inode *ptmx_inode);
 /* mknod in devpts */
 struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
                void *priv);
@@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode);
 /* Dummy stubs in the no-pty case */
 static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
 static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
+static inline void devpts_add_ref(struct inode *ptmx_inode) { }
+static inline void devpts_del_ref(struct inode *ptmx_inode) { }
 static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
                dev_t device, int index, void *priv)
 {
index 569b5a866bb1e6308bbc4c0a28a2da92d106d6b5..47be3ad7d3e5bad63b48a8fa344dbea65c0a97dd 100644 (file)
@@ -1199,7 +1199,10 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
 struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
                                       struct list_head *head, bool remove);
 
-bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len);
+bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
+                    unsigned long data_size);
+bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
+                                 size_t len);
 
 extern struct work_struct efivar_work;
 void efivar_run_worker(void);
index 6b7e89f45aa49e3eb1531c51f6edae4cc18d576a..533c4408529a19819570c5dc40d917aa10ac2d26 100644 (file)
@@ -220,10 +220,7 @@ struct fsnotify_mark {
        /* List of marks by group->i_fsnotify_marks. Also reused for queueing
         * mark into destroy_list when it's waiting for the end of SRCU period
         * before it can be freed. [group->mark_mutex] */
-       union {
-               struct list_head g_list;
-               struct rcu_head g_rcu;
-       };
+       struct list_head g_list;
        /* Protects inode / mnt pointers, flags, masks */
        spinlock_t lock;
        /* List of marks for inode / vfsmount [obj_lock] */
index 81de7123959d96d97dd57d41d76289b3a8185920..c2b340e23f62d3240abc6360ab0412a82a12f21a 100644 (file)
@@ -603,6 +603,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
 
 extern int skip_trace(unsigned long ip);
 extern void ftrace_module_init(struct module *mod);
+extern void ftrace_module_enable(struct module *mod);
 extern void ftrace_release_mod(struct module *mod);
 
 extern void ftrace_disable_daemon(void);
@@ -612,8 +613,9 @@ static inline int skip_trace(unsigned long ip) { return 0; }
 static inline int ftrace_force_update(void) { return 0; }
 static inline void ftrace_disable_daemon(void) { }
 static inline void ftrace_enable_daemon(void) { }
-static inline void ftrace_release_mod(struct module *mod) {}
-static inline void ftrace_module_init(struct module *mod) {}
+static inline void ftrace_module_init(struct module *mod) { }
+static inline void ftrace_module_enable(struct module *mod) { }
+static inline void ftrace_release_mod(struct module *mod) { }
 static inline __init int register_ftrace_command(struct ftrace_func_command *cmd)
 {
        return -EINVAL;
index 821273ca4873b147136f46f235d83b344b192373..2d9b650047a5b96582f66dff2b2581cce97c2b65 100644 (file)
@@ -235,6 +235,9 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 /* low 64 bit */
 #define dma_frcd_page_addr(d) (d & (((u64)-1) << PAGE_SHIFT))
 
+/* PRS_REG */
+#define DMA_PRS_PPR    ((u32)1)
+
 #define IOMMU_WAIT_OP(iommu, offset, op, cond, sts)                    \
 do {                                                                   \
        cycles_t start_time = get_cycles();                             \
index 851821bfd55321dce527f4b32e03d1534994678a..2c4ebef79d0c61b596efed901eb834d8a436492d 100644 (file)
@@ -526,6 +526,7 @@ enum ata_lpm_policy {
 enum ata_lpm_hints {
        ATA_LPM_EMPTY           = (1 << 0), /* port empty/probing */
        ATA_LPM_HIPM            = (1 << 1), /* may use HIPM */
+       ATA_LPM_WAKE_ONLY       = (1 << 2), /* only wake up link */
 };
 
 /* forward declarations */
@@ -719,7 +720,7 @@ struct ata_device {
        union {
                u16             id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
                u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
-       };
+       } ____cacheline_aligned;
 
        /* DEVSLP Timing Variables from Identify Device Data Log */
        u8                      devslp_timing[ATA_LOG_DEVSLP_SIZE];
index bed40dff0e86999b5c39c82ebadc29f25e0060ec..141ffdd59960d7b31583f629140b0f7dd9916b37 100644 (file)
@@ -26,9 +26,8 @@ enum {
 
        /* need to set a limit somewhere, but yes, this is likely overkill */
        ND_IOCTL_MAX_BUFLEN = SZ_4M,
-       ND_CMD_MAX_ELEM = 4,
+       ND_CMD_MAX_ELEM = 5,
        ND_CMD_MAX_ENVELOPE = 16,
-       ND_CMD_ARS_STATUS_MAX = SZ_4K,
        ND_MAX_MAPPINGS = 32,
 
        /* region flag indicating to direct-map persistent memory by default */
index d6750111e48ecc4603dbc5f28eb01f2810ed6303..2190419bdf0a04e549b64946037d8d61fd025781 100644 (file)
@@ -135,6 +135,10 @@ enum {
        /* Memory types */
        NVM_ID_FMTYPE_SLC       = 0,
        NVM_ID_FMTYPE_MLC       = 1,
+
+       /* Device capabilities */
+       NVM_ID_DCAP_BBLKMGMT    = 0x1,
+       NVM_UD_DCAP_ECC         = 0x2,
 };
 
 struct nvm_id_lp_mlc {
index c57e424d914b70fc5032f9b6d1ec918e8e195c64..4dca42fd32f52d17326e436c4d9fcbd86a0e8d24 100644 (file)
@@ -66,7 +66,7 @@ struct lock_class {
        /*
         * class-hash:
         */
-       struct list_head                hash_entry;
+       struct hlist_node               hash_entry;
 
        /*
         * global list of all lock-classes:
@@ -199,7 +199,7 @@ struct lock_chain {
        u8                              irq_context;
        u8                              depth;
        u16                             base;
-       struct list_head                entry;
+       struct hlist_node               entry;
        u64                             chain_key;
 };
 
index 430a929f048b3d2f27d1e842f45e80f9e9e6347a..a0e8cc8dcc67dcc88e7d32ab47a8ef22af52c946 100644 (file)
@@ -44,6 +44,8 @@
 
 #include <linux/timecounter.h>
 
+#define DEFAULT_UAR_PAGE_SHIFT  12
+
 #define MAX_MSIX_P_PORT                17
 #define MAX_MSIX               64
 #define MIN_MSIX_P_PORT                5
@@ -856,6 +858,7 @@ struct mlx4_dev {
        u64                     regid_promisc_array[MLX4_MAX_PORTS + 1];
        u64                     regid_allmulti_array[MLX4_MAX_PORTS + 1];
        struct mlx4_vf_dev     *dev_vfs;
+       u8  uar_page_shift;
 };
 
 struct mlx4_clock_params {
@@ -1528,4 +1531,14 @@ int mlx4_ACCESS_PTYS_REG(struct mlx4_dev *dev,
 int mlx4_get_internal_clock_params(struct mlx4_dev *dev,
                                   struct mlx4_clock_params *params);
 
+static inline int mlx4_to_hw_uar_index(struct mlx4_dev *dev, int index)
+{
+       return (index << (PAGE_SHIFT - dev->uar_page_shift));
+}
+
+static inline int mlx4_get_num_reserved_uar(struct mlx4_dev *dev)
+{
+       /* The first 128 UARs are used for EQ doorbells */
+       return (128 >> (PAGE_SHIFT - dev->uar_page_shift));
+}
 #endif /* MLX4_DEVICE_H */
index 231ab6bcea76356ecf6539513fc210fe1e208451..51f1e540fc2b83bf9dd143637bad8acdbc44d0fd 100644 (file)
@@ -207,15 +207,15 @@ struct mlx5_ifc_flow_table_fields_supported_bits {
        u8         outer_dmac[0x1];
        u8         outer_smac[0x1];
        u8         outer_ether_type[0x1];
-       u8         reserved_0[0x1];
+       u8         reserved_at_3[0x1];
        u8         outer_first_prio[0x1];
        u8         outer_first_cfi[0x1];
        u8         outer_first_vid[0x1];
-       u8         reserved_1[0x1];
+       u8         reserved_at_7[0x1];
        u8         outer_second_prio[0x1];
        u8         outer_second_cfi[0x1];
        u8         outer_second_vid[0x1];
-       u8         reserved_2[0x1];
+       u8         reserved_at_b[0x1];
        u8         outer_sip[0x1];
        u8         outer_dip[0x1];
        u8         outer_frag[0x1];
@@ -230,21 +230,21 @@ struct mlx5_ifc_flow_table_fields_supported_bits {
        u8         outer_gre_protocol[0x1];
        u8         outer_gre_key[0x1];
        u8         outer_vxlan_vni[0x1];
-       u8         reserved_3[0x5];
+       u8         reserved_at_1a[0x5];
        u8         source_eswitch_port[0x1];
 
        u8         inner_dmac[0x1];
        u8         inner_smac[0x1];
        u8         inner_ether_type[0x1];
-       u8         reserved_4[0x1];
+       u8         reserved_at_23[0x1];
        u8         inner_first_prio[0x1];
        u8         inner_first_cfi[0x1];
        u8         inner_first_vid[0x1];
-       u8         reserved_5[0x1];
+       u8         reserved_at_27[0x1];
        u8         inner_second_prio[0x1];
        u8         inner_second_cfi[0x1];
        u8         inner_second_vid[0x1];
-       u8         reserved_6[0x1];
+       u8         reserved_at_2b[0x1];
        u8         inner_sip[0x1];
        u8         inner_dip[0x1];
        u8         inner_frag[0x1];
@@ -256,37 +256,37 @@ struct mlx5_ifc_flow_table_fields_supported_bits {
        u8         inner_tcp_sport[0x1];
        u8         inner_tcp_dport[0x1];
        u8         inner_tcp_flags[0x1];
-       u8         reserved_7[0x9];
+       u8         reserved_at_37[0x9];
 
-       u8         reserved_8[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_flow_table_prop_layout_bits {
        u8         ft_support[0x1];
-       u8         reserved_0[0x2];
+       u8         reserved_at_1[0x2];
        u8         flow_modify_en[0x1];
        u8         modify_root[0x1];
        u8         identified_miss_table_mode[0x1];
        u8         flow_table_modify[0x1];
-       u8         reserved_1[0x19];
+       u8         reserved_at_7[0x19];
 
-       u8         reserved_2[0x2];
+       u8         reserved_at_20[0x2];
        u8         log_max_ft_size[0x6];
-       u8         reserved_3[0x10];
+       u8         reserved_at_28[0x10];
        u8         max_ft_level[0x8];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_40[0x20];
 
-       u8         reserved_5[0x18];
+       u8         reserved_at_60[0x18];
        u8         log_max_ft_num[0x8];
 
-       u8         reserved_6[0x18];
+       u8         reserved_at_80[0x18];
        u8         log_max_destination[0x8];
 
-       u8         reserved_7[0x18];
+       u8         reserved_at_a0[0x18];
        u8         log_max_flow[0x8];
 
-       u8         reserved_8[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_flow_table_fields_supported_bits ft_field_support;
 
@@ -298,13 +298,13 @@ struct mlx5_ifc_odp_per_transport_service_cap_bits {
        u8         receive[0x1];
        u8         write[0x1];
        u8         read[0x1];
-       u8         reserved_0[0x1];
+       u8         reserved_at_4[0x1];
        u8         srq_receive[0x1];
-       u8         reserved_1[0x1a];
+       u8         reserved_at_6[0x1a];
 };
 
 struct mlx5_ifc_ipv4_layout_bits {
-       u8         reserved_0[0x60];
+       u8         reserved_at_0[0x60];
 
        u8         ipv4[0x20];
 };
@@ -316,7 +316,7 @@ struct mlx5_ifc_ipv6_layout_bits {
 union mlx5_ifc_ipv6_layout_ipv4_layout_auto_bits {
        struct mlx5_ifc_ipv6_layout_bits ipv6_layout;
        struct mlx5_ifc_ipv4_layout_bits ipv4_layout;
-       u8         reserved_0[0x80];
+       u8         reserved_at_0[0x80];
 };
 
 struct mlx5_ifc_fte_match_set_lyr_2_4_bits {
@@ -336,15 +336,15 @@ struct mlx5_ifc_fte_match_set_lyr_2_4_bits {
        u8         ip_dscp[0x6];
        u8         ip_ecn[0x2];
        u8         vlan_tag[0x1];
-       u8         reserved_0[0x1];
+       u8         reserved_at_91[0x1];
        u8         frag[0x1];
-       u8         reserved_1[0x4];
+       u8         reserved_at_93[0x4];
        u8         tcp_flags[0x9];
 
        u8         tcp_sport[0x10];
        u8         tcp_dport[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_c0[0x20];
 
        u8         udp_sport[0x10];
        u8         udp_dport[0x10];
@@ -355,9 +355,9 @@ struct mlx5_ifc_fte_match_set_lyr_2_4_bits {
 };
 
 struct mlx5_ifc_fte_match_set_misc_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         source_port[0x10];
 
        u8         outer_second_prio[0x3];
@@ -369,31 +369,31 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 
        u8         outer_second_vlan_tag[0x1];
        u8         inner_second_vlan_tag[0x1];
-       u8         reserved_2[0xe];
+       u8         reserved_at_62[0xe];
        u8         gre_protocol[0x10];
 
        u8         gre_key_h[0x18];
        u8         gre_key_l[0x8];
 
        u8         vxlan_vni[0x18];
-       u8         reserved_3[0x8];
+       u8         reserved_at_b8[0x8];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_c0[0x20];
 
-       u8         reserved_5[0xc];
+       u8         reserved_at_e0[0xc];
        u8         outer_ipv6_flow_label[0x14];
 
-       u8         reserved_6[0xc];
+       u8         reserved_at_100[0xc];
        u8         inner_ipv6_flow_label[0x14];
 
-       u8         reserved_7[0xe0];
+       u8         reserved_at_120[0xe0];
 };
 
 struct mlx5_ifc_cmd_pas_bits {
        u8         pa_h[0x20];
 
        u8         pa_l[0x14];
-       u8         reserved_0[0xc];
+       u8         reserved_at_34[0xc];
 };
 
 struct mlx5_ifc_uint64_bits {
@@ -418,31 +418,31 @@ enum {
 struct mlx5_ifc_ads_bits {
        u8         fl[0x1];
        u8         free_ar[0x1];
-       u8         reserved_0[0xe];
+       u8         reserved_at_2[0xe];
        u8         pkey_index[0x10];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_20[0x8];
        u8         grh[0x1];
        u8         mlid[0x7];
        u8         rlid[0x10];
 
        u8         ack_timeout[0x5];
-       u8         reserved_2[0x3];
+       u8         reserved_at_45[0x3];
        u8         src_addr_index[0x8];
-       u8         reserved_3[0x4];
+       u8         reserved_at_50[0x4];
        u8         stat_rate[0x4];
        u8         hop_limit[0x8];
 
-       u8         reserved_4[0x4];
+       u8         reserved_at_60[0x4];
        u8         tclass[0x8];
        u8         flow_label[0x14];
 
        u8         rgid_rip[16][0x8];
 
-       u8         reserved_5[0x4];
+       u8         reserved_at_100[0x4];
        u8         f_dscp[0x1];
        u8         f_ecn[0x1];
-       u8         reserved_6[0x1];
+       u8         reserved_at_106[0x1];
        u8         f_eth_prio[0x1];
        u8         ecn[0x2];
        u8         dscp[0x6];
@@ -458,25 +458,25 @@ struct mlx5_ifc_ads_bits {
 };
 
 struct mlx5_ifc_flow_table_nic_cap_bits {
-       u8         reserved_0[0x200];
+       u8         reserved_at_0[0x200];
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_receive;
 
-       u8         reserved_1[0x200];
+       u8         reserved_at_400[0x200];
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_receive_sniffer;
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_transmit;
 
-       u8         reserved_2[0x200];
+       u8         reserved_at_a00[0x200];
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_transmit_sniffer;
 
-       u8         reserved_3[0x7200];
+       u8         reserved_at_e00[0x7200];
 };
 
 struct mlx5_ifc_flow_table_eswitch_cap_bits {
-       u8     reserved_0[0x200];
+       u8     reserved_at_0[0x200];
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_esw_fdb;
 
@@ -484,7 +484,7 @@ struct mlx5_ifc_flow_table_eswitch_cap_bits {
 
        struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_esw_acl_egress;
 
-       u8      reserved_1[0x7800];
+       u8      reserved_at_800[0x7800];
 };
 
 struct mlx5_ifc_e_switch_cap_bits {
@@ -493,9 +493,9 @@ struct mlx5_ifc_e_switch_cap_bits {
        u8         vport_svlan_insert[0x1];
        u8         vport_cvlan_insert_if_not_exist[0x1];
        u8         vport_cvlan_insert_overwrite[0x1];
-       u8         reserved_0[0x1b];
+       u8         reserved_at_5[0x1b];
 
-       u8         reserved_1[0x7e0];
+       u8         reserved_at_20[0x7e0];
 };
 
 struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
@@ -504,51 +504,51 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
        u8         lro_cap[0x1];
        u8         lro_psh_flag[0x1];
        u8         lro_time_stamp[0x1];
-       u8         reserved_0[0x3];
+       u8         reserved_at_5[0x3];
        u8         self_lb_en_modifiable[0x1];
-       u8         reserved_1[0x2];
+       u8         reserved_at_9[0x2];
        u8         max_lso_cap[0x5];
-       u8         reserved_2[0x4];
+       u8         reserved_at_10[0x4];
        u8         rss_ind_tbl_cap[0x4];
-       u8         reserved_3[0x3];
+       u8         reserved_at_18[0x3];
        u8         tunnel_lso_const_out_ip_id[0x1];
-       u8         reserved_4[0x2];
+       u8         reserved_at_1c[0x2];
        u8         tunnel_statless_gre[0x1];
        u8         tunnel_stateless_vxlan[0x1];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_20[0x20];
 
-       u8         reserved_6[0x10];
+       u8         reserved_at_40[0x10];
        u8         lro_min_mss_size[0x10];
 
-       u8         reserved_7[0x120];
+       u8         reserved_at_60[0x120];
 
        u8         lro_timer_supported_periods[4][0x20];
 
-       u8         reserved_8[0x600];
+       u8         reserved_at_200[0x600];
 };
 
 struct mlx5_ifc_roce_cap_bits {
        u8         roce_apm[0x1];
-       u8         reserved_0[0x1f];
+       u8         reserved_at_1[0x1f];
 
-       u8         reserved_1[0x60];
+       u8         reserved_at_20[0x60];
 
-       u8         reserved_2[0xc];
+       u8         reserved_at_80[0xc];
        u8         l3_type[0x4];
-       u8         reserved_3[0x8];
+       u8         reserved_at_90[0x8];
        u8         roce_version[0x8];
 
-       u8         reserved_4[0x10];
+       u8         reserved_at_a0[0x10];
        u8         r_roce_dest_udp_port[0x10];
 
        u8         r_roce_max_src_udp_port[0x10];
        u8         r_roce_min_src_udp_port[0x10];
 
-       u8         reserved_5[0x10];
+       u8         reserved_at_e0[0x10];
        u8         roce_address_table_size[0x10];
 
-       u8         reserved_6[0x700];
+       u8         reserved_at_100[0x700];
 };
 
 enum {
@@ -576,35 +576,35 @@ enum {
 };
 
 struct mlx5_ifc_atomic_caps_bits {
-       u8         reserved_0[0x40];
+       u8         reserved_at_0[0x40];
 
        u8         atomic_req_8B_endianess_mode[0x2];
-       u8         reserved_1[0x4];
+       u8         reserved_at_42[0x4];
        u8         supported_atomic_req_8B_endianess_mode_1[0x1];
 
-       u8         reserved_2[0x19];
+       u8         reserved_at_47[0x19];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
-       u8         reserved_4[0x10];
+       u8         reserved_at_80[0x10];
        u8         atomic_operations[0x10];
 
-       u8         reserved_5[0x10];
+       u8         reserved_at_a0[0x10];
        u8         atomic_size_qp[0x10];
 
-       u8         reserved_6[0x10];
+       u8         reserved_at_c0[0x10];
        u8         atomic_size_dc[0x10];
 
-       u8         reserved_7[0x720];
+       u8         reserved_at_e0[0x720];
 };
 
 struct mlx5_ifc_odp_cap_bits {
-       u8         reserved_0[0x40];
+       u8         reserved_at_0[0x40];
 
        u8         sig[0x1];
-       u8         reserved_1[0x1f];
+       u8         reserved_at_41[0x1f];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_odp_per_transport_service_cap_bits rc_odp_caps;
 
@@ -612,7 +612,7 @@ struct mlx5_ifc_odp_cap_bits {
 
        struct mlx5_ifc_odp_per_transport_service_cap_bits ud_odp_caps;
 
-       u8         reserved_3[0x720];
+       u8         reserved_at_e0[0x720];
 };
 
 enum {
@@ -660,55 +660,55 @@ enum {
 };
 
 struct mlx5_ifc_cmd_hca_cap_bits {
-       u8         reserved_0[0x80];
+       u8         reserved_at_0[0x80];
 
        u8         log_max_srq_sz[0x8];
        u8         log_max_qp_sz[0x8];
-       u8         reserved_1[0xb];
+       u8         reserved_at_90[0xb];
        u8         log_max_qp[0x5];
 
-       u8         reserved_2[0xb];
+       u8         reserved_at_a0[0xb];
        u8         log_max_srq[0x5];
-       u8         reserved_3[0x10];
+       u8         reserved_at_b0[0x10];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_c0[0x8];
        u8         log_max_cq_sz[0x8];
-       u8         reserved_5[0xb];
+       u8         reserved_at_d0[0xb];
        u8         log_max_cq[0x5];
 
        u8         log_max_eq_sz[0x8];
-       u8         reserved_6[0x2];
+       u8         reserved_at_e8[0x2];
        u8         log_max_mkey[0x6];
-       u8         reserved_7[0xc];
+       u8         reserved_at_f0[0xc];
        u8         log_max_eq[0x4];
 
        u8         max_indirection[0x8];
-       u8         reserved_8[0x1];
+       u8         reserved_at_108[0x1];
        u8         log_max_mrw_sz[0x7];
-       u8         reserved_9[0x2];
+       u8         reserved_at_110[0x2];
        u8         log_max_bsf_list_size[0x6];
-       u8         reserved_10[0x2];
+       u8         reserved_at_118[0x2];
        u8         log_max_klm_list_size[0x6];
 
-       u8         reserved_11[0xa];
+       u8         reserved_at_120[0xa];
        u8         log_max_ra_req_dc[0x6];
-       u8         reserved_12[0xa];
+       u8         reserved_at_130[0xa];
        u8         log_max_ra_res_dc[0x6];
 
-       u8         reserved_13[0xa];
+       u8         reserved_at_140[0xa];
        u8         log_max_ra_req_qp[0x6];
-       u8         reserved_14[0xa];
+       u8         reserved_at_150[0xa];
        u8         log_max_ra_res_qp[0x6];
 
        u8         pad_cap[0x1];
        u8         cc_query_allowed[0x1];
        u8         cc_modify_allowed[0x1];
-       u8         reserved_15[0xd];
+       u8         reserved_at_163[0xd];
        u8         gid_table_size[0x10];
 
        u8         out_of_seq_cnt[0x1];
        u8         vport_counters[0x1];
-       u8         reserved_16[0x4];
+       u8         reserved_at_182[0x4];
        u8         max_qp_cnt[0xa];
        u8         pkey_table_size[0x10];
 
@@ -716,158 +716,158 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         vhca_group_manager[0x1];
        u8         ib_virt[0x1];
        u8         eth_virt[0x1];
-       u8         reserved_17[0x1];
+       u8         reserved_at_1a4[0x1];
        u8         ets[0x1];
        u8         nic_flow_table[0x1];
        u8         eswitch_flow_table[0x1];
        u8         early_vf_enable;
-       u8         reserved_18[0x2];
+       u8         reserved_at_1a8[0x2];
        u8         local_ca_ack_delay[0x5];
-       u8         reserved_19[0x6];
+       u8         reserved_at_1af[0x6];
        u8         port_type[0x2];
        u8         num_ports[0x8];
 
-       u8         reserved_20[0x3];
+       u8         reserved_at_1bf[0x3];
        u8         log_max_msg[0x5];
-       u8         reserved_21[0x18];
+       u8         reserved_at_1c7[0x18];
 
        u8         stat_rate_support[0x10];
-       u8         reserved_22[0xc];
+       u8         reserved_at_1ef[0xc];
        u8         cqe_version[0x4];
 
        u8         compact_address_vector[0x1];
-       u8         reserved_23[0xe];
+       u8         reserved_at_200[0xe];
        u8         drain_sigerr[0x1];
        u8         cmdif_checksum[0x2];
        u8         sigerr_cqe[0x1];
-       u8         reserved_24[0x1];
+       u8         reserved_at_212[0x1];
        u8         wq_signature[0x1];
        u8         sctr_data_cqe[0x1];
-       u8         reserved_25[0x1];
+       u8         reserved_at_215[0x1];
        u8         sho[0x1];
        u8         tph[0x1];
        u8         rf[0x1];
        u8         dct[0x1];
-       u8         reserved_26[0x1];
+       u8         reserved_at_21a[0x1];
        u8         eth_net_offloads[0x1];
        u8         roce[0x1];
        u8         atomic[0x1];
-       u8         reserved_27[0x1];
+       u8         reserved_at_21e[0x1];
 
        u8         cq_oi[0x1];
        u8         cq_resize[0x1];
        u8         cq_moderation[0x1];
-       u8         reserved_28[0x3];
+       u8         reserved_at_222[0x3];
        u8         cq_eq_remap[0x1];
        u8         pg[0x1];
        u8         block_lb_mc[0x1];
-       u8         reserved_29[0x1];
+       u8         reserved_at_228[0x1];
        u8         scqe_break_moderation[0x1];
-       u8         reserved_30[0x1];
+       u8         reserved_at_22a[0x1];
        u8         cd[0x1];
-       u8         reserved_31[0x1];
+       u8         reserved_at_22c[0x1];
        u8         apm[0x1];
-       u8         reserved_32[0x7];
+       u8         reserved_at_22e[0x7];
        u8         qkv[0x1];
        u8         pkv[0x1];
-       u8         reserved_33[0x4];
+       u8         reserved_at_237[0x4];
        u8         xrc[0x1];
        u8         ud[0x1];
        u8         uc[0x1];
        u8         rc[0x1];
 
-       u8         reserved_34[0xa];
+       u8         reserved_at_23f[0xa];
        u8         uar_sz[0x6];
-       u8         reserved_35[0x8];
+       u8         reserved_at_24f[0x8];
        u8         log_pg_sz[0x8];
 
        u8         bf[0x1];
-       u8         reserved_36[0x1];
+       u8         reserved_at_260[0x1];
        u8         pad_tx_eth_packet[0x1];
-       u8         reserved_37[0x8];
+       u8         reserved_at_262[0x8];
        u8         log_bf_reg_size[0x5];
-       u8         reserved_38[0x10];
+       u8         reserved_at_26f[0x10];
 
-       u8         reserved_39[0x10];
+       u8         reserved_at_27f[0x10];
        u8         max_wqe_sz_sq[0x10];
 
-       u8         reserved_40[0x10];
+       u8         reserved_at_29f[0x10];
        u8         max_wqe_sz_rq[0x10];
 
-       u8         reserved_41[0x10];
+       u8         reserved_at_2bf[0x10];
        u8         max_wqe_sz_sq_dc[0x10];
 
-       u8         reserved_42[0x7];
+       u8         reserved_at_2df[0x7];
        u8         max_qp_mcg[0x19];
 
-       u8         reserved_43[0x18];
+       u8         reserved_at_2ff[0x18];
        u8         log_max_mcg[0x8];
 
-       u8         reserved_44[0x3];
+       u8         reserved_at_31f[0x3];
        u8         log_max_transport_domain[0x5];
-       u8         reserved_45[0x3];
+       u8         reserved_at_327[0x3];
        u8         log_max_pd[0x5];
-       u8         reserved_46[0xb];
+       u8         reserved_at_32f[0xb];
        u8         log_max_xrcd[0x5];
 
-       u8         reserved_47[0x20];
+       u8         reserved_at_33f[0x20];
 
-       u8         reserved_48[0x3];
+       u8         reserved_at_35f[0x3];
        u8         log_max_rq[0x5];
-       u8         reserved_49[0x3];
+       u8         reserved_at_367[0x3];
        u8         log_max_sq[0x5];
-       u8         reserved_50[0x3];
+       u8         reserved_at_36f[0x3];
        u8         log_max_tir[0x5];
-       u8         reserved_51[0x3];
+       u8         reserved_at_377[0x3];
        u8         log_max_tis[0x5];
 
        u8         basic_cyclic_rcv_wqe[0x1];
-       u8         reserved_52[0x2];
+       u8         reserved_at_380[0x2];
        u8         log_max_rmp[0x5];
-       u8         reserved_53[0x3];
+       u8         reserved_at_387[0x3];
        u8         log_max_rqt[0x5];
-       u8         reserved_54[0x3];
+       u8         reserved_at_38f[0x3];
        u8         log_max_rqt_size[0x5];
-       u8         reserved_55[0x3];
+       u8         reserved_at_397[0x3];
        u8         log_max_tis_per_sq[0x5];
 
-       u8         reserved_56[0x3];
+       u8         reserved_at_39f[0x3];
        u8         log_max_stride_sz_rq[0x5];
-       u8         reserved_57[0x3];
+       u8         reserved_at_3a7[0x3];
        u8         log_min_stride_sz_rq[0x5];
-       u8         reserved_58[0x3];
+       u8         reserved_at_3af[0x3];
        u8         log_max_stride_sz_sq[0x5];
-       u8         reserved_59[0x3];
+       u8         reserved_at_3b7[0x3];
        u8         log_min_stride_sz_sq[0x5];
 
-       u8         reserved_60[0x1b];
+       u8         reserved_at_3bf[0x1b];
        u8         log_max_wq_sz[0x5];
 
        u8         nic_vport_change_event[0x1];
-       u8         reserved_61[0xa];
+       u8         reserved_at_3e0[0xa];
        u8         log_max_vlan_list[0x5];
-       u8         reserved_62[0x3];
+       u8         reserved_at_3ef[0x3];
        u8         log_max_current_mc_list[0x5];
-       u8         reserved_63[0x3];
+       u8         reserved_at_3f7[0x3];
        u8         log_max_current_uc_list[0x5];
 
-       u8         reserved_64[0x80];
+       u8         reserved_at_3ff[0x80];
 
-       u8         reserved_65[0x3];
+       u8         reserved_at_47f[0x3];
        u8         log_max_l2_table[0x5];
-       u8         reserved_66[0x8];
+       u8         reserved_at_487[0x8];
        u8         log_uar_page_sz[0x10];
 
-       u8         reserved_67[0x20];
+       u8         reserved_at_49f[0x20];
        u8         device_frequency_mhz[0x20];
        u8         device_frequency_khz[0x20];
-       u8         reserved_68[0x5f];
+       u8         reserved_at_4ff[0x5f];
        u8         cqe_zip[0x1];
 
        u8         cqe_zip_timeout[0x10];
        u8         cqe_zip_max_num[0x10];
 
-       u8         reserved_69[0x220];
+       u8         reserved_at_57f[0x220];
 };
 
 enum mlx5_flow_destination_type {
@@ -880,7 +880,7 @@ struct mlx5_ifc_dest_format_struct_bits {
        u8         destination_type[0x8];
        u8         destination_id[0x18];
 
-       u8         reserved_0[0x20];
+       u8         reserved_at_20[0x20];
 };
 
 struct mlx5_ifc_fte_match_param_bits {
@@ -890,7 +890,7 @@ struct mlx5_ifc_fte_match_param_bits {
 
        struct mlx5_ifc_fte_match_set_lyr_2_4_bits inner_headers;
 
-       u8         reserved_0[0xa00];
+       u8         reserved_at_600[0xa00];
 };
 
 enum {
@@ -922,18 +922,18 @@ struct mlx5_ifc_wq_bits {
        u8         wq_signature[0x1];
        u8         end_padding_mode[0x2];
        u8         cd_slave[0x1];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         hds_skip_first_sge[0x1];
        u8         log2_hds_buf_size[0x3];
-       u8         reserved_1[0x7];
+       u8         reserved_at_24[0x7];
        u8         page_offset[0x5];
        u8         lwm[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         pd[0x18];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_60[0x8];
        u8         uar_page[0x18];
 
        u8         dbr_addr[0x40];
@@ -942,60 +942,60 @@ struct mlx5_ifc_wq_bits {
 
        u8         sw_counter[0x20];
 
-       u8         reserved_4[0xc];
+       u8         reserved_at_100[0xc];
        u8         log_wq_stride[0x4];
-       u8         reserved_5[0x3];
+       u8         reserved_at_110[0x3];
        u8         log_wq_pg_sz[0x5];
-       u8         reserved_6[0x3];
+       u8         reserved_at_118[0x3];
        u8         log_wq_sz[0x5];
 
-       u8         reserved_7[0x4e0];
+       u8         reserved_at_120[0x4e0];
 
        struct mlx5_ifc_cmd_pas_bits pas[0];
 };
 
 struct mlx5_ifc_rq_num_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         rq_num[0x18];
 };
 
 struct mlx5_ifc_mac_address_layout_bits {
-       u8         reserved_0[0x10];
+       u8         reserved_at_0[0x10];
        u8         mac_addr_47_32[0x10];
 
        u8         mac_addr_31_0[0x20];
 };
 
 struct mlx5_ifc_vlan_layout_bits {
-       u8         reserved_0[0x14];
+       u8         reserved_at_0[0x14];
        u8         vlan[0x0c];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_20[0x20];
 };
 
 struct mlx5_ifc_cong_control_r_roce_ecn_np_bits {
-       u8         reserved_0[0xa0];
+       u8         reserved_at_0[0xa0];
 
        u8         min_time_between_cnps[0x20];
 
-       u8         reserved_1[0x12];
+       u8         reserved_at_c0[0x12];
        u8         cnp_dscp[0x6];
-       u8         reserved_2[0x5];
+       u8         reserved_at_d8[0x5];
        u8         cnp_802p_prio[0x3];
 
-       u8         reserved_3[0x720];
+       u8         reserved_at_e0[0x720];
 };
 
 struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits {
-       u8         reserved_0[0x60];
+       u8         reserved_at_0[0x60];
 
-       u8         reserved_1[0x4];
+       u8         reserved_at_60[0x4];
        u8         clamp_tgt_rate[0x1];
-       u8         reserved_2[0x3];
+       u8         reserved_at_65[0x3];
        u8         clamp_tgt_rate_after_time_inc[0x1];
-       u8         reserved_3[0x17];
+       u8         reserved_at_69[0x17];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_80[0x20];
 
        u8         rpg_time_reset[0x20];
 
@@ -1015,7 +1015,7 @@ struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits {
 
        u8         rpg_min_rate[0x20];
 
-       u8         reserved_5[0xe0];
+       u8         reserved_at_1c0[0xe0];
 
        u8         rate_to_set_on_first_cnp[0x20];
 
@@ -1025,15 +1025,15 @@ struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits {
 
        u8         rate_reduce_monitor_period[0x20];
 
-       u8         reserved_6[0x20];
+       u8         reserved_at_320[0x20];
 
        u8         initial_alpha_value[0x20];
 
-       u8         reserved_7[0x4a0];
+       u8         reserved_at_360[0x4a0];
 };
 
 struct mlx5_ifc_cong_control_802_1qau_rp_bits {
-       u8         reserved_0[0x80];
+       u8         reserved_at_0[0x80];
 
        u8         rppp_max_rps[0x20];
 
@@ -1055,7 +1055,7 @@ struct mlx5_ifc_cong_control_802_1qau_rp_bits {
 
        u8         rpg_min_rate[0x20];
 
-       u8         reserved_1[0x640];
+       u8         reserved_at_1c0[0x640];
 };
 
 enum {
@@ -1205,7 +1205,7 @@ struct mlx5_ifc_phys_layer_cntrs_bits {
 
        u8         successful_recovery_events[0x20];
 
-       u8         reserved_0[0x180];
+       u8         reserved_at_640[0x180];
 };
 
 struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits {
@@ -1213,7 +1213,7 @@ struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits {
 
        u8         transmit_queue_low[0x20];
 
-       u8         reserved_0[0x780];
+       u8         reserved_at_40[0x780];
 };
 
 struct mlx5_ifc_eth_per_prio_grp_data_layout_bits {
@@ -1221,7 +1221,7 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits {
 
        u8         rx_octets_low[0x20];
 
-       u8         reserved_0[0xc0];
+       u8         reserved_at_40[0xc0];
 
        u8         rx_frames_high[0x20];
 
@@ -1231,7 +1231,7 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits {
 
        u8         tx_octets_low[0x20];
 
-       u8         reserved_1[0xc0];
+       u8         reserved_at_180[0xc0];
 
        u8         tx_frames_high[0x20];
 
@@ -1257,7 +1257,7 @@ struct mlx5_ifc_eth_per_prio_grp_data_layout_bits {
 
        u8         rx_pause_transition_low[0x20];
 
-       u8         reserved_2[0x400];
+       u8         reserved_at_3c0[0x400];
 };
 
 struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits {
@@ -1265,7 +1265,7 @@ struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits {
 
        u8         port_transmit_wait_low[0x20];
 
-       u8         reserved_0[0x780];
+       u8         reserved_at_40[0x780];
 };
 
 struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits {
@@ -1333,7 +1333,7 @@ struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits {
 
        u8         dot3out_pause_frames_low[0x20];
 
-       u8         reserved_0[0x3c0];
+       u8         reserved_at_400[0x3c0];
 };
 
 struct mlx5_ifc_eth_2819_cntrs_grp_data_layout_bits {
@@ -1421,7 +1421,7 @@ struct mlx5_ifc_eth_2819_cntrs_grp_data_layout_bits {
 
        u8         ether_stats_pkts8192to10239octets_low[0x20];
 
-       u8         reserved_0[0x280];
+       u8         reserved_at_540[0x280];
 };
 
 struct mlx5_ifc_eth_2863_cntrs_grp_data_layout_bits {
@@ -1477,7 +1477,7 @@ struct mlx5_ifc_eth_2863_cntrs_grp_data_layout_bits {
 
        u8         if_out_broadcast_pkts_low[0x20];
 
-       u8         reserved_0[0x480];
+       u8         reserved_at_340[0x480];
 };
 
 struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits {
@@ -1557,54 +1557,54 @@ struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits {
 
        u8         a_pause_mac_ctrl_frames_transmitted_low[0x20];
 
-       u8         reserved_0[0x300];
+       u8         reserved_at_4c0[0x300];
 };
 
 struct mlx5_ifc_cmd_inter_comp_event_bits {
        u8         command_completion_vector[0x20];
 
-       u8         reserved_0[0xc0];
+       u8         reserved_at_20[0xc0];
 };
 
 struct mlx5_ifc_stall_vl_event_bits {
-       u8         reserved_0[0x18];
+       u8         reserved_at_0[0x18];
        u8         port_num[0x1];
-       u8         reserved_1[0x3];
+       u8         reserved_at_19[0x3];
        u8         vl[0x4];
 
-       u8         reserved_2[0xa0];
+       u8         reserved_at_20[0xa0];
 };
 
 struct mlx5_ifc_db_bf_congestion_event_bits {
        u8         event_subtype[0x8];
-       u8         reserved_0[0x8];
+       u8         reserved_at_8[0x8];
        u8         congestion_level[0x8];
-       u8         reserved_1[0x8];
+       u8         reserved_at_18[0x8];
 
-       u8         reserved_2[0xa0];
+       u8         reserved_at_20[0xa0];
 };
 
 struct mlx5_ifc_gpio_event_bits {
-       u8         reserved_0[0x60];
+       u8         reserved_at_0[0x60];
 
        u8         gpio_event_hi[0x20];
 
        u8         gpio_event_lo[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_a0[0x40];
 };
 
 struct mlx5_ifc_port_state_change_event_bits {
-       u8         reserved_0[0x40];
+       u8         reserved_at_0[0x40];
 
        u8         port_num[0x4];
-       u8         reserved_1[0x1c];
+       u8         reserved_at_44[0x1c];
 
-       u8         reserved_2[0x80];
+       u8         reserved_at_60[0x80];
 };
 
 struct mlx5_ifc_dropped_packet_logged_bits {
-       u8         reserved_0[0xe0];
+       u8         reserved_at_0[0xe0];
 };
 
 enum {
@@ -1613,15 +1613,15 @@ enum {
 };
 
 struct mlx5_ifc_cq_error_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         cqn[0x18];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_20[0x20];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         syndrome[0x8];
 
-       u8         reserved_3[0x80];
+       u8         reserved_at_60[0x80];
 };
 
 struct mlx5_ifc_rdma_page_fault_event_bits {
@@ -1629,14 +1629,14 @@ struct mlx5_ifc_rdma_page_fault_event_bits {
 
        u8         r_key[0x20];
 
-       u8         reserved_0[0x10];
+       u8         reserved_at_40[0x10];
        u8         packet_len[0x10];
 
        u8         rdma_op_len[0x20];
 
        u8         rdma_va[0x40];
 
-       u8         reserved_1[0x5];
+       u8         reserved_at_c0[0x5];
        u8         rdma[0x1];
        u8         write[0x1];
        u8         requestor[0x1];
@@ -1646,15 +1646,15 @@ struct mlx5_ifc_rdma_page_fault_event_bits {
 struct mlx5_ifc_wqe_associated_page_fault_event_bits {
        u8         bytes_committed[0x20];
 
-       u8         reserved_0[0x10];
+       u8         reserved_at_20[0x10];
        u8         wqe_index[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_40[0x10];
        u8         len[0x10];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_60[0x60];
 
-       u8         reserved_3[0x5];
+       u8         reserved_at_c0[0x5];
        u8         rdma[0x1];
        u8         write_read[0x1];
        u8         requestor[0x1];
@@ -1662,26 +1662,26 @@ struct mlx5_ifc_wqe_associated_page_fault_event_bits {
 };
 
 struct mlx5_ifc_qp_events_bits {
-       u8         reserved_0[0xa0];
+       u8         reserved_at_0[0xa0];
 
        u8         type[0x8];
-       u8         reserved_1[0x18];
+       u8         reserved_at_a8[0x18];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_c0[0x8];
        u8         qpn_rqn_sqn[0x18];
 };
 
 struct mlx5_ifc_dct_events_bits {
-       u8         reserved_0[0xc0];
+       u8         reserved_at_0[0xc0];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_c0[0x8];
        u8         dct_number[0x18];
 };
 
 struct mlx5_ifc_comp_event_bits {
-       u8         reserved_0[0xc0];
+       u8         reserved_at_0[0xc0];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_c0[0x8];
        u8         cq_number[0x18];
 };
 
@@ -1754,41 +1754,41 @@ enum {
 
 struct mlx5_ifc_qpc_bits {
        u8         state[0x4];
-       u8         reserved_0[0x4];
+       u8         reserved_at_4[0x4];
        u8         st[0x8];
-       u8         reserved_1[0x3];
+       u8         reserved_at_10[0x3];
        u8         pm_state[0x2];
-       u8         reserved_2[0x7];
+       u8         reserved_at_15[0x7];
        u8         end_padding_mode[0x2];
-       u8         reserved_3[0x2];
+       u8         reserved_at_1e[0x2];
 
        u8         wq_signature[0x1];
        u8         block_lb_mc[0x1];
        u8         atomic_like_write_en[0x1];
        u8         latency_sensitive[0x1];
-       u8         reserved_4[0x1];
+       u8         reserved_at_24[0x1];
        u8         drain_sigerr[0x1];
-       u8         reserved_5[0x2];
+       u8         reserved_at_26[0x2];
        u8         pd[0x18];
 
        u8         mtu[0x3];
        u8         log_msg_max[0x5];
-       u8         reserved_6[0x1];
+       u8         reserved_at_48[0x1];
        u8         log_rq_size[0x4];
        u8         log_rq_stride[0x3];
        u8         no_sq[0x1];
        u8         log_sq_size[0x4];
-       u8         reserved_7[0x6];
+       u8         reserved_at_55[0x6];
        u8         rlky[0x1];
-       u8         reserved_8[0x4];
+       u8         reserved_at_5c[0x4];
 
        u8         counter_set_id[0x8];
        u8         uar_page[0x18];
 
-       u8         reserved_9[0x8];
+       u8         reserved_at_80[0x8];
        u8         user_index[0x18];
 
-       u8         reserved_10[0x3];
+       u8         reserved_at_a0[0x3];
        u8         log_page_size[0x5];
        u8         remote_qpn[0x18];
 
@@ -1797,66 +1797,66 @@ struct mlx5_ifc_qpc_bits {
        struct mlx5_ifc_ads_bits secondary_address_path;
 
        u8         log_ack_req_freq[0x4];
-       u8         reserved_11[0x4];
+       u8         reserved_at_384[0x4];
        u8         log_sra_max[0x3];
-       u8         reserved_12[0x2];
+       u8         reserved_at_38b[0x2];
        u8         retry_count[0x3];
        u8         rnr_retry[0x3];
-       u8         reserved_13[0x1];
+       u8         reserved_at_393[0x1];
        u8         fre[0x1];
        u8         cur_rnr_retry[0x3];
        u8         cur_retry_count[0x3];
-       u8         reserved_14[0x5];
+       u8         reserved_at_39b[0x5];
 
-       u8         reserved_15[0x20];
+       u8         reserved_at_3a0[0x20];
 
-       u8         reserved_16[0x8];
+       u8         reserved_at_3c0[0x8];
        u8         next_send_psn[0x18];
 
-       u8         reserved_17[0x8];
+       u8         reserved_at_3e0[0x8];
        u8         cqn_snd[0x18];
 
-       u8         reserved_18[0x40];
+       u8         reserved_at_400[0x40];
 
-       u8         reserved_19[0x8];
+       u8         reserved_at_440[0x8];
        u8         last_acked_psn[0x18];
 
-       u8         reserved_20[0x8];
+       u8         reserved_at_460[0x8];
        u8         ssn[0x18];
 
-       u8         reserved_21[0x8];
+       u8         reserved_at_480[0x8];
        u8         log_rra_max[0x3];
-       u8         reserved_22[0x1];
+       u8         reserved_at_48b[0x1];
        u8         atomic_mode[0x4];
        u8         rre[0x1];
        u8         rwe[0x1];
        u8         rae[0x1];
-       u8         reserved_23[0x1];
+       u8         reserved_at_493[0x1];
        u8         page_offset[0x6];
-       u8         reserved_24[0x3];
+       u8         reserved_at_49a[0x3];
        u8         cd_slave_receive[0x1];
        u8         cd_slave_send[0x1];
        u8         cd_master[0x1];
 
-       u8         reserved_25[0x3];
+       u8         reserved_at_4a0[0x3];
        u8         min_rnr_nak[0x5];
        u8         next_rcv_psn[0x18];
 
-       u8         reserved_26[0x8];
+       u8         reserved_at_4c0[0x8];
        u8         xrcd[0x18];
 
-       u8         reserved_27[0x8];
+       u8         reserved_at_4e0[0x8];
        u8         cqn_rcv[0x18];
 
        u8         dbr_addr[0x40];
 
        u8         q_key[0x20];
 
-       u8         reserved_28[0x5];
+       u8         reserved_at_560[0x5];
        u8         rq_type[0x3];
        u8         srqn_rmpn[0x18];
 
-       u8         reserved_29[0x8];
+       u8         reserved_at_580[0x8];
        u8         rmsn[0x18];
 
        u8         hw_sq_wqebb_counter[0x10];
@@ -1866,33 +1866,33 @@ struct mlx5_ifc_qpc_bits {
 
        u8         sw_rq_counter[0x20];
 
-       u8         reserved_30[0x20];
+       u8         reserved_at_600[0x20];
 
-       u8         reserved_31[0xf];
+       u8         reserved_at_620[0xf];
        u8         cgs[0x1];
        u8         cs_req[0x8];
        u8         cs_res[0x8];
 
        u8         dc_access_key[0x40];
 
-       u8         reserved_32[0xc0];
+       u8         reserved_at_680[0xc0];
 };
 
 struct mlx5_ifc_roce_addr_layout_bits {
        u8         source_l3_address[16][0x8];
 
-       u8         reserved_0[0x3];
+       u8         reserved_at_80[0x3];
        u8         vlan_valid[0x1];
        u8         vlan_id[0xc];
        u8         source_mac_47_32[0x10];
 
        u8         source_mac_31_0[0x20];
 
-       u8         reserved_1[0x14];
+       u8         reserved_at_c0[0x14];
        u8         roce_l3_type[0x4];
        u8         roce_version[0x8];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_e0[0x20];
 };
 
 union mlx5_ifc_hca_cap_union_bits {
@@ -1904,7 +1904,7 @@ union mlx5_ifc_hca_cap_union_bits {
        struct mlx5_ifc_flow_table_nic_cap_bits flow_table_nic_cap;
        struct mlx5_ifc_flow_table_eswitch_cap_bits flow_table_eswitch_cap;
        struct mlx5_ifc_e_switch_cap_bits e_switch_cap;
-       u8         reserved_0[0x8000];
+       u8         reserved_at_0[0x8000];
 };
 
 enum {
@@ -1914,24 +1914,24 @@ enum {
 };
 
 struct mlx5_ifc_flow_context_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
        u8         group_id[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         flow_tag[0x18];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_60[0x10];
        u8         action[0x10];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_80[0x8];
        u8         destination_list_size[0x18];
 
-       u8         reserved_4[0x160];
+       u8         reserved_at_a0[0x160];
 
        struct mlx5_ifc_fte_match_param_bits match_value;
 
-       u8         reserved_5[0x600];
+       u8         reserved_at_1200[0x600];
 
        struct mlx5_ifc_dest_format_struct_bits destination[0];
 };
@@ -1944,43 +1944,43 @@ enum {
 struct mlx5_ifc_xrc_srqc_bits {
        u8         state[0x4];
        u8         log_xrc_srq_size[0x4];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         wq_signature[0x1];
        u8         cont_srq[0x1];
-       u8         reserved_1[0x1];
+       u8         reserved_at_22[0x1];
        u8         rlky[0x1];
        u8         basic_cyclic_rcv_wqe[0x1];
        u8         log_rq_stride[0x3];
        u8         xrcd[0x18];
 
        u8         page_offset[0x6];
-       u8         reserved_2[0x2];
+       u8         reserved_at_46[0x2];
        u8         cqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         user_index_equal_xrc_srqn[0x1];
-       u8         reserved_4[0x1];
+       u8         reserved_at_81[0x1];
        u8         log_page_size[0x6];
        u8         user_index[0x18];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_a0[0x20];
 
-       u8         reserved_6[0x8];
+       u8         reserved_at_c0[0x8];
        u8         pd[0x18];
 
        u8         lwm[0x10];
        u8         wqe_cnt[0x10];
 
-       u8         reserved_7[0x40];
+       u8         reserved_at_100[0x40];
 
        u8         db_record_addr_h[0x20];
 
        u8         db_record_addr_l[0x1e];
-       u8         reserved_8[0x2];
+       u8         reserved_at_17e[0x2];
 
-       u8         reserved_9[0x80];
+       u8         reserved_at_180[0x80];
 };
 
 struct mlx5_ifc_traffic_counter_bits {
@@ -1990,16 +1990,16 @@ struct mlx5_ifc_traffic_counter_bits {
 };
 
 struct mlx5_ifc_tisc_bits {
-       u8         reserved_0[0xc];
+       u8         reserved_at_0[0xc];
        u8         prio[0x4];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x100];
+       u8         reserved_at_20[0x100];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_120[0x8];
        u8         transport_domain[0x18];
 
-       u8         reserved_4[0x3c0];
+       u8         reserved_at_140[0x3c0];
 };
 
 enum {
@@ -2024,31 +2024,31 @@ enum {
 };
 
 struct mlx5_ifc_tirc_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
        u8         disp_type[0x4];
-       u8         reserved_1[0x1c];
+       u8         reserved_at_24[0x1c];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
-       u8         reserved_3[0x4];
+       u8         reserved_at_80[0x4];
        u8         lro_timeout_period_usecs[0x10];
        u8         lro_enable_mask[0x4];
        u8         lro_max_ip_payload_size[0x8];
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_a0[0x40];
 
-       u8         reserved_5[0x8];
+       u8         reserved_at_e0[0x8];
        u8         inline_rqn[0x18];
 
        u8         rx_hash_symmetric[0x1];
-       u8         reserved_6[0x1];
+       u8         reserved_at_101[0x1];
        u8         tunneled_offload_en[0x1];
-       u8         reserved_7[0x5];
+       u8         reserved_at_103[0x5];
        u8         indirect_table[0x18];
 
        u8         rx_hash_fn[0x4];
-       u8         reserved_8[0x2];
+       u8         reserved_at_124[0x2];
        u8         self_lb_block[0x2];
        u8         transport_domain[0x18];
 
@@ -2058,7 +2058,7 @@ struct mlx5_ifc_tirc_bits {
 
        struct mlx5_ifc_rx_hash_field_select_bits rx_hash_field_selector_inner;
 
-       u8         reserved_9[0x4c0];
+       u8         reserved_at_2c0[0x4c0];
 };
 
 enum {
@@ -2069,39 +2069,39 @@ enum {
 struct mlx5_ifc_srqc_bits {
        u8         state[0x4];
        u8         log_srq_size[0x4];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         wq_signature[0x1];
        u8         cont_srq[0x1];
-       u8         reserved_1[0x1];
+       u8         reserved_at_22[0x1];
        u8         rlky[0x1];
-       u8         reserved_2[0x1];
+       u8         reserved_at_24[0x1];
        u8         log_rq_stride[0x3];
        u8         xrcd[0x18];
 
        u8         page_offset[0x6];
-       u8         reserved_3[0x2];
+       u8         reserved_at_46[0x2];
        u8         cqn[0x18];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_60[0x20];
 
-       u8         reserved_5[0x2];
+       u8         reserved_at_80[0x2];
        u8         log_page_size[0x6];
-       u8         reserved_6[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_7[0x20];
+       u8         reserved_at_a0[0x20];
 
-       u8         reserved_8[0x8];
+       u8         reserved_at_c0[0x8];
        u8         pd[0x18];
 
        u8         lwm[0x10];
        u8         wqe_cnt[0x10];
 
-       u8         reserved_9[0x40];
+       u8         reserved_at_100[0x40];
 
        u8         dbr_addr[0x40];
 
-       u8         reserved_10[0x80];
+       u8         reserved_at_180[0x80];
 };
 
 enum {
@@ -2115,39 +2115,39 @@ struct mlx5_ifc_sqc_bits {
        u8         cd_master[0x1];
        u8         fre[0x1];
        u8         flush_in_error_en[0x1];
-       u8         reserved_0[0x4];
+       u8         reserved_at_4[0x4];
        u8         state[0x4];
-       u8         reserved_1[0x14];
+       u8         reserved_at_c[0x14];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_20[0x8];
        u8         user_index[0x18];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
-       u8         reserved_4[0xa0];
+       u8         reserved_at_60[0xa0];
 
        u8         tis_lst_sz[0x10];
-       u8         reserved_5[0x10];
+       u8         reserved_at_110[0x10];
 
-       u8         reserved_6[0x40];
+       u8         reserved_at_120[0x40];
 
-       u8         reserved_7[0x8];
+       u8         reserved_at_160[0x8];
        u8         tis_num_0[0x18];
 
        struct mlx5_ifc_wq_bits wq;
 };
 
 struct mlx5_ifc_rqtc_bits {
-       u8         reserved_0[0xa0];
+       u8         reserved_at_0[0xa0];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_a0[0x10];
        u8         rqt_max_size[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_c0[0x10];
        u8         rqt_actual_size[0x10];
 
-       u8         reserved_3[0x6a0];
+       u8         reserved_at_e0[0x6a0];
 
        struct mlx5_ifc_rq_num_bits rq_num[0];
 };
@@ -2165,27 +2165,27 @@ enum {
 
 struct mlx5_ifc_rqc_bits {
        u8         rlky[0x1];
-       u8         reserved_0[0x2];
+       u8         reserved_at_1[0x2];
        u8         vsd[0x1];
        u8         mem_rq_type[0x4];
        u8         state[0x4];
-       u8         reserved_1[0x1];
+       u8         reserved_at_c[0x1];
        u8         flush_in_error_en[0x1];
-       u8         reserved_2[0x12];
+       u8         reserved_at_e[0x12];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_20[0x8];
        u8         user_index[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
        u8         counter_set_id[0x8];
-       u8         reserved_5[0x18];
+       u8         reserved_at_68[0x18];
 
-       u8         reserved_6[0x8];
+       u8         reserved_at_80[0x8];
        u8         rmpn[0x18];
 
-       u8         reserved_7[0xe0];
+       u8         reserved_at_a0[0xe0];
 
        struct mlx5_ifc_wq_bits wq;
 };
@@ -2196,31 +2196,31 @@ enum {
 };
 
 struct mlx5_ifc_rmpc_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         state[0x4];
-       u8         reserved_1[0x14];
+       u8         reserved_at_c[0x14];
 
        u8         basic_cyclic_rcv_wqe[0x1];
-       u8         reserved_2[0x1f];
+       u8         reserved_at_21[0x1f];
 
-       u8         reserved_3[0x140];
+       u8         reserved_at_40[0x140];
 
        struct mlx5_ifc_wq_bits wq;
 };
 
 struct mlx5_ifc_nic_vport_context_bits {
-       u8         reserved_0[0x1f];
+       u8         reserved_at_0[0x1f];
        u8         roce_en[0x1];
 
        u8         arm_change_event[0x1];
-       u8         reserved_1[0x1a];
+       u8         reserved_at_21[0x1a];
        u8         event_on_mtu[0x1];
        u8         event_on_promisc_change[0x1];
        u8         event_on_vlan_change[0x1];
        u8         event_on_mc_address_change[0x1];
        u8         event_on_uc_address_change[0x1];
 
-       u8         reserved_2[0xf0];
+       u8         reserved_at_40[0xf0];
 
        u8         mtu[0x10];
 
@@ -2228,21 +2228,21 @@ struct mlx5_ifc_nic_vport_context_bits {
        u8         port_guid[0x40];
        u8         node_guid[0x40];
 
-       u8         reserved_3[0x140];
+       u8         reserved_at_200[0x140];
        u8         qkey_violation_counter[0x10];
-       u8         reserved_4[0x430];
+       u8         reserved_at_350[0x430];
 
        u8         promisc_uc[0x1];
        u8         promisc_mc[0x1];
        u8         promisc_all[0x1];
-       u8         reserved_5[0x2];
+       u8         reserved_at_783[0x2];
        u8         allowed_list_type[0x3];
-       u8         reserved_6[0xc];
+       u8         reserved_at_788[0xc];
        u8         allowed_list_size[0xc];
 
        struct mlx5_ifc_mac_address_layout_bits permanent_address;
 
-       u8         reserved_7[0x20];
+       u8         reserved_at_7e0[0x20];
 
        u8         current_uc_mac_address[0][0x40];
 };
@@ -2254,9 +2254,9 @@ enum {
 };
 
 struct mlx5_ifc_mkc_bits {
-       u8         reserved_0[0x1];
+       u8         reserved_at_0[0x1];
        u8         free[0x1];
-       u8         reserved_1[0xd];
+       u8         reserved_at_2[0xd];
        u8         small_fence_on_rdma_read_response[0x1];
        u8         umr_en[0x1];
        u8         a[0x1];
@@ -2265,19 +2265,19 @@ struct mlx5_ifc_mkc_bits {
        u8         lw[0x1];
        u8         lr[0x1];
        u8         access_mode[0x2];
-       u8         reserved_2[0x8];
+       u8         reserved_at_18[0x8];
 
        u8         qpn[0x18];
        u8         mkey_7_0[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_40[0x20];
 
        u8         length64[0x1];
        u8         bsf_en[0x1];
        u8         sync_umr[0x1];
-       u8         reserved_4[0x2];
+       u8         reserved_at_63[0x2];
        u8         expected_sigerr_count[0x1];
-       u8         reserved_5[0x1];
+       u8         reserved_at_66[0x1];
        u8         en_rinval[0x1];
        u8         pd[0x18];
 
@@ -2287,18 +2287,18 @@ struct mlx5_ifc_mkc_bits {
 
        u8         bsf_octword_size[0x20];
 
-       u8         reserved_6[0x80];
+       u8         reserved_at_120[0x80];
 
        u8         translations_octword_size[0x20];
 
-       u8         reserved_7[0x1b];
+       u8         reserved_at_1c0[0x1b];
        u8         log_page_size[0x5];
 
-       u8         reserved_8[0x20];
+       u8         reserved_at_1e0[0x20];
 };
 
 struct mlx5_ifc_pkey_bits {
-       u8         reserved_0[0x10];
+       u8         reserved_at_0[0x10];
        u8         pkey[0x10];
 };
 
@@ -2309,19 +2309,19 @@ struct mlx5_ifc_array128_auto_bits {
 struct mlx5_ifc_hca_vport_context_bits {
        u8         field_select[0x20];
 
-       u8         reserved_0[0xe0];
+       u8         reserved_at_20[0xe0];
 
        u8         sm_virt_aware[0x1];
        u8         has_smi[0x1];
        u8         has_raw[0x1];
        u8         grh_required[0x1];
-       u8         reserved_1[0xc];
+       u8         reserved_at_104[0xc];
        u8         port_physical_state[0x4];
        u8         vport_state_policy[0x4];
        u8         port_state[0x4];
        u8         vport_state[0x4];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_120[0x20];
 
        u8         system_image_guid[0x40];
 
@@ -2337,33 +2337,33 @@ struct mlx5_ifc_hca_vport_context_bits {
 
        u8         cap_mask2_field_select[0x20];
 
-       u8         reserved_3[0x80];
+       u8         reserved_at_280[0x80];
 
        u8         lid[0x10];
-       u8         reserved_4[0x4];
+       u8         reserved_at_310[0x4];
        u8         init_type_reply[0x4];
        u8         lmc[0x3];
        u8         subnet_timeout[0x5];
 
        u8         sm_lid[0x10];
        u8         sm_sl[0x4];
-       u8         reserved_5[0xc];
+       u8         reserved_at_334[0xc];
 
        u8         qkey_violation_counter[0x10];
        u8         pkey_violation_counter[0x10];
 
-       u8         reserved_6[0xca0];
+       u8         reserved_at_360[0xca0];
 };
 
 struct mlx5_ifc_esw_vport_context_bits {
-       u8         reserved_0[0x3];
+       u8         reserved_at_0[0x3];
        u8         vport_svlan_strip[0x1];
        u8         vport_cvlan_strip[0x1];
        u8         vport_svlan_insert[0x1];
        u8         vport_cvlan_insert[0x2];
-       u8         reserved_1[0x18];
+       u8         reserved_at_8[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_20[0x20];
 
        u8         svlan_cfi[0x1];
        u8         svlan_pcp[0x3];
@@ -2372,7 +2372,7 @@ struct mlx5_ifc_esw_vport_context_bits {
        u8         cvlan_pcp[0x3];
        u8         cvlan_id[0xc];
 
-       u8         reserved_3[0x7a0];
+       u8         reserved_at_60[0x7a0];
 };
 
 enum {
@@ -2387,41 +2387,41 @@ enum {
 
 struct mlx5_ifc_eqc_bits {
        u8         status[0x4];
-       u8         reserved_0[0x9];
+       u8         reserved_at_4[0x9];
        u8         ec[0x1];
        u8         oi[0x1];
-       u8         reserved_1[0x5];
+       u8         reserved_at_f[0x5];
        u8         st[0x4];
-       u8         reserved_2[0x8];
+       u8         reserved_at_18[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_20[0x20];
 
-       u8         reserved_4[0x14];
+       u8         reserved_at_40[0x14];
        u8         page_offset[0x6];
-       u8         reserved_5[0x6];
+       u8         reserved_at_5a[0x6];
 
-       u8         reserved_6[0x3];
+       u8         reserved_at_60[0x3];
        u8         log_eq_size[0x5];
        u8         uar_page[0x18];
 
-       u8         reserved_7[0x20];
+       u8         reserved_at_80[0x20];
 
-       u8         reserved_8[0x18];
+       u8         reserved_at_a0[0x18];
        u8         intr[0x8];
 
-       u8         reserved_9[0x3];
+       u8         reserved_at_c0[0x3];
        u8         log_page_size[0x5];
-       u8         reserved_10[0x18];
+       u8         reserved_at_c8[0x18];
 
-       u8         reserved_11[0x60];
+       u8         reserved_at_e0[0x60];
 
-       u8         reserved_12[0x8];
+       u8         reserved_at_140[0x8];
        u8         consumer_counter[0x18];
 
-       u8         reserved_13[0x8];
+       u8         reserved_at_160[0x8];
        u8         producer_counter[0x18];
 
-       u8         reserved_14[0x80];
+       u8         reserved_at_180[0x80];
 };
 
 enum {
@@ -2445,14 +2445,14 @@ enum {
 };
 
 struct mlx5_ifc_dctc_bits {
-       u8         reserved_0[0x4];
+       u8         reserved_at_0[0x4];
        u8         state[0x4];
-       u8         reserved_1[0x18];
+       u8         reserved_at_8[0x18];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_20[0x8];
        u8         user_index[0x18];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
        u8         counter_set_id[0x8];
@@ -2464,45 +2464,45 @@ struct mlx5_ifc_dctc_bits {
        u8         latency_sensitive[0x1];
        u8         rlky[0x1];
        u8         free_ar[0x1];
-       u8         reserved_4[0xd];
+       u8         reserved_at_73[0xd];
 
-       u8         reserved_5[0x8];
+       u8         reserved_at_80[0x8];
        u8         cs_res[0x8];
-       u8         reserved_6[0x3];
+       u8         reserved_at_90[0x3];
        u8         min_rnr_nak[0x5];
-       u8         reserved_7[0x8];
+       u8         reserved_at_98[0x8];
 
-       u8         reserved_8[0x8];
+       u8         reserved_at_a0[0x8];
        u8         srqn[0x18];
 
-       u8         reserved_9[0x8];
+       u8         reserved_at_c0[0x8];
        u8         pd[0x18];
 
        u8         tclass[0x8];
-       u8         reserved_10[0x4];
+       u8         reserved_at_e8[0x4];
        u8         flow_label[0x14];
 
        u8         dc_access_key[0x40];
 
-       u8         reserved_11[0x5];
+       u8         reserved_at_140[0x5];
        u8         mtu[0x3];
        u8         port[0x8];
        u8         pkey_index[0x10];
 
-       u8         reserved_12[0x8];
+       u8         reserved_at_160[0x8];
        u8         my_addr_index[0x8];
-       u8         reserved_13[0x8];
+       u8         reserved_at_170[0x8];
        u8         hop_limit[0x8];
 
        u8         dc_access_key_violation_count[0x20];
 
-       u8         reserved_14[0x14];
+       u8         reserved_at_1a0[0x14];
        u8         dei_cfi[0x1];
        u8         eth_prio[0x3];
        u8         ecn[0x2];
        u8         dscp[0x6];
 
-       u8         reserved_15[0x40];
+       u8         reserved_at_1c0[0x40];
 };
 
 enum {
@@ -2524,54 +2524,54 @@ enum {
 
 struct mlx5_ifc_cqc_bits {
        u8         status[0x4];
-       u8         reserved_0[0x4];
+       u8         reserved_at_4[0x4];
        u8         cqe_sz[0x3];
        u8         cc[0x1];
-       u8         reserved_1[0x1];
+       u8         reserved_at_c[0x1];
        u8         scqe_break_moderation_en[0x1];
        u8         oi[0x1];
-       u8         reserved_2[0x2];
+       u8         reserved_at_f[0x2];
        u8         cqe_zip_en[0x1];
        u8         mini_cqe_res_format[0x2];
        u8         st[0x4];
-       u8         reserved_3[0x8];
+       u8         reserved_at_18[0x8];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_20[0x20];
 
-       u8         reserved_5[0x14];
+       u8         reserved_at_40[0x14];
        u8         page_offset[0x6];
-       u8         reserved_6[0x6];
+       u8         reserved_at_5a[0x6];
 
-       u8         reserved_7[0x3];
+       u8         reserved_at_60[0x3];
        u8         log_cq_size[0x5];
        u8         uar_page[0x18];
 
-       u8         reserved_8[0x4];
+       u8         reserved_at_80[0x4];
        u8         cq_period[0xc];
        u8         cq_max_count[0x10];
 
-       u8         reserved_9[0x18];
+       u8         reserved_at_a0[0x18];
        u8         c_eqn[0x8];
 
-       u8         reserved_10[0x3];
+       u8         reserved_at_c0[0x3];
        u8         log_page_size[0x5];
-       u8         reserved_11[0x18];
+       u8         reserved_at_c8[0x18];
 
-       u8         reserved_12[0x20];
+       u8         reserved_at_e0[0x20];
 
-       u8         reserved_13[0x8];
+       u8         reserved_at_100[0x8];
        u8         last_notified_index[0x18];
 
-       u8         reserved_14[0x8];
+       u8         reserved_at_120[0x8];
        u8         last_solicit_index[0x18];
 
-       u8         reserved_15[0x8];
+       u8         reserved_at_140[0x8];
        u8         consumer_counter[0x18];
 
-       u8         reserved_16[0x8];
+       u8         reserved_at_160[0x8];
        u8         producer_counter[0x18];
 
-       u8         reserved_17[0x40];
+       u8         reserved_at_180[0x40];
 
        u8         dbr_addr[0x40];
 };
@@ -2580,16 +2580,16 @@ union mlx5_ifc_cong_control_roce_ecn_auto_bits {
        struct mlx5_ifc_cong_control_802_1qau_rp_bits cong_control_802_1qau_rp;
        struct mlx5_ifc_cong_control_r_roce_ecn_rp_bits cong_control_r_roce_ecn_rp;
        struct mlx5_ifc_cong_control_r_roce_ecn_np_bits cong_control_r_roce_ecn_np;
-       u8         reserved_0[0x800];
+       u8         reserved_at_0[0x800];
 };
 
 struct mlx5_ifc_query_adapter_param_block_bits {
-       u8         reserved_0[0xc0];
+       u8         reserved_at_0[0xc0];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_c0[0x8];
        u8         ieee_vendor_id[0x18];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_e0[0x10];
        u8         vsd_vendor_id[0x10];
 
        u8         vsd[208][0x8];
@@ -2600,14 +2600,14 @@ struct mlx5_ifc_query_adapter_param_block_bits {
 union mlx5_ifc_modify_field_select_resize_field_select_auto_bits {
        struct mlx5_ifc_modify_field_select_bits modify_field_select;
        struct mlx5_ifc_resize_field_select_bits resize_field_select;
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 };
 
 union mlx5_ifc_field_select_802_1_r_roce_auto_bits {
        struct mlx5_ifc_field_select_802_1qau_rp_bits field_select_802_1qau_rp;
        struct mlx5_ifc_field_select_r_roce_rp_bits field_select_r_roce_rp;
        struct mlx5_ifc_field_select_r_roce_np_bits field_select_r_roce_np;
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 };
 
 union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits {
@@ -2619,7 +2619,7 @@ union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits {
        struct mlx5_ifc_eth_per_prio_grp_data_layout_bits eth_per_prio_grp_data_layout;
        struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits eth_per_traffic_grp_data_layout;
        struct mlx5_ifc_phys_layer_cntrs_bits phys_layer_cntrs;
-       u8         reserved_0[0x7c0];
+       u8         reserved_at_0[0x7c0];
 };
 
 union mlx5_ifc_event_auto_bits {
@@ -2635,23 +2635,23 @@ union mlx5_ifc_event_auto_bits {
        struct mlx5_ifc_db_bf_congestion_event_bits db_bf_congestion_event;
        struct mlx5_ifc_stall_vl_event_bits stall_vl_event;
        struct mlx5_ifc_cmd_inter_comp_event_bits cmd_inter_comp_event;
-       u8         reserved_0[0xe0];
+       u8         reserved_at_0[0xe0];
 };
 
 struct mlx5_ifc_health_buffer_bits {
-       u8         reserved_0[0x100];
+       u8         reserved_at_0[0x100];
 
        u8         assert_existptr[0x20];
 
        u8         assert_callra[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_140[0x40];
 
        u8         fw_version[0x20];
 
        u8         hw_id[0x20];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_1c0[0x20];
 
        u8         irisc_index[0x8];
        u8         synd[0x8];
@@ -2660,20 +2660,20 @@ struct mlx5_ifc_health_buffer_bits {
 
 struct mlx5_ifc_register_loopback_control_bits {
        u8         no_lb[0x1];
-       u8         reserved_0[0x7];
+       u8         reserved_at_1[0x7];
        u8         port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_20[0x60];
 };
 
 struct mlx5_ifc_teardown_hca_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 enum {
@@ -2683,108 +2683,108 @@ enum {
 
 struct mlx5_ifc_teardown_hca_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         profile[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_sqerr2rts_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_sqerr2rts_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_sqd2rts_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_sqd2rts_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_set_roce_address_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_set_roce_address_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         roce_address_index[0x10];
-       u8         reserved_2[0x10];
+       u8         reserved_at_50[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_roce_addr_layout_bits roce_address;
 };
 
 struct mlx5_ifc_set_mad_demux_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 enum {
@@ -2794,89 +2794,89 @@ enum {
 
 struct mlx5_ifc_set_mad_demux_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_40[0x20];
 
-       u8         reserved_3[0x6];
+       u8         reserved_at_60[0x6];
        u8         demux_mode[0x2];
-       u8         reserved_4[0x18];
+       u8         reserved_at_68[0x18];
 };
 
 struct mlx5_ifc_set_l2_table_entry_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_set_l2_table_entry_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_40[0x60];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_index[0x18];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_c0[0x20];
 
-       u8         reserved_5[0x13];
+       u8         reserved_at_e0[0x13];
        u8         vlan_valid[0x1];
        u8         vlan[0xc];
 
        struct mlx5_ifc_mac_address_layout_bits mac_address;
 
-       u8         reserved_6[0xc0];
+       u8         reserved_at_140[0xc0];
 };
 
 struct mlx5_ifc_set_issi_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_set_issi_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         current_issi[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_set_hca_cap_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_set_hca_cap_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        union mlx5_ifc_hca_cap_union_bits capability;
 };
@@ -2890,156 +2890,156 @@ enum {
 
 struct mlx5_ifc_set_fte_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_set_fte_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x18];
+       u8         reserved_at_c0[0x18];
        u8         modify_enable_mask[0x8];
 
-       u8         reserved_6[0x20];
+       u8         reserved_at_e0[0x20];
 
        u8         flow_index[0x20];
 
-       u8         reserved_7[0xe0];
+       u8         reserved_at_120[0xe0];
 
        struct mlx5_ifc_flow_context_bits flow_context;
 };
 
 struct mlx5_ifc_rts2rts_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_rts2rts_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_rtr2rts_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_rtr2rts_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_rst2init_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_rst2init_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_query_xrc_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_xrc_srqc_bits xrc_srq_context_entry;
 
-       u8         reserved_2[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_query_xrc_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         xrc_srqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 enum {
@@ -3049,13 +3049,13 @@ enum {
 
 struct mlx5_ifc_query_vport_state_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_40[0x20];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_60[0x18];
        u8         admin_state[0x4];
        u8         state[0x4];
 };
@@ -3067,25 +3067,25 @@ enum {
 
 struct mlx5_ifc_query_vport_state_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_vport_counter_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_traffic_counter_bits received_errors;
 
@@ -3111,7 +3111,7 @@ struct mlx5_ifc_query_vport_counter_out_bits {
 
        struct mlx5_ifc_traffic_counter_bits transmitted_eth_multicast;
 
-       u8         reserved_2[0xa00];
+       u8         reserved_at_680[0xa00];
 };
 
 enum {
@@ -3120,328 +3120,328 @@ enum {
 
 struct mlx5_ifc_query_vport_counter_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x60];
+       u8         reserved_at_60[0x60];
 
        u8         clear[0x1];
-       u8         reserved_4[0x1f];
+       u8         reserved_at_c1[0x1f];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_e0[0x20];
 };
 
 struct mlx5_ifc_query_tis_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_tisc_bits tis_context;
 };
 
 struct mlx5_ifc_query_tis_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         tisn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_tir_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_tirc_bits tir_context;
 };
 
 struct mlx5_ifc_query_tir_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         tirn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_srqc_bits srq_context_entry;
 
-       u8         reserved_2[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_query_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         srqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_sq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_sqc_bits sq_context;
 };
 
 struct mlx5_ifc_query_sq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         sqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_special_contexts_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_40[0x20];
 
        u8         resd_lkey[0x20];
 };
 
 struct mlx5_ifc_query_special_contexts_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_query_rqt_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_rqtc_bits rqt_context;
 };
 
 struct mlx5_ifc_query_rqt_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqtn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_rq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_rqc_bits rq_context;
 };
 
 struct mlx5_ifc_query_rq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_roce_address_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_roce_addr_layout_bits roce_address;
 };
 
 struct mlx5_ifc_query_roce_address_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         roce_address_index[0x10];
-       u8         reserved_2[0x10];
+       u8         reserved_at_50[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_rmp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_rmpc_bits rmp_context;
 };
 
 struct mlx5_ifc_query_rmp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rmpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_3[0x80];
+       u8         reserved_at_800[0x80];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_query_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_q_counter_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         rx_write_requests[0x20];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_a0[0x20];
 
        u8         rx_read_requests[0x20];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_e0[0x20];
 
        u8         rx_atomic_requests[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_120[0x20];
 
        u8         rx_dct_connect[0x20];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_160[0x20];
 
        u8         out_of_buffer[0x20];
 
-       u8         reserved_6[0x20];
+       u8         reserved_at_1a0[0x20];
 
        u8         out_of_sequence[0x20];
 
-       u8         reserved_7[0x620];
+       u8         reserved_at_1e0[0x620];
 };
 
 struct mlx5_ifc_query_q_counter_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x80];
+       u8         reserved_at_40[0x80];
 
        u8         clear[0x1];
-       u8         reserved_3[0x1f];
+       u8         reserved_at_c1[0x1f];
 
-       u8         reserved_4[0x18];
+       u8         reserved_at_e0[0x18];
        u8         counter_set_id[0x8];
 };
 
 struct mlx5_ifc_query_pages_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_40[0x10];
        u8         function_id[0x10];
 
        u8         num_pages[0x20];
@@ -3455,55 +3455,55 @@ enum {
 
 struct mlx5_ifc_query_pages_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         function_id[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_nic_vport_context_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_nic_vport_context_bits nic_vport_context;
 };
 
 struct mlx5_ifc_query_nic_vport_context_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x5];
+       u8         reserved_at_60[0x5];
        u8         allowed_list_type[0x3];
-       u8         reserved_4[0x18];
+       u8         reserved_at_68[0x18];
 };
 
 struct mlx5_ifc_query_mkey_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_mkc_bits memory_key_mkey_entry;
 
-       u8         reserved_2[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         bsf0_klm0_pas_mtt0_1[16][0x8];
 
@@ -3512,265 +3512,265 @@ struct mlx5_ifc_query_mkey_out_bits {
 
 struct mlx5_ifc_query_mkey_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         mkey_index[0x18];
 
        u8         pg_access[0x1];
-       u8         reserved_3[0x1f];
+       u8         reserved_at_61[0x1f];
 };
 
 struct mlx5_ifc_query_mad_demux_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         mad_dumux_parameters_block[0x20];
 };
 
 struct mlx5_ifc_query_mad_demux_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_query_l2_table_entry_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xa0];
+       u8         reserved_at_40[0xa0];
 
-       u8         reserved_2[0x13];
+       u8         reserved_at_e0[0x13];
        u8         vlan_valid[0x1];
        u8         vlan[0xc];
 
        struct mlx5_ifc_mac_address_layout_bits mac_address;
 
-       u8         reserved_3[0xc0];
+       u8         reserved_at_140[0xc0];
 };
 
 struct mlx5_ifc_query_l2_table_entry_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_40[0x60];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_index[0x18];
 
-       u8         reserved_4[0x140];
+       u8         reserved_at_c0[0x140];
 };
 
 struct mlx5_ifc_query_issi_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_40[0x10];
        u8         current_issi[0x10];
 
-       u8         reserved_2[0xa0];
+       u8         reserved_at_60[0xa0];
 
-       u8         supported_issi_reserved[76][0x8];
+       u8         reserved_at_100[76][0x8];
        u8         supported_issi_dw0[0x20];
 };
 
 struct mlx5_ifc_query_issi_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_query_hca_vport_pkey_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_pkey_bits pkey[0];
 };
 
 struct mlx5_ifc_query_hca_vport_pkey_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xb];
+       u8         reserved_at_41[0xb];
        u8         port_num[0x4];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         pkey_index[0x10];
 };
 
 struct mlx5_ifc_query_hca_vport_gid_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_40[0x20];
 
        u8         gids_num[0x10];
-       u8         reserved_2[0x10];
+       u8         reserved_at_70[0x10];
 
        struct mlx5_ifc_array128_auto_bits gid[0];
 };
 
 struct mlx5_ifc_query_hca_vport_gid_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xb];
+       u8         reserved_at_41[0xb];
        u8         port_num[0x4];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         gid_index[0x10];
 };
 
 struct mlx5_ifc_query_hca_vport_context_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_hca_vport_context_bits hca_vport_context;
 };
 
 struct mlx5_ifc_query_hca_vport_context_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xb];
+       u8         reserved_at_41[0xb];
        u8         port_num[0x4];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_hca_cap_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        union mlx5_ifc_hca_cap_union_bits capability;
 };
 
 struct mlx5_ifc_query_hca_cap_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_query_flow_table_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x80];
+       u8         reserved_at_40[0x80];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_c0[0x8];
        u8         level[0x8];
-       u8         reserved_3[0x8];
+       u8         reserved_at_d0[0x8];
        u8         log_size[0x8];
 
-       u8         reserved_4[0x120];
+       u8         reserved_at_e0[0x120];
 };
 
 struct mlx5_ifc_query_flow_table_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x140];
+       u8         reserved_at_c0[0x140];
 };
 
 struct mlx5_ifc_query_fte_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x1c0];
+       u8         reserved_at_40[0x1c0];
 
        struct mlx5_ifc_flow_context_bits flow_context;
 };
 
 struct mlx5_ifc_query_fte_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x40];
+       u8         reserved_at_c0[0x40];
 
        u8         flow_index[0x20];
 
-       u8         reserved_6[0xe0];
+       u8         reserved_at_120[0xe0];
 };
 
 enum {
@@ -3781,84 +3781,84 @@ enum {
 
 struct mlx5_ifc_query_flow_group_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0xa0];
+       u8         reserved_at_40[0xa0];
 
        u8         start_flow_index[0x20];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_100[0x20];
 
        u8         end_flow_index[0x20];
 
-       u8         reserved_3[0xa0];
+       u8         reserved_at_140[0xa0];
 
-       u8         reserved_4[0x18];
+       u8         reserved_at_1e0[0x18];
        u8         match_criteria_enable[0x8];
 
        struct mlx5_ifc_fte_match_param_bits match_criteria;
 
-       u8         reserved_5[0xe00];
+       u8         reserved_at_1200[0xe00];
 };
 
 struct mlx5_ifc_query_flow_group_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
        u8         group_id[0x20];
 
-       u8         reserved_5[0x120];
+       u8         reserved_at_e0[0x120];
 };
 
 struct mlx5_ifc_query_esw_vport_context_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_esw_vport_context_bits esw_vport_context;
 };
 
 struct mlx5_ifc_query_esw_vport_context_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_modify_esw_vport_context_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_esw_vport_context_fields_select_bits {
-       u8         reserved[0x1c];
+       u8         reserved_at_0[0x1c];
        u8         vport_cvlan_insert[0x1];
        u8         vport_svlan_insert[0x1];
        u8         vport_cvlan_strip[0x1];
@@ -3867,13 +3867,13 @@ struct mlx5_ifc_esw_vport_context_fields_select_bits {
 
 struct mlx5_ifc_modify_esw_vport_context_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
        struct mlx5_ifc_esw_vport_context_fields_select_bits field_select;
@@ -3883,124 +3883,124 @@ struct mlx5_ifc_modify_esw_vport_context_in_bits {
 
 struct mlx5_ifc_query_eq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_eqc_bits eq_context_entry;
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_280[0x40];
 
        u8         event_bitmask[0x40];
 
-       u8         reserved_3[0x580];
+       u8         reserved_at_300[0x580];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_query_eq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         eq_number[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_dct_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_dctc_bits dct_context_entry;
 
-       u8         reserved_2[0x180];
+       u8         reserved_at_280[0x180];
 };
 
 struct mlx5_ifc_query_dct_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         dctn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_cq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_cqc_bits cq_context;
 
-       u8         reserved_2[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_query_cq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_cong_status_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_40[0x20];
 
        u8         enable[0x1];
        u8         tag_enable[0x1];
-       u8         reserved_2[0x1e];
+       u8         reserved_at_62[0x1e];
 };
 
 struct mlx5_ifc_query_cong_status_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         priority[0x4];
        u8         cong_protocol[0x4];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_cong_statistics_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         cur_flows[0x20];
 
@@ -4014,7 +4014,7 @@ struct mlx5_ifc_query_cong_statistics_out_bits {
 
        u8         cnp_handled_low[0x20];
 
-       u8         reserved_2[0x100];
+       u8         reserved_at_140[0x100];
 
        u8         time_stamp_high[0x20];
 
@@ -4030,453 +4030,453 @@ struct mlx5_ifc_query_cong_statistics_out_bits {
 
        u8         cnps_sent_low[0x20];
 
-       u8         reserved_3[0x560];
+       u8         reserved_at_320[0x560];
 };
 
 struct mlx5_ifc_query_cong_statistics_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         clear[0x1];
-       u8         reserved_2[0x1f];
+       u8         reserved_at_41[0x1f];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_cong_params_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        union mlx5_ifc_cong_control_roce_ecn_auto_bits congestion_parameters;
 };
 
 struct mlx5_ifc_query_cong_params_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x1c];
+       u8         reserved_at_40[0x1c];
        u8         cong_protocol[0x4];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_query_adapter_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_query_adapter_param_block_bits query_adapter_struct;
 };
 
 struct mlx5_ifc_query_adapter_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_qp_2rst_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_qp_2rst_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_qp_2err_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_qp_2err_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_page_fault_resume_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_page_fault_resume_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         error[0x1];
-       u8         reserved_2[0x4];
+       u8         reserved_at_41[0x4];
        u8         rdma[0x1];
        u8         read_write[0x1];
        u8         req_res[0x1];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_nop_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_nop_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_vport_state_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_vport_state_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x18];
+       u8         reserved_at_60[0x18];
        u8         admin_state[0x4];
-       u8         reserved_4[0x4];
+       u8         reserved_at_7c[0x4];
 };
 
 struct mlx5_ifc_modify_tis_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_tis_bitmask_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
-       u8         reserved_1[0x1f];
+       u8         reserved_at_20[0x1f];
        u8         prio[0x1];
 };
 
 struct mlx5_ifc_modify_tis_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         tisn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_modify_tis_bitmask_bits bitmask;
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_tisc_bits ctx;
 };
 
 struct mlx5_ifc_modify_tir_bitmask_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
-       u8         reserved_1[0x1b];
+       u8         reserved_at_20[0x1b];
        u8         self_lb_en[0x1];
-       u8         reserved_2[0x3];
+       u8         reserved_at_3c[0x3];
        u8         lro[0x1];
 };
 
 struct mlx5_ifc_modify_tir_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_tir_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         tirn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_modify_tir_bitmask_bits bitmask;
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_tirc_bits ctx;
 };
 
 struct mlx5_ifc_modify_sq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_sq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         sq_state[0x4];
-       u8         reserved_2[0x4];
+       u8         reserved_at_44[0x4];
        u8         sqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         modify_bitmask[0x40];
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_sqc_bits ctx;
 };
 
 struct mlx5_ifc_modify_rqt_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_rqt_bitmask_bits {
-       u8         reserved[0x20];
+       u8         reserved_at_0[0x20];
 
-       u8         reserved1[0x1f];
+       u8         reserved_at_20[0x1f];
        u8         rqn_list[0x1];
 };
 
 struct mlx5_ifc_modify_rqt_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqtn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_rqt_bitmask_bits bitmask;
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_rqtc_bits ctx;
 };
 
 struct mlx5_ifc_modify_rq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_rq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         rq_state[0x4];
-       u8         reserved_2[0x4];
+       u8         reserved_at_44[0x4];
        u8         rqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         modify_bitmask[0x40];
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_rqc_bits ctx;
 };
 
 struct mlx5_ifc_modify_rmp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_rmp_bitmask_bits {
-       u8         reserved[0x20];
+       u8         reserved_at_0[0x20];
 
-       u8         reserved1[0x1f];
+       u8         reserved_at_20[0x1f];
        u8         lwm[0x1];
 };
 
 struct mlx5_ifc_modify_rmp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         rmp_state[0x4];
-       u8         reserved_2[0x4];
+       u8         reserved_at_44[0x4];
        u8         rmpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_rmp_bitmask_bits bitmask;
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_c0[0x40];
 
        struct mlx5_ifc_rmpc_bits ctx;
 };
 
 struct mlx5_ifc_modify_nic_vport_context_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_nic_vport_field_select_bits {
-       u8         reserved_0[0x19];
+       u8         reserved_at_0[0x19];
        u8         mtu[0x1];
        u8         change_event[0x1];
        u8         promisc[0x1];
        u8         permanent_address[0x1];
        u8         addresses_list[0x1];
        u8         roce_en[0x1];
-       u8         reserved_1[0x1];
+       u8         reserved_at_1f[0x1];
 };
 
 struct mlx5_ifc_modify_nic_vport_context_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xf];
+       u8         reserved_at_41[0xf];
        u8         vport_number[0x10];
 
        struct mlx5_ifc_modify_nic_vport_field_select_bits field_select;
 
-       u8         reserved_3[0x780];
+       u8         reserved_at_80[0x780];
 
        struct mlx5_ifc_nic_vport_context_bits nic_vport_context;
 };
 
 struct mlx5_ifc_modify_hca_vport_context_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_hca_vport_context_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         other_vport[0x1];
-       u8         reserved_2[0xb];
+       u8         reserved_at_41[0xb];
        u8         port_num[0x4];
        u8         vport_number[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        struct mlx5_ifc_hca_vport_context_bits hca_vport_context;
 };
 
 struct mlx5_ifc_modify_cq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 enum {
@@ -4486,83 +4486,83 @@ enum {
 
 struct mlx5_ifc_modify_cq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
        union mlx5_ifc_modify_field_select_resize_field_select_auto_bits modify_field_select_resize_field_select;
 
        struct mlx5_ifc_cqc_bits cq_context;
 
-       u8         reserved_3[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_modify_cong_status_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_cong_status_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         priority[0x4];
        u8         cong_protocol[0x4];
 
        u8         enable[0x1];
        u8         tag_enable[0x1];
-       u8         reserved_3[0x1e];
+       u8         reserved_at_62[0x1e];
 };
 
 struct mlx5_ifc_modify_cong_params_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_cong_params_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x1c];
+       u8         reserved_at_40[0x1c];
        u8         cong_protocol[0x4];
 
        union mlx5_ifc_field_select_802_1_r_roce_auto_bits field_select;
 
-       u8         reserved_3[0x80];
+       u8         reserved_at_80[0x80];
 
        union mlx5_ifc_cong_control_roce_ecn_auto_bits congestion_parameters;
 };
 
 struct mlx5_ifc_manage_pages_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
        u8         output_num_entries[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         pas[0][0x40];
 };
@@ -4575,12 +4575,12 @@ enum {
 
 struct mlx5_ifc_manage_pages_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         function_id[0x10];
 
        u8         input_num_entries[0x20];
@@ -4590,117 +4590,117 @@ struct mlx5_ifc_manage_pages_in_bits {
 
 struct mlx5_ifc_mad_ifc_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         response_mad_packet[256][0x8];
 };
 
 struct mlx5_ifc_mad_ifc_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         remote_lid[0x10];
-       u8         reserved_2[0x8];
+       u8         reserved_at_50[0x8];
        u8         port[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         mad[256][0x8];
 };
 
 struct mlx5_ifc_init_hca_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_init_hca_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_init2rtr_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_init2rtr_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_init2init_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_init2init_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_800[0x80];
 };
 
 struct mlx5_ifc_get_dropped_packet_log_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         packet_headers_log[128][0x8];
 
@@ -4709,1029 +4709,1029 @@ struct mlx5_ifc_get_dropped_packet_log_out_bits {
 
 struct mlx5_ifc_get_dropped_packet_log_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_gen_eqe_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         eq_number[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         eqe[64][0x8];
 };
 
 struct mlx5_ifc_gen_eq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_enable_hca_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_40[0x20];
 };
 
 struct mlx5_ifc_enable_hca_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         function_id[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_drain_dct_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_drain_dct_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         dctn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_disable_hca_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_40[0x20];
 };
 
 struct mlx5_ifc_disable_hca_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         function_id[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_detach_from_mcg_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_detach_from_mcg_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         multicast_gid[16][0x8];
 };
 
 struct mlx5_ifc_destroy_xrc_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_xrc_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         xrc_srqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_tis_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_tis_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         tisn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_tir_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_tir_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         tirn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         srqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_sq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_sq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         sqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_rqt_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_rqt_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqtn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_rq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_rq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_rmp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_rmp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         rmpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_psv_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_psv_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         psvn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_mkey_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_mkey_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         mkey_index[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_flow_table_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_flow_table_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x140];
+       u8         reserved_at_c0[0x140];
 };
 
 struct mlx5_ifc_destroy_flow_group_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_flow_group_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
        u8         group_id[0x20];
 
-       u8         reserved_5[0x120];
+       u8         reserved_at_e0[0x120];
 };
 
 struct mlx5_ifc_destroy_eq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_eq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         eq_number[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_dct_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_dct_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         dctn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_destroy_cq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_destroy_cq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_delete_vxlan_udp_dport_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_delete_vxlan_udp_dport_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_40[0x20];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         vxlan_udp_port[0x10];
 };
 
 struct mlx5_ifc_delete_l2_table_entry_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_delete_l2_table_entry_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_40[0x60];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_index[0x18];
 
-       u8         reserved_4[0x140];
+       u8         reserved_at_c0[0x140];
 };
 
 struct mlx5_ifc_delete_fte_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_delete_fte_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x40];
+       u8         reserved_at_c0[0x40];
 
        u8         flow_index[0x20];
 
-       u8         reserved_6[0xe0];
+       u8         reserved_at_120[0xe0];
 };
 
 struct mlx5_ifc_dealloc_xrcd_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_dealloc_xrcd_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         xrcd[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_dealloc_uar_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_dealloc_uar_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         uar[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_dealloc_transport_domain_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_dealloc_transport_domain_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         transport_domain[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_dealloc_q_counter_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_dealloc_q_counter_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_40[0x18];
        u8         counter_set_id[0x8];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_dealloc_pd_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_dealloc_pd_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         pd[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_xrc_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         xrc_srqn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_xrc_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_xrc_srqc_bits xrc_srq_context_entry;
 
-       u8         reserved_3[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_create_tis_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         tisn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_tis_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_tisc_bits ctx;
 };
 
 struct mlx5_ifc_create_tir_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         tirn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_tir_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_tirc_bits ctx;
 };
 
 struct mlx5_ifc_create_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         srqn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_srqc_bits srq_context_entry;
 
-       u8         reserved_3[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_create_sq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         sqn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_sq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_sqc_bits ctx;
 };
 
 struct mlx5_ifc_create_rqt_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqtn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_rqt_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_rqtc_bits rqt_context;
 };
 
 struct mlx5_ifc_create_rq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         rqn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_rq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_rqc_bits ctx;
 };
 
 struct mlx5_ifc_create_rmp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         rmpn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_rmp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0xc0];
+       u8         reserved_at_40[0xc0];
 
        struct mlx5_ifc_rmpc_bits ctx;
 };
 
 struct mlx5_ifc_create_qp_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_qp_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         opt_param_mask[0x20];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_a0[0x20];
 
        struct mlx5_ifc_qpc_bits qpc;
 
-       u8         reserved_4[0x80];
+       u8         reserved_at_800[0x80];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_create_psv_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_80[0x8];
        u8         psv0_index[0x18];
 
-       u8         reserved_3[0x8];
+       u8         reserved_at_a0[0x8];
        u8         psv1_index[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_c0[0x8];
        u8         psv2_index[0x18];
 
-       u8         reserved_5[0x8];
+       u8         reserved_at_e0[0x8];
        u8         psv3_index[0x18];
 };
 
 struct mlx5_ifc_create_psv_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         num_psv[0x4];
-       u8         reserved_2[0x4];
+       u8         reserved_at_44[0x4];
        u8         pd[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_mkey_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         mkey_index[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_mkey_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_40[0x20];
 
        u8         pg_access[0x1];
-       u8         reserved_3[0x1f];
+       u8         reserved_at_61[0x1f];
 
        struct mlx5_ifc_mkc_bits memory_key_mkey_entry;
 
-       u8         reserved_4[0x80];
+       u8         reserved_at_280[0x80];
 
        u8         translations_octword_actual_size[0x20];
 
-       u8         reserved_5[0x560];
+       u8         reserved_at_320[0x560];
 
        u8         klm_pas_mtt[0][0x20];
 };
 
 struct mlx5_ifc_create_flow_table_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_flow_table_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_a0[0x20];
 
-       u8         reserved_5[0x4];
+       u8         reserved_at_c0[0x4];
        u8         table_miss_mode[0x4];
        u8         level[0x8];
-       u8         reserved_6[0x8];
+       u8         reserved_at_d0[0x8];
        u8         log_size[0x8];
 
-       u8         reserved_7[0x8];
+       u8         reserved_at_e0[0x8];
        u8         table_miss_id[0x18];
 
-       u8         reserved_8[0x100];
+       u8         reserved_at_100[0x100];
 };
 
 struct mlx5_ifc_create_flow_group_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         group_id[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 enum {
@@ -5742,134 +5742,134 @@ enum {
 
 struct mlx5_ifc_create_flow_group_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_c0[0x20];
 
        u8         start_flow_index[0x20];
 
-       u8         reserved_6[0x20];
+       u8         reserved_at_100[0x20];
 
        u8         end_flow_index[0x20];
 
-       u8         reserved_7[0xa0];
+       u8         reserved_at_140[0xa0];
 
-       u8         reserved_8[0x18];
+       u8         reserved_at_1e0[0x18];
        u8         match_criteria_enable[0x8];
 
        struct mlx5_ifc_fte_match_param_bits match_criteria;
 
-       u8         reserved_9[0xe00];
+       u8         reserved_at_1200[0xe00];
 };
 
 struct mlx5_ifc_create_eq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x18];
+       u8         reserved_at_40[0x18];
        u8         eq_number[0x8];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_eq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_eqc_bits eq_context_entry;
 
-       u8         reserved_3[0x40];
+       u8         reserved_at_280[0x40];
 
        u8         event_bitmask[0x40];
 
-       u8         reserved_4[0x580];
+       u8         reserved_at_300[0x580];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_create_dct_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         dctn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_dct_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_dctc_bits dct_context_entry;
 
-       u8         reserved_3[0x180];
+       u8         reserved_at_280[0x180];
 };
 
 struct mlx5_ifc_create_cq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         cqn[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_create_cq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        struct mlx5_ifc_cqc_bits cq_context;
 
-       u8         reserved_3[0x600];
+       u8         reserved_at_280[0x600];
 
        u8         pas[0][0x40];
 };
 
 struct mlx5_ifc_config_int_moderation_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x4];
+       u8         reserved_at_40[0x4];
        u8         min_delay[0xc];
        u8         int_vector[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 enum {
@@ -5879,49 +5879,49 @@ enum {
 
 struct mlx5_ifc_config_int_moderation_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x4];
+       u8         reserved_at_40[0x4];
        u8         min_delay[0xc];
        u8         int_vector[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_attach_to_mcg_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_attach_to_mcg_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         qpn[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 
        u8         multicast_gid[16][0x8];
 };
 
 struct mlx5_ifc_arm_xrc_srq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 enum {
@@ -5930,25 +5930,25 @@ enum {
 
 struct mlx5_ifc_arm_xrc_srq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         xrc_srqn[0x18];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         lwm[0x10];
 };
 
 struct mlx5_ifc_arm_rq_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 enum {
@@ -5957,179 +5957,179 @@ enum {
 
 struct mlx5_ifc_arm_rq_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         srq_number[0x18];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         lwm[0x10];
 };
 
 struct mlx5_ifc_arm_dct_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_arm_dct_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_40[0x8];
        u8         dct_number[0x18];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_alloc_xrcd_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         xrcd[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_alloc_xrcd_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_alloc_uar_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         uar[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_alloc_uar_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_alloc_transport_domain_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         transport_domain[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_alloc_transport_domain_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_alloc_q_counter_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x18];
+       u8         reserved_at_40[0x18];
        u8         counter_set_id[0x8];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_alloc_q_counter_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_alloc_pd_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x8];
+       u8         reserved_at_40[0x8];
        u8         pd[0x18];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_60[0x20];
 };
 
 struct mlx5_ifc_alloc_pd_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_add_vxlan_udp_dport_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_add_vxlan_udp_dport_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_40[0x20];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         vxlan_udp_port[0x10];
 };
 
 struct mlx5_ifc_access_register_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         register_data[0][0x20];
 };
@@ -6141,12 +6141,12 @@ enum {
 
 struct mlx5_ifc_access_register_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x10];
+       u8         reserved_at_40[0x10];
        u8         register_id[0x10];
 
        u8         argument[0x20];
@@ -6159,24 +6159,24 @@ struct mlx5_ifc_sltp_reg_bits {
        u8         version[0x4];
        u8         local_port[0x8];
        u8         pnat[0x2];
-       u8         reserved_0[0x2];
+       u8         reserved_at_12[0x2];
        u8         lane[0x4];
-       u8         reserved_1[0x8];
+       u8         reserved_at_18[0x8];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_20[0x20];
 
-       u8         reserved_3[0x7];
+       u8         reserved_at_40[0x7];
        u8         polarity[0x1];
        u8         ob_tap0[0x8];
        u8         ob_tap1[0x8];
        u8         ob_tap2[0x8];
 
-       u8         reserved_4[0xc];
+       u8         reserved_at_60[0xc];
        u8         ob_preemp_mode[0x4];
        u8         ob_reg[0x8];
        u8         ob_bias[0x8];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_80[0x20];
 };
 
 struct mlx5_ifc_slrg_reg_bits {
@@ -6184,36 +6184,36 @@ struct mlx5_ifc_slrg_reg_bits {
        u8         version[0x4];
        u8         local_port[0x8];
        u8         pnat[0x2];
-       u8         reserved_0[0x2];
+       u8         reserved_at_12[0x2];
        u8         lane[0x4];
-       u8         reserved_1[0x8];
+       u8         reserved_at_18[0x8];
 
        u8         time_to_link_up[0x10];
-       u8         reserved_2[0xc];
+       u8         reserved_at_30[0xc];
        u8         grade_lane_speed[0x4];
 
        u8         grade_version[0x8];
        u8         grade[0x18];
 
-       u8         reserved_3[0x4];
+       u8         reserved_at_60[0x4];
        u8         height_grade_type[0x4];
        u8         height_grade[0x18];
 
        u8         height_dz[0x10];
        u8         height_dv[0x10];
 
-       u8         reserved_4[0x10];
+       u8         reserved_at_a0[0x10];
        u8         height_sigma[0x10];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_c0[0x20];
 
-       u8         reserved_6[0x4];
+       u8         reserved_at_e0[0x4];
        u8         phase_grade_type[0x4];
        u8         phase_grade[0x18];
 
-       u8         reserved_7[0x8];
+       u8         reserved_at_100[0x8];
        u8         phase_eo_pos[0x8];
-       u8         reserved_8[0x8];
+       u8         reserved_at_110[0x8];
        u8         phase_eo_neg[0x8];
 
        u8         ffe_set_tested[0x10];
@@ -6221,70 +6221,70 @@ struct mlx5_ifc_slrg_reg_bits {
 };
 
 struct mlx5_ifc_pvlc_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x1c];
+       u8         reserved_at_20[0x1c];
        u8         vl_hw_cap[0x4];
 
-       u8         reserved_3[0x1c];
+       u8         reserved_at_40[0x1c];
        u8         vl_admin[0x4];
 
-       u8         reserved_4[0x1c];
+       u8         reserved_at_60[0x1c];
        u8         vl_operational[0x4];
 };
 
 struct mlx5_ifc_pude_reg_bits {
        u8         swid[0x8];
        u8         local_port[0x8];
-       u8         reserved_0[0x4];
+       u8         reserved_at_10[0x4];
        u8         admin_status[0x4];
-       u8         reserved_1[0x4];
+       u8         reserved_at_18[0x4];
        u8         oper_status[0x4];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_20[0x60];
 };
 
 struct mlx5_ifc_ptys_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0xd];
+       u8         reserved_at_10[0xd];
        u8         proto_mask[0x3];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_20[0x40];
 
        u8         eth_proto_capability[0x20];
 
        u8         ib_link_width_capability[0x10];
        u8         ib_proto_capability[0x10];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_a0[0x20];
 
        u8         eth_proto_admin[0x20];
 
        u8         ib_link_width_admin[0x10];
        u8         ib_proto_admin[0x10];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_100[0x20];
 
        u8         eth_proto_oper[0x20];
 
        u8         ib_link_width_oper[0x10];
        u8         ib_proto_oper[0x10];
 
-       u8         reserved_5[0x20];
+       u8         reserved_at_160[0x20];
 
        u8         eth_proto_lp_advertise[0x20];
 
-       u8         reserved_6[0x60];
+       u8         reserved_at_1a0[0x60];
 };
 
 struct mlx5_ifc_ptas_reg_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
        u8         algorithm_options[0x10];
-       u8         reserved_1[0x4];
+       u8         reserved_at_30[0x4];
        u8         repetitions_mode[0x4];
        u8         num_of_repetitions[0x8];
 
@@ -6310,13 +6310,13 @@ struct mlx5_ifc_ptas_reg_bits {
        u8         ndeo_error_threshold[0x10];
 
        u8         mixer_offset_step_size[0x10];
-       u8         reserved_2[0x8];
+       u8         reserved_at_110[0x8];
        u8         mix90_phase_for_voltage_bath[0x8];
 
        u8         mixer_offset_start[0x10];
        u8         mixer_offset_end[0x10];
 
-       u8         reserved_3[0x15];
+       u8         reserved_at_140[0x15];
        u8         ber_test_time[0xb];
 };
 
@@ -6324,154 +6324,154 @@ struct mlx5_ifc_pspa_reg_bits {
        u8         swid[0x8];
        u8         local_port[0x8];
        u8         sub_port[0x8];
-       u8         reserved_0[0x8];
+       u8         reserved_at_18[0x8];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_20[0x20];
 };
 
 struct mlx5_ifc_pqdr_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x5];
+       u8         reserved_at_10[0x5];
        u8         prio[0x3];
-       u8         reserved_2[0x6];
+       u8         reserved_at_18[0x6];
        u8         mode[0x2];
 
-       u8         reserved_3[0x20];
+       u8         reserved_at_20[0x20];
 
-       u8         reserved_4[0x10];
+       u8         reserved_at_40[0x10];
        u8         min_threshold[0x10];
 
-       u8         reserved_5[0x10];
+       u8         reserved_at_60[0x10];
        u8         max_threshold[0x10];
 
-       u8         reserved_6[0x10];
+       u8         reserved_at_80[0x10];
        u8         mark_probability_denominator[0x10];
 
-       u8         reserved_7[0x60];
+       u8         reserved_at_a0[0x60];
 };
 
 struct mlx5_ifc_ppsc_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_20[0x60];
 
-       u8         reserved_3[0x1c];
+       u8         reserved_at_80[0x1c];
        u8         wrps_admin[0x4];
 
-       u8         reserved_4[0x1c];
+       u8         reserved_at_a0[0x1c];
        u8         wrps_status[0x4];
 
-       u8         reserved_5[0x8];
+       u8         reserved_at_c0[0x8];
        u8         up_threshold[0x8];
-       u8         reserved_6[0x8];
+       u8         reserved_at_d0[0x8];
        u8         down_threshold[0x8];
 
-       u8         reserved_7[0x20];
+       u8         reserved_at_e0[0x20];
 
-       u8         reserved_8[0x1c];
+       u8         reserved_at_100[0x1c];
        u8         srps_admin[0x4];
 
-       u8         reserved_9[0x1c];
+       u8         reserved_at_120[0x1c];
        u8         srps_status[0x4];
 
-       u8         reserved_10[0x40];
+       u8         reserved_at_140[0x40];
 };
 
 struct mlx5_ifc_pplr_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_20[0x8];
        u8         lb_cap[0x8];
-       u8         reserved_3[0x8];
+       u8         reserved_at_30[0x8];
        u8         lb_en[0x8];
 };
 
 struct mlx5_ifc_pplm_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_20[0x20];
 
        u8         port_profile_mode[0x8];
        u8         static_port_profile[0x8];
        u8         active_port_profile[0x8];
-       u8         reserved_3[0x8];
+       u8         reserved_at_58[0x8];
 
        u8         retransmission_active[0x8];
        u8         fec_mode_active[0x18];
 
-       u8         reserved_4[0x20];
+       u8         reserved_at_80[0x20];
 };
 
 struct mlx5_ifc_ppcnt_reg_bits {
        u8         swid[0x8];
        u8         local_port[0x8];
        u8         pnat[0x2];
-       u8         reserved_0[0x8];
+       u8         reserved_at_12[0x8];
        u8         grp[0x6];
 
        u8         clr[0x1];
-       u8         reserved_1[0x1c];
+       u8         reserved_at_21[0x1c];
        u8         prio_tc[0x3];
 
        union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits counter_set;
 };
 
 struct mlx5_ifc_ppad_reg_bits {
-       u8         reserved_0[0x3];
+       u8         reserved_at_0[0x3];
        u8         single_mac[0x1];
-       u8         reserved_1[0x4];
+       u8         reserved_at_4[0x4];
        u8         local_port[0x8];
        u8         mac_47_32[0x10];
 
        u8         mac_31_0[0x20];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_pmtu_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
        u8         max_mtu[0x10];
-       u8         reserved_2[0x10];
+       u8         reserved_at_30[0x10];
 
        u8         admin_mtu[0x10];
-       u8         reserved_3[0x10];
+       u8         reserved_at_50[0x10];
 
        u8         oper_mtu[0x10];
-       u8         reserved_4[0x10];
+       u8         reserved_at_70[0x10];
 };
 
 struct mlx5_ifc_pmpr_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         module[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0x18];
+       u8         reserved_at_20[0x18];
        u8         attenuation_5g[0x8];
 
-       u8         reserved_3[0x18];
+       u8         reserved_at_40[0x18];
        u8         attenuation_7g[0x8];
 
-       u8         reserved_4[0x18];
+       u8         reserved_at_60[0x18];
        u8         attenuation_12g[0x8];
 };
 
 struct mlx5_ifc_pmpe_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         module[0x8];
-       u8         reserved_1[0xc];
+       u8         reserved_at_10[0xc];
        u8         module_status[0x4];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_20[0x60];
 };
 
 struct mlx5_ifc_pmpc_reg_bits {
@@ -6479,20 +6479,20 @@ struct mlx5_ifc_pmpc_reg_bits {
 };
 
 struct mlx5_ifc_pmlpn_reg_bits {
-       u8         reserved_0[0x4];
+       u8         reserved_at_0[0x4];
        u8         mlpn_status[0x4];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
        u8         e[0x1];
-       u8         reserved_2[0x1f];
+       u8         reserved_at_21[0x1f];
 };
 
 struct mlx5_ifc_pmlp_reg_bits {
        u8         rxtx[0x1];
-       u8         reserved_0[0x7];
+       u8         reserved_at_1[0x7];
        u8         local_port[0x8];
-       u8         reserved_1[0x8];
+       u8         reserved_at_10[0x8];
        u8         width[0x8];
 
        u8         lane0_module_mapping[0x20];
@@ -6503,36 +6503,36 @@ struct mlx5_ifc_pmlp_reg_bits {
 
        u8         lane3_module_mapping[0x20];
 
-       u8         reserved_2[0x160];
+       u8         reserved_at_a0[0x160];
 };
 
 struct mlx5_ifc_pmaos_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         module[0x8];
-       u8         reserved_1[0x4];
+       u8         reserved_at_10[0x4];
        u8         admin_status[0x4];
-       u8         reserved_2[0x4];
+       u8         reserved_at_18[0x4];
        u8         oper_status[0x4];
 
        u8         ase[0x1];
        u8         ee[0x1];
-       u8         reserved_3[0x1c];
+       u8         reserved_at_22[0x1c];
        u8         e[0x2];
 
-       u8         reserved_4[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_plpc_reg_bits {
-       u8         reserved_0[0x4];
+       u8         reserved_at_0[0x4];
        u8         profile_id[0xc];
-       u8         reserved_1[0x4];
+       u8         reserved_at_10[0x4];
        u8         proto_mask[0x4];
-       u8         reserved_2[0x8];
+       u8         reserved_at_18[0x8];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_20[0x10];
        u8         lane_speed[0x10];
 
-       u8         reserved_4[0x17];
+       u8         reserved_at_40[0x17];
        u8         lpbf[0x1];
        u8         fec_mode_policy[0x8];
 
@@ -6545,44 +6545,44 @@ struct mlx5_ifc_plpc_reg_bits {
        u8         retransmission_request_admin[0x8];
        u8         fec_mode_request_admin[0x18];
 
-       u8         reserved_5[0x80];
+       u8         reserved_at_c0[0x80];
 };
 
 struct mlx5_ifc_plib_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x8];
+       u8         reserved_at_10[0x8];
        u8         ib_port[0x8];
 
-       u8         reserved_2[0x60];
+       u8         reserved_at_20[0x60];
 };
 
 struct mlx5_ifc_plbf_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0xd];
+       u8         reserved_at_10[0xd];
        u8         lbf_mode[0x3];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_20[0x20];
 };
 
 struct mlx5_ifc_pipg_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
        u8         dic[0x1];
-       u8         reserved_2[0x19];
+       u8         reserved_at_21[0x19];
        u8         ipg[0x4];
-       u8         reserved_3[0x2];
+       u8         reserved_at_3e[0x2];
 };
 
 struct mlx5_ifc_pifr_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0xe0];
+       u8         reserved_at_20[0xe0];
 
        u8         port_filter[8][0x20];
 
@@ -6590,36 +6590,36 @@ struct mlx5_ifc_pifr_reg_bits {
 };
 
 struct mlx5_ifc_pfcc_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
        u8         ppan[0x4];
-       u8         reserved_2[0x4];
+       u8         reserved_at_24[0x4];
        u8         prio_mask_tx[0x8];
-       u8         reserved_3[0x8];
+       u8         reserved_at_30[0x8];
        u8         prio_mask_rx[0x8];
 
        u8         pptx[0x1];
        u8         aptx[0x1];
-       u8         reserved_4[0x6];
+       u8         reserved_at_42[0x6];
        u8         pfctx[0x8];
-       u8         reserved_5[0x10];
+       u8         reserved_at_50[0x10];
 
        u8         pprx[0x1];
        u8         aprx[0x1];
-       u8         reserved_6[0x6];
+       u8         reserved_at_62[0x6];
        u8         pfcrx[0x8];
-       u8         reserved_7[0x10];
+       u8         reserved_at_70[0x10];
 
-       u8         reserved_8[0x80];
+       u8         reserved_at_80[0x80];
 };
 
 struct mlx5_ifc_pelc_reg_bits {
        u8         op[0x4];
-       u8         reserved_0[0x4];
+       u8         reserved_at_4[0x4];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
        u8         op_admin[0x8];
        u8         op_capability[0x8];
@@ -6634,28 +6634,28 @@ struct mlx5_ifc_pelc_reg_bits {
 
        u8         active[0x40];
 
-       u8         reserved_2[0x80];
+       u8         reserved_at_140[0x80];
 };
 
 struct mlx5_ifc_peir_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_2[0xc];
+       u8         reserved_at_20[0xc];
        u8         error_count[0x4];
-       u8         reserved_3[0x10];
+       u8         reserved_at_30[0x10];
 
-       u8         reserved_4[0xc];
+       u8         reserved_at_40[0xc];
        u8         lane[0x4];
-       u8         reserved_5[0x8];
+       u8         reserved_at_50[0x8];
        u8         error_type[0x8];
 };
 
 struct mlx5_ifc_pcap_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         local_port[0x8];
-       u8         reserved_1[0x10];
+       u8         reserved_at_10[0x10];
 
        u8         port_capability_mask[4][0x20];
 };
@@ -6663,46 +6663,46 @@ struct mlx5_ifc_pcap_reg_bits {
 struct mlx5_ifc_paos_reg_bits {
        u8         swid[0x8];
        u8         local_port[0x8];
-       u8         reserved_0[0x4];
+       u8         reserved_at_10[0x4];
        u8         admin_status[0x4];
-       u8         reserved_1[0x4];
+       u8         reserved_at_18[0x4];
        u8         oper_status[0x4];
 
        u8         ase[0x1];
        u8         ee[0x1];
-       u8         reserved_2[0x1c];
+       u8         reserved_at_22[0x1c];
        u8         e[0x2];
 
-       u8         reserved_3[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_pamp_reg_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         opamp_group[0x8];
-       u8         reserved_1[0xc];
+       u8         reserved_at_10[0xc];
        u8         opamp_group_type[0x4];
 
        u8         start_index[0x10];
-       u8         reserved_2[0x4];
+       u8         reserved_at_30[0x4];
        u8         num_of_indices[0xc];
 
        u8         index_data[18][0x10];
 };
 
 struct mlx5_ifc_lane_2_module_mapping_bits {
-       u8         reserved_0[0x6];
+       u8         reserved_at_0[0x6];
        u8         rx_lane[0x2];
-       u8         reserved_1[0x6];
+       u8         reserved_at_8[0x6];
        u8         tx_lane[0x2];
-       u8         reserved_2[0x8];
+       u8         reserved_at_10[0x8];
        u8         module[0x8];
 };
 
 struct mlx5_ifc_bufferx_reg_bits {
-       u8         reserved_0[0x6];
+       u8         reserved_at_0[0x6];
        u8         lossy[0x1];
        u8         epsb[0x1];
-       u8         reserved_1[0xc];
+       u8         reserved_at_8[0xc];
        u8         size[0xc];
 
        u8         xoff_threshold[0x10];
@@ -6714,21 +6714,21 @@ struct mlx5_ifc_set_node_in_bits {
 };
 
 struct mlx5_ifc_register_power_settings_bits {
-       u8         reserved_0[0x18];
+       u8         reserved_at_0[0x18];
        u8         power_settings_level[0x8];
 
-       u8         reserved_1[0x60];
+       u8         reserved_at_20[0x60];
 };
 
 struct mlx5_ifc_register_host_endianness_bits {
        u8         he[0x1];
-       u8         reserved_0[0x1f];
+       u8         reserved_at_1[0x1f];
 
-       u8         reserved_1[0x60];
+       u8         reserved_at_20[0x60];
 };
 
 struct mlx5_ifc_umr_pointer_desc_argument_bits {
-       u8         reserved_0[0x20];
+       u8         reserved_at_0[0x20];
 
        u8         mkey[0x20];
 
@@ -6741,7 +6741,7 @@ struct mlx5_ifc_ud_adrs_vector_bits {
        u8         dc_key[0x40];
 
        u8         ext[0x1];
-       u8         reserved_0[0x7];
+       u8         reserved_at_41[0x7];
        u8         destination_qp_dct[0x18];
 
        u8         static_rate[0x4];
@@ -6750,7 +6750,7 @@ struct mlx5_ifc_ud_adrs_vector_bits {
        u8         mlid[0x7];
        u8         rlid_udp_sport[0x10];
 
-       u8         reserved_1[0x20];
+       u8         reserved_at_80[0x20];
 
        u8         rmac_47_16[0x20];
 
@@ -6758,9 +6758,9 @@ struct mlx5_ifc_ud_adrs_vector_bits {
        u8         tclass[0x8];
        u8         hop_limit[0x8];
 
-       u8         reserved_2[0x1];
+       u8         reserved_at_e0[0x1];
        u8         grh[0x1];
-       u8         reserved_3[0x2];
+       u8         reserved_at_e2[0x2];
        u8         src_addr_index[0x8];
        u8         flow_label[0x14];
 
@@ -6768,27 +6768,27 @@ struct mlx5_ifc_ud_adrs_vector_bits {
 };
 
 struct mlx5_ifc_pages_req_event_bits {
-       u8         reserved_0[0x10];
+       u8         reserved_at_0[0x10];
        u8         function_id[0x10];
 
        u8         num_pages[0x20];
 
-       u8         reserved_1[0xa0];
+       u8         reserved_at_40[0xa0];
 };
 
 struct mlx5_ifc_eqe_bits {
-       u8         reserved_0[0x8];
+       u8         reserved_at_0[0x8];
        u8         event_type[0x8];
-       u8         reserved_1[0x8];
+       u8         reserved_at_10[0x8];
        u8         event_sub_type[0x8];
 
-       u8         reserved_2[0xe0];
+       u8         reserved_at_20[0xe0];
 
        union mlx5_ifc_event_auto_bits event_data;
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_1e0[0x10];
        u8         signature[0x8];
-       u8         reserved_4[0x7];
+       u8         reserved_at_1f8[0x7];
        u8         owner[0x1];
 };
 
@@ -6798,14 +6798,14 @@ enum {
 
 struct mlx5_ifc_cmd_queue_entry_bits {
        u8         type[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         input_length[0x20];
 
        u8         input_mailbox_pointer_63_32[0x20];
 
        u8         input_mailbox_pointer_31_9[0x17];
-       u8         reserved_1[0x9];
+       u8         reserved_at_77[0x9];
 
        u8         command_input_inline_data[16][0x8];
 
@@ -6814,20 +6814,20 @@ struct mlx5_ifc_cmd_queue_entry_bits {
        u8         output_mailbox_pointer_63_32[0x20];
 
        u8         output_mailbox_pointer_31_9[0x17];
-       u8         reserved_2[0x9];
+       u8         reserved_at_1b7[0x9];
 
        u8         output_length[0x20];
 
        u8         token[0x8];
        u8         signature[0x8];
-       u8         reserved_3[0x8];
+       u8         reserved_at_1f0[0x8];
        u8         status[0x7];
        u8         ownership[0x1];
 };
 
 struct mlx5_ifc_cmd_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
@@ -6836,9 +6836,9 @@ struct mlx5_ifc_cmd_out_bits {
 
 struct mlx5_ifc_cmd_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
        u8         command[0][0x20];
@@ -6847,16 +6847,16 @@ struct mlx5_ifc_cmd_in_bits {
 struct mlx5_ifc_cmd_if_box_bits {
        u8         mailbox_data[512][0x8];
 
-       u8         reserved_0[0x180];
+       u8         reserved_at_1000[0x180];
 
        u8         next_pointer_63_32[0x20];
 
        u8         next_pointer_31_10[0x16];
-       u8         reserved_1[0xa];
+       u8         reserved_at_11b6[0xa];
 
        u8         block_number[0x20];
 
-       u8         reserved_2[0x8];
+       u8         reserved_at_11e0[0x8];
        u8         token[0x8];
        u8         ctrl_signature[0x8];
        u8         signature[0x8];
@@ -6866,7 +6866,7 @@ struct mlx5_ifc_mtt_bits {
        u8         ptag_63_32[0x20];
 
        u8         ptag_31_8[0x18];
-       u8         reserved_0[0x6];
+       u8         reserved_at_38[0x6];
        u8         wr_en[0x1];
        u8         rd_en[0x1];
 };
@@ -6904,38 +6904,38 @@ struct mlx5_ifc_initial_seg_bits {
        u8         cmd_interface_rev[0x10];
        u8         fw_rev_subminor[0x10];
 
-       u8         reserved_0[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         cmdq_phy_addr_63_32[0x20];
 
        u8         cmdq_phy_addr_31_12[0x14];
-       u8         reserved_1[0x2];
+       u8         reserved_at_b4[0x2];
        u8         nic_interface[0x2];
        u8         log_cmdq_size[0x4];
        u8         log_cmdq_stride[0x4];
 
        u8         command_doorbell_vector[0x20];
 
-       u8         reserved_2[0xf00];
+       u8         reserved_at_e0[0xf00];
 
        u8         initializing[0x1];
-       u8         reserved_3[0x4];
+       u8         reserved_at_fe1[0x4];
        u8         nic_interface_supported[0x3];
-       u8         reserved_4[0x18];
+       u8         reserved_at_fe8[0x18];
 
        struct mlx5_ifc_health_buffer_bits health_buffer;
 
        u8         no_dram_nic_offset[0x20];
 
-       u8         reserved_5[0x6e40];
+       u8         reserved_at_1220[0x6e40];
 
-       u8         reserved_6[0x1f];
+       u8         reserved_at_8060[0x1f];
        u8         clear_int[0x1];
 
        u8         health_syndrome[0x8];
        u8         health_counter[0x18];
 
-       u8         reserved_7[0x17fc0];
+       u8         reserved_at_80a0[0x17fc0];
 };
 
 union mlx5_ifc_ports_control_registers_document_bits {
@@ -6980,44 +6980,44 @@ union mlx5_ifc_ports_control_registers_document_bits {
        struct mlx5_ifc_pvlc_reg_bits pvlc_reg;
        struct mlx5_ifc_slrg_reg_bits slrg_reg;
        struct mlx5_ifc_sltp_reg_bits sltp_reg;
-       u8         reserved_0[0x60e0];
+       u8         reserved_at_0[0x60e0];
 };
 
 union mlx5_ifc_debug_enhancements_document_bits {
        struct mlx5_ifc_health_buffer_bits health_buffer;
-       u8         reserved_0[0x200];
+       u8         reserved_at_0[0x200];
 };
 
 union mlx5_ifc_uplink_pci_interface_document_bits {
        struct mlx5_ifc_initial_seg_bits initial_seg;
-       u8         reserved_0[0x20060];
+       u8         reserved_at_0[0x20060];
 };
 
 struct mlx5_ifc_set_flow_table_root_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_set_flow_table_root_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x40];
+       u8         reserved_at_40[0x40];
 
        u8         table_type[0x8];
-       u8         reserved_3[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_4[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_5[0x140];
+       u8         reserved_at_c0[0x140];
 };
 
 enum {
@@ -7026,39 +7026,39 @@ enum {
 
 struct mlx5_ifc_modify_flow_table_out_bits {
        u8         status[0x8];
-       u8         reserved_0[0x18];
+       u8         reserved_at_8[0x18];
 
        u8         syndrome[0x20];
 
-       u8         reserved_1[0x40];
+       u8         reserved_at_40[0x40];
 };
 
 struct mlx5_ifc_modify_flow_table_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         reserved_at_10[0x10];
 
-       u8         reserved_1[0x10];
+       u8         reserved_at_20[0x10];
        u8         op_mod[0x10];
 
-       u8         reserved_2[0x20];
+       u8         reserved_at_40[0x20];
 
-       u8         reserved_3[0x10];
+       u8         reserved_at_60[0x10];
        u8         modify_field_select[0x10];
 
        u8         table_type[0x8];
-       u8         reserved_4[0x18];
+       u8         reserved_at_88[0x18];
 
-       u8         reserved_5[0x8];
+       u8         reserved_at_a0[0x8];
        u8         table_id[0x18];
 
-       u8         reserved_6[0x4];
+       u8         reserved_at_c0[0x4];
        u8         table_miss_mode[0x4];
-       u8         reserved_7[0x18];
+       u8         reserved_at_c8[0x18];
 
-       u8         reserved_8[0x8];
+       u8         reserved_at_e0[0x8];
        u8         table_miss_id[0x18];
 
-       u8         reserved_9[0x100];
+       u8         reserved_at_100[0x100];
 };
 
 #endif /* MLX5_IFC_H */
index 4560d8f1545d2cec7e6da19da460fff26151c105..2bb0c308570672e7105b14f85a4215b0f9500207 100644 (file)
@@ -324,6 +324,12 @@ struct module_layout {
 #define __module_layout_align
 #endif
 
+struct mod_kallsyms {
+       Elf_Sym *symtab;
+       unsigned int num_symtab;
+       char *strtab;
+};
+
 struct module {
        enum module_state state;
 
@@ -405,15 +411,10 @@ struct module {
 #endif
 
 #ifdef CONFIG_KALLSYMS
-       /*
-        * We keep the symbol and string tables for kallsyms.
-        * The core_* fields below are temporary, loader-only (they
-        * could really be discarded after module init).
-        */
-       Elf_Sym *symtab, *core_symtab;
-       unsigned int num_symtab, core_num_syms;
-       char *strtab, *core_strtab;
-
+       /* Protected by RCU and/or module_mutex: use rcu_dereference() */
+       struct mod_kallsyms *kallsyms;
+       struct mod_kallsyms core_kallsyms;
+       
        /* Section attributes */
        struct module_sect_attrs *sect_attrs;
 
index 289c2314d76668b8357728382bb33d6828617458..5440b7b705eb1756f4d095e6eab3518893245568 100644 (file)
@@ -3718,7 +3718,7 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
 void *netdev_lower_get_next(struct net_device *dev,
                                struct list_head **iter);
 #define netdev_for_each_lower_dev(dev, ldev, iter) \
-       for (iter = &(dev)->adj_list.lower, \
+       for (iter = (dev)->adj_list.lower.next, \
             ldev = netdev_lower_get_next(dev, &(iter)); \
             ldev; \
             ldev = netdev_lower_get_next(dev, &(iter)))
index 48e0320cd6432463b86cc3d7684d5ecd4ab48651..67300f8e5f2f0248e8651cbe17e5c14e1110ca2c 100644 (file)
@@ -550,9 +550,7 @@ extern int  nfs_readpage_async(struct nfs_open_context *, struct inode *,
 
 static inline loff_t nfs_size_to_loff_t(__u64 size)
 {
-       if (size > (__u64) OFFSET_MAX - 1)
-               return OFFSET_MAX - 1;
-       return (loff_t) size;
+       return min_t(u64, size, OFFSET_MAX);
 }
 
 static inline ino_t
index 791098a08a8765bea64b4137baaf12ef4af62ac8..d320906cf13e5d7d3d443a6249992202eb171f59 100644 (file)
@@ -275,6 +275,7 @@ struct nfs4_layoutcommit_args {
        size_t layoutupdate_len;
        struct page *layoutupdate_page;
        struct page **layoutupdate_pages;
+       __be32 *start_p;
 };
 
 struct nfs4_layoutcommit_res {
index 27df4a6585daedcc6a74865bf048cfd06a0593ba..27716254dcc54bd6d6ca5e864f58e92fd94ea305 100644 (file)
@@ -988,23 +988,6 @@ static inline int pci_is_managed(struct pci_dev *pdev)
        return pdev->is_managed;
 }
 
-static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq)
-{
-       pdev->irq = irq;
-       pdev->irq_managed = 1;
-}
-
-static inline void pci_reset_managed_irq(struct pci_dev *pdev)
-{
-       pdev->irq = 0;
-       pdev->irq_managed = 0;
-}
-
-static inline bool pci_has_managed_irq(struct pci_dev *pdev)
-{
-       return pdev->irq_managed && pdev->irq > 0;
-}
-
 void pci_disable_device(struct pci_dev *dev);
 
 extern unsigned int pcibios_max_latency;
index b35a61a481fa0460b3b32591e6dd52f2fa9077e7..f5c5a3fa2c8101cc37ea917d29dec30713ec0699 100644 (file)
@@ -397,6 +397,7 @@ struct pmu {
  * enum perf_event_active_state - the states of a event
  */
 enum perf_event_active_state {
+       PERF_EVENT_STATE_DEAD           = -4,
        PERF_EVENT_STATE_EXIT           = -3,
        PERF_EVENT_STATE_ERROR          = -2,
        PERF_EVENT_STATE_OFF            = -1,
@@ -905,7 +906,7 @@ perf_sw_event_sched(u32 event_id, u64 nr, u64 addr)
        }
 }
 
-extern struct static_key_deferred perf_sched_events;
+extern struct static_key_false perf_sched_events;
 
 static __always_inline bool
 perf_sw_migrate_enabled(void)
@@ -924,7 +925,7 @@ static inline void perf_event_task_migrate(struct task_struct *task)
 static inline void perf_event_task_sched_in(struct task_struct *prev,
                                            struct task_struct *task)
 {
-       if (static_key_false(&perf_sched_events.key))
+       if (static_branch_unlikely(&perf_sched_events))
                __perf_event_task_sched_in(prev, task);
 
        if (perf_sw_migrate_enabled() && task->sched_migrated) {
@@ -941,7 +942,7 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
 {
        perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0);
 
-       if (static_key_false(&perf_sched_events.key))
+       if (static_branch_unlikely(&perf_sched_events))
                __perf_event_task_sched_out(prev, next);
 }
 
index 2d8e49711b6392a591ee352b12c162096d4c89f6..1132953235c0708bd87e1b9eea777bb705f54cb3 100644 (file)
@@ -10,7 +10,7 @@
  * backing is indicated by flags in the high bits of the value.
  */
 typedef struct {
-       unsigned long val;
+       u64 val;
 } pfn_t;
 #endif
 
index 37448ab5fb5c2eddc80b97125ee80ecff4bc1b58..94994810c7c086e8410f3333d919ef5256595ad5 100644 (file)
@@ -9,14 +9,13 @@
  * PFN_DEV - pfn is not covered by system memmap by default
  * PFN_MAP - pfn has a dynamic page mapping established by a device driver
  */
-#define PFN_FLAGS_MASK (((unsigned long) ~PAGE_MASK) \
-               << (BITS_PER_LONG - PAGE_SHIFT))
-#define PFN_SG_CHAIN (1UL << (BITS_PER_LONG - 1))
-#define PFN_SG_LAST (1UL << (BITS_PER_LONG - 2))
-#define PFN_DEV (1UL << (BITS_PER_LONG - 3))
-#define PFN_MAP (1UL << (BITS_PER_LONG - 4))
-
-static inline pfn_t __pfn_to_pfn_t(unsigned long pfn, unsigned long flags)
+#define PFN_FLAGS_MASK (((u64) ~PAGE_MASK) << (BITS_PER_LONG_LONG - PAGE_SHIFT))
+#define PFN_SG_CHAIN (1ULL << (BITS_PER_LONG_LONG - 1))
+#define PFN_SG_LAST (1ULL << (BITS_PER_LONG_LONG - 2))
+#define PFN_DEV (1ULL << (BITS_PER_LONG_LONG - 3))
+#define PFN_MAP (1ULL << (BITS_PER_LONG_LONG - 4))
+
+static inline pfn_t __pfn_to_pfn_t(unsigned long pfn, u64 flags)
 {
        pfn_t pfn_t = { .val = pfn | (flags & PFN_FLAGS_MASK), };
 
@@ -29,7 +28,7 @@ static inline pfn_t pfn_to_pfn_t(unsigned long pfn)
        return __pfn_to_pfn_t(pfn, 0);
 }
 
-extern pfn_t phys_to_pfn_t(phys_addr_t addr, unsigned long flags);
+extern pfn_t phys_to_pfn_t(phys_addr_t addr, u64 flags);
 
 static inline bool pfn_t_has_page(pfn_t pfn)
 {
@@ -87,7 +86,7 @@ static inline pmd_t pfn_t_pmd(pfn_t pfn, pgprot_t pgprot)
 #ifdef __HAVE_ARCH_PTE_DEVMAP
 static inline bool pfn_t_devmap(pfn_t pfn)
 {
-       const unsigned long flags = PFN_DEV|PFN_MAP;
+       const u64 flags = PFN_DEV|PFN_MAP;
 
        return (pfn.val & flags) == flags;
 }
index a81766cae230ebf37998edfff5922e8054817232..9db1b905df2487e8d014e1c7d6592f29152059d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961/ADAU1781/ADAU1781 codecs
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781 codecs
  *
  * Copyright 2011-2014 Analog Devices Inc.
  * Author: Lars-Peter Clausen <lars@metafoo.de>
index 998d8f1c3c9172037ef185963f415dbb0fad999f..b50c0492629dbfa9f902f214ad714f1c2df372bc 100644 (file)
@@ -49,6 +49,7 @@ struct bq27xxx_reg_cache {
 
 struct bq27xxx_device_info {
        struct device *dev;
+       int id;
        enum bq27xxx_chip chip;
        const char *name;
        struct bq27xxx_access_methods bus;
index a75840c1aa71414acc43468da6cc8f83ec06c1b8..9c29122037f95283cc02b8af995975e80e059abd 100644 (file)
@@ -34,6 +34,7 @@ extern const struct file_operations random_fops, urandom_fops;
 #endif
 
 unsigned int get_random_int(void);
+unsigned long get_random_long(void);
 unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
 u32 prandom_u32(void);
index 11f935c1a090419d6cda938aa925bfa79de3616b..4ce9ff7086f4897a67f6037d88df21012cf28413 100644 (file)
@@ -299,6 +299,7 @@ struct sk_buff;
 #else
 #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1)
 #endif
+extern int sysctl_max_skb_frags;
 
 typedef struct skb_frag_struct skb_frag_t;
 
index 343c13ac4f71f41f370b3bd51c8cd38c9ea75c2f..35cb9264e0d50bb8b8cce8f569d950de2d6694b2 100644 (file)
@@ -44,6 +44,7 @@
 
 #define KNAV_DMA_NUM_EPIB_WORDS                        4
 #define KNAV_DMA_NUM_PS_WORDS                  16
+#define KNAV_DMA_NUM_SW_DATA_WORDS             4
 #define KNAV_DMA_FDQ_PER_CHAN                  4
 
 /* Tx channel scheduling priority */
@@ -142,6 +143,7 @@ struct knav_dma_cfg {
  * @orig_buff:                 buff pointer since 'buff' can be overwritten
  * @epib:                      Extended packet info block
  * @psdata:                    Protocol specific
+ * @sw_data:                   Software private data not touched by h/w
  */
 struct knav_dma_desc {
        __le32  desc_info;
@@ -154,7 +156,7 @@ struct knav_dma_desc {
        __le32  orig_buff;
        __le32  epib[KNAV_DMA_NUM_EPIB_WORDS];
        __le32  psdata[KNAV_DMA_NUM_PS_WORDS];
-       __le32  pad[4];
+       u32     sw_data[KNAV_DMA_NUM_SW_DATA_WORDS];
 } ____cacheline_aligned;
 
 #if IS_ENABLED(CONFIG_KEYSTONE_NAVIGATOR_DMA)
index 429fdfc3baf59e018d0e198062f894642af8a5bc..925730bc9fc1bb4914410779bdf5ea469ed41c18 100644 (file)
@@ -568,6 +568,8 @@ enum {
        FILTER_DYN_STRING,
        FILTER_PTR_STRING,
        FILTER_TRACE_FN,
+       FILTER_COMM,
+       FILTER_CPU,
 };
 
 extern int trace_event_raw_init(struct trace_event_call *call);
index acd522a91539155db94143d5da4e4848a44a437e..acfdbf353a0b5bc7cfeb6ae58fa7e6a6acfa16ba 100644 (file)
  * See the file COPYING for more details.
  */
 
+#include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/types.h>
+#include <linux/cpumask.h>
 #include <linux/rcupdate.h>
 #include <linux/tracepoint-defs.h>
 
@@ -132,6 +134,9 @@ extern void syscall_unregfunc(void);
                void *it_func;                                          \
                void *__data;                                           \
                                                                        \
+               if (!cpu_online(raw_smp_processor_id()))                \
+                       return;                                         \
+                                                                       \
                if (!(cond))                                            \
                        return;                                         \
                prercu;                                                 \
index cbb20afdbc01cc4a600574446d5b19c33a0d90c1..bb679b48f408217a422d0cd427ede3e05e2e67bd 100644 (file)
@@ -11,4 +11,8 @@ unsigned long ucs2_strlen(const ucs2_char_t *s);
 unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
 int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
 
+unsigned long ucs2_utf8size(const ucs2_char_t *src);
+unsigned long ucs2_as_utf8(u8 *dest, const ucs2_char_t *src,
+                          unsigned long maxlength);
+
 #endif /* _LINUX_UCS2_STRING_H_ */
index 0e32bc71245ef46b90aa21112e4d2bef42cc5950..ca73c503b92a758ad5ce9b6d022c53c0758951c5 100644 (file)
@@ -311,6 +311,7 @@ enum {
 
        __WQ_DRAINING           = 1 << 16, /* internal: workqueue is draining */
        __WQ_ORDERED            = 1 << 17, /* internal: workqueue is ordered */
+       __WQ_LEGACY             = 1 << 18, /* internal: create*_workqueue() */
 
        WQ_MAX_ACTIVE           = 512,    /* I like 512, better ideas? */
        WQ_MAX_UNBOUND_PER_CPU  = 4,      /* 4 * #cpus for unbound wq */
@@ -411,12 +412,12 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
        alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1, ##args)
 
 #define create_workqueue(name)                                         \
-       alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, (name))
+       alloc_workqueue("%s", __WQ_LEGACY | WQ_MEM_RECLAIM, 1, (name))
 #define create_freezable_workqueue(name)                               \
-       alloc_workqueue("%s", WQ_FREEZABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, \
-                       1, (name))
+       alloc_workqueue("%s", __WQ_LEGACY | WQ_FREEZABLE | WQ_UNBOUND | \
+                       WQ_MEM_RECLAIM, 1, (name))
 #define create_singlethread_workqueue(name)                            \
-       alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name)
+       alloc_ordered_workqueue("%s", __WQ_LEGACY | WQ_MEM_RECLAIM, name)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
index b333c945e57117aa3d80f6ec2df47f6513c82260..d0b5ca5d4e080346e8a657c6c6aee540e47776e7 100644 (file)
@@ -198,6 +198,7 @@ void wbc_attach_and_unlock_inode(struct writeback_control *wbc,
 void wbc_detach_inode(struct writeback_control *wbc);
 void wbc_account_io(struct writeback_control *wbc, struct page *page,
                    size_t bytes);
+void cgroup_writeback_umount(void);
 
 /**
  * inode_attach_wb - associate an inode with its wb
@@ -301,6 +302,10 @@ static inline void wbc_account_io(struct writeback_control *wbc,
 {
 }
 
+static inline void cgroup_writeback_umount(void)
+{
+}
+
 #endif /* CONFIG_CGROUP_WRITEBACK */
 
 /*
index 2a91a0561a478393ca9e9d2f1993467cc4c5c9cb..9b4c418bebd84ae0a7debfbcc697ee92b136ec99 100644 (file)
@@ -6,8 +6,8 @@
 #include <linux/mutex.h>
 #include <net/sock.h>
 
-void unix_inflight(struct file *fp);
-void unix_notinflight(struct file *fp);
+void unix_inflight(struct user_struct *user, struct file *fp);
+void unix_notinflight(struct user_struct *user, struct file *fp);
 void unix_gc(void);
 void wait_for_unix_gc(void);
 struct sock *unix_get_socket(struct file *filp);
index 481fe1c9044cfd8b49585139e24df16b0716debf..49dcad4fe99e0ad5de491ef0e0675a3b516aabca 100644 (file)
@@ -270,8 +270,9 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
                                            struct sock *newsk,
                                            const struct request_sock *req);
 
-void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req,
-                             struct sock *child);
+struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
+                                     struct request_sock *req,
+                                     struct sock *child);
 void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
                                   unsigned long timeout);
 struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child,
index 7029527725ddbb80f7b78e66565b69ad8aad5806..4079fc18ffe4643522178b394ed6d1b54d5a6093 100644 (file)
@@ -61,6 +61,7 @@ struct fib_nh_exception {
        struct rtable __rcu             *fnhe_rth_input;
        struct rtable __rcu             *fnhe_rth_output;
        unsigned long                   fnhe_stamp;
+       struct rcu_head                 rcu;
 };
 
 struct fnhe_hash_bucket {
index 6db96ea0144f0445c4e52c51cddcc3d25d60ccdd..dda9abf6b89c14afddf71562c763bdd6bb7d85c3 100644 (file)
@@ -230,6 +230,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
 int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
                    u8 *protocol, struct flowi4 *fl4);
+int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
 int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
 
 struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
index 262532d111f51e3a91a06af785b4721e8fab9d56..59fa93c01d2a16a129298498f1d56556b895acd9 100644 (file)
@@ -21,6 +21,7 @@ struct scm_creds {
 struct scm_fp_list {
        short                   count;
        short                   max;
+       struct user_struct      *user;
        struct file             *fp[SCM_MAX_FD];
 };
 
index f6f8f032c73e81326790239cf021d2e50414ce1b..ae6468f5c9f373d63d987fb114deba1064bc16d5 100644 (file)
@@ -447,7 +447,7 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
 
 void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
 void tcp_v4_mtu_reduced(struct sock *sk);
-void tcp_req_err(struct sock *sk, u32 seq);
+void tcp_req_err(struct sock *sk, u32 seq, bool abort);
 int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
 struct sock *tcp_create_openreq_child(const struct sock *sk,
                                      struct request_sock *req,
index e2b712c90d3f22d4bcbb75ded3a296304d23d7c6..c21c38ce74501dbdac327e9cac8b0b6d051a42b0 100644 (file)
@@ -343,7 +343,7 @@ void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
 void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
 
 void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
-void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
+int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
                                    void (*ack)(struct hdac_bus *,
                                                struct hdac_stream *));
 
index b0be09279943fc1a911a6071507ebdd79eed2912..af1fb37c6b265cf20de58dee1e0d7490669a9bf1 100644 (file)
@@ -1093,6 +1093,8 @@ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
 unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
 unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
                                         unsigned int rates_b);
+unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min,
+                                       unsigned int rate_max);
 
 /**
  * snd_pcm_set_runtime_buffer - Set the PCM runtime buffer
index 56cf8e485ef22101ac22b1120704664bf599eaef..28ee5c2e6bcd7b08abeda34669cc2da17f4dcf9a 100644 (file)
@@ -94,5 +94,8 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
        sense_reason_t (*exec_cmd)(struct se_cmd *cmd));
 
 bool target_sense_desc_format(struct se_device *dev);
+sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
+bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
+                                      struct request_queue *q, int block_size);
 
 #endif /* TARGET_CORE_BACKEND_H */
index 5d82816cc4e3dbb34068748d95dd86b3bbb5a537..e8c8c08bf575f4de6436d8c090b15f77b6717f2a 100644 (file)
@@ -140,6 +140,8 @@ enum se_cmd_flags_table {
        SCF_COMPARE_AND_WRITE           = 0x00080000,
        SCF_COMPARE_AND_WRITE_POST      = 0x00100000,
        SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000,
+       SCF_ACK_KREF                    = 0x00400000,
+       SCF_USE_CPUID                   = 0x00800000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -187,6 +189,7 @@ enum target_sc_flags_table {
        TARGET_SCF_BIDI_OP              = 0x01,
        TARGET_SCF_ACK_KREF             = 0x02,
        TARGET_SCF_UNKNOWN_SIZE         = 0x04,
+       TARGET_SCF_USE_CPUID    = 0x08,
 };
 
 /* fabric independent task management function values */
@@ -490,8 +493,9 @@ struct se_cmd {
 #define CMD_T_SENT             (1 << 4)
 #define CMD_T_STOP             (1 << 5)
 #define CMD_T_DEV_ACTIVE       (1 << 7)
-#define CMD_T_REQUEST_STOP     (1 << 8)
 #define CMD_T_BUSY             (1 << 9)
+#define CMD_T_TAS              (1 << 10)
+#define CMD_T_FABRIC_STOP      (1 << 11)
        spinlock_t              t_state_lock;
        struct kref             cmd_kref;
        struct completion       t_transport_stop_comp;
@@ -511,9 +515,6 @@ struct se_cmd {
 
        struct list_head        state_list;
 
-       /* old task stop completion, consider merging with some of the above */
-       struct completion       task_stop_comp;
-
        /* backend private data */
        void                    *priv;
 
index 317a1ed2f4acc7745c3e02955c60e8c1dc8eb7c3..9130dd5a184a25e7d6c6cf0b633d7d5c0c4fc0f6 100644 (file)
@@ -231,13 +231,13 @@ TRACE_EVENT(snd_soc_jack_report,
        TP_ARGS(jack, mask, val),
 
        TP_STRUCT__entry(
-               __string(       name,           jack->jack->name        )
+               __string(       name,           jack->jack->id          )
                __field(        int,            mask                    )
                __field(        int,            val                     )
        ),
 
        TP_fast_assign(
-               __assign_str(name, jack->jack->name);
+               __assign_str(name, jack->jack->id);
                __entry->mask = mask;
                __entry->val = val;
        ),
@@ -253,12 +253,12 @@ TRACE_EVENT(snd_soc_jack_notify,
        TP_ARGS(jack, val),
 
        TP_STRUCT__entry(
-               __string(       name,           jack->jack->name        )
+               __string(       name,           jack->jack->id          )
                __field(        int,            val                     )
        ),
 
        TP_fast_assign(
-               __assign_str(name, jack->jack->name);
+               __assign_str(name, jack->jack->id);
                __entry->val = val;
        ),
 
index 1e3c8cb43bd7ac61650da4b6e31ab854af4a7b89..625b38f65764b34fe9d942339ef61a08af817564 100644 (file)
@@ -66,27 +66,33 @@ struct media_device_info {
 /*
  * DVB entities
  */
-#define MEDIA_ENT_F_DTV_DEMOD          (MEDIA_ENT_F_BASE + 1)
-#define MEDIA_ENT_F_TS_DEMUX           (MEDIA_ENT_F_BASE + 2)
-#define MEDIA_ENT_F_DTV_CA             (MEDIA_ENT_F_BASE + 3)
-#define MEDIA_ENT_F_DTV_NET_DECAP      (MEDIA_ENT_F_BASE + 4)
+#define MEDIA_ENT_F_DTV_DEMOD          (MEDIA_ENT_F_BASE + 0x00001)
+#define MEDIA_ENT_F_TS_DEMUX           (MEDIA_ENT_F_BASE + 0x00002)
+#define MEDIA_ENT_F_DTV_CA             (MEDIA_ENT_F_BASE + 0x00003)
+#define MEDIA_ENT_F_DTV_NET_DECAP      (MEDIA_ENT_F_BASE + 0x00004)
 
 /*
- * Connectors
+ * I/O entities
  */
-/* It is a responsibility of the entity drivers to add connectors and links */
-#define MEDIA_ENT_F_CONN_RF            (MEDIA_ENT_F_BASE + 21)
-#define MEDIA_ENT_F_CONN_SVIDEO                (MEDIA_ENT_F_BASE + 22)
-#define MEDIA_ENT_F_CONN_COMPOSITE     (MEDIA_ENT_F_BASE + 23)
-/* For internal test signal generators and other debug connectors */
-#define MEDIA_ENT_F_CONN_TEST          (MEDIA_ENT_F_BASE + 24)
+#define MEDIA_ENT_F_IO_DTV             (MEDIA_ENT_F_BASE + 0x01001)
+#define MEDIA_ENT_F_IO_VBI             (MEDIA_ENT_F_BASE + 0x01002)
+#define MEDIA_ENT_F_IO_SWRADIO         (MEDIA_ENT_F_BASE + 0x01003)
 
 /*
- * I/O entities
+ * Connectors
  */
-#define MEDIA_ENT_F_IO_DTV             (MEDIA_ENT_F_BASE + 31)
-#define MEDIA_ENT_F_IO_VBI             (MEDIA_ENT_F_BASE + 32)
-#define MEDIA_ENT_F_IO_SWRADIO         (MEDIA_ENT_F_BASE + 33)
+/* It is a responsibility of the entity drivers to add connectors and links */
+#ifdef __KERNEL__
+       /*
+        * For now, it should not be used in userspace, as some
+        * definitions may change
+        */
+
+#define MEDIA_ENT_F_CONN_RF            (MEDIA_ENT_F_BASE + 0x30001)
+#define MEDIA_ENT_F_CONN_SVIDEO                (MEDIA_ENT_F_BASE + 0x30002)
+#define MEDIA_ENT_F_CONN_COMPOSITE     (MEDIA_ENT_F_BASE + 0x30003)
+
+#endif
 
 /*
  * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and
@@ -291,14 +297,14 @@ struct media_v2_entity {
        __u32 id;
        char name[64];          /* FIXME: move to a property? (RFC says so) */
        __u32 function;         /* Main function of the entity */
-       __u16 reserved[12];
-};
+       __u32 reserved[6];
+} __attribute__ ((packed));
 
 /* Should match the specific fields at media_intf_devnode */
 struct media_v2_intf_devnode {
        __u32 major;
        __u32 minor;
-};
+} __attribute__ ((packed));
 
 struct media_v2_interface {
        __u32 id;
@@ -310,22 +316,22 @@ struct media_v2_interface {
                struct media_v2_intf_devnode devnode;
                __u32 raw[16];
        };
-};
+} __attribute__ ((packed));
 
 struct media_v2_pad {
        __u32 id;
        __u32 entity_id;
        __u32 flags;
-       __u16 reserved[9];
-};
+       __u32 reserved[5];
+} __attribute__ ((packed));
 
 struct media_v2_link {
        __u32 id;
        __u32 source_id;
        __u32 sink_id;
        __u32 flags;
-       __u32 reserved[5];
-};
+       __u32 reserved[6];
+} __attribute__ ((packed));
 
 struct media_v2_topology {
        __u64 topology_version;
@@ -345,7 +351,7 @@ struct media_v2_topology {
        __u32 num_links;
        __u32 reserved4;
        __u64 ptr_links;
-};
+} __attribute__ ((packed));
 
 static inline void __user *media_get_uptr(__u64 arg)
 {
index 5b4a4be06e2b9301699db8da20d8df8d10bc0a89..cc68b92124d46108d43241d2b4cc603c2771e5b0 100644 (file)
@@ -66,14 +66,18 @@ struct nd_cmd_ars_cap {
        __u64 length;
        __u32 status;
        __u32 max_ars_out;
+       __u32 clear_err_unit;
+       __u32 reserved;
 } __packed;
 
 struct nd_cmd_ars_start {
        __u64 address;
        __u64 length;
        __u16 type;
-       __u8 reserved[6];
+       __u8 flags;
+       __u8 reserved[5];
        __u32 status;
+       __u32 scrub_time;
 } __packed;
 
 struct nd_cmd_ars_status {
@@ -81,11 +85,14 @@ struct nd_cmd_ars_status {
        __u32 out_length;
        __u64 address;
        __u64 length;
+       __u64 restart_address;
+       __u64 restart_length;
        __u16 type;
+       __u16 flags;
        __u32 num_records;
        struct nd_ars_record {
                __u32 handle;
-               __u32 flags;
+               __u32 reserved;
                __u64 err_address;
                __u64 length;
        } __packed records[0];
index ed3027d0f277a53745b41ea731c4783e3c554bee..331fc1b0b3c7952110f0223d741fc4fa19881d70 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -156,11 +156,12 @@ static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
        struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
 
        /*
-        * We raced in the idr lookup or with shm_destroy().  Either way, the
-        * ID is busted.
+        * Callers of shm_lock() must validate the status of the returned ipc
+        * object pointer (as returned by ipc_lock()), and error out as
+        * appropriate.
         */
-       WARN_ON(IS_ERR(ipcp));
-
+       if (IS_ERR(ipcp))
+               return (void *)ipcp;
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -186,18 +187,33 @@ static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
 }
 
 
-/* This is called by fork, once for every shm attach. */
-static void shm_open(struct vm_area_struct *vma)
+static int __shm_open(struct vm_area_struct *vma)
 {
        struct file *file = vma->vm_file;
        struct shm_file_data *sfd = shm_file_data(file);
        struct shmid_kernel *shp;
 
        shp = shm_lock(sfd->ns, sfd->id);
+
+       if (IS_ERR(shp))
+               return PTR_ERR(shp);
+
        shp->shm_atim = get_seconds();
        shp->shm_lprid = task_tgid_vnr(current);
        shp->shm_nattch++;
        shm_unlock(shp);
+       return 0;
+}
+
+/* This is called by fork, once for every shm attach. */
+static void shm_open(struct vm_area_struct *vma)
+{
+       int err = __shm_open(vma);
+       /*
+        * We raced in the idr lookup or with shm_destroy().
+        * Either way, the ID is busted.
+        */
+       WARN_ON_ONCE(err);
 }
 
 /*
@@ -260,6 +276,14 @@ static void shm_close(struct vm_area_struct *vma)
        down_write(&shm_ids(ns).rwsem);
        /* remove from the list of attaches of the shm segment */
        shp = shm_lock(ns, sfd->id);
+
+       /*
+        * We raced in the idr lookup or with shm_destroy().
+        * Either way, the ID is busted.
+        */
+       if (WARN_ON_ONCE(IS_ERR(shp)))
+               goto done; /* no-op */
+
        shp->shm_lprid = task_tgid_vnr(current);
        shp->shm_dtim = get_seconds();
        shp->shm_nattch--;
@@ -267,6 +291,7 @@ static void shm_close(struct vm_area_struct *vma)
                shm_destroy(ns, shp);
        else
                shm_unlock(shp);
+done:
        up_write(&shm_ids(ns).rwsem);
 }
 
@@ -388,17 +413,25 @@ static int shm_mmap(struct file *file, struct vm_area_struct *vma)
        struct shm_file_data *sfd = shm_file_data(file);
        int ret;
 
+       /*
+        * In case of remap_file_pages() emulation, the file can represent
+        * removed IPC ID: propogate shm_lock() error to caller.
+        */
+       ret =__shm_open(vma);
+       if (ret)
+               return ret;
+
        ret = sfd->file->f_op->mmap(sfd->file, vma);
-       if (ret != 0)
+       if (ret) {
+               shm_close(vma);
                return ret;
+       }
        sfd->vm_ops = vma->vm_ops;
 #ifdef CONFIG_MMU
        WARN_ON(!sfd->vm_ops->fault);
 #endif
        vma->vm_ops = &shm_vm_ops;
-       shm_open(vma);
-
-       return ret;
+       return 0;
 }
 
 static int shm_release(struct inode *ino, struct file *file)
index d1d3e8f57de907764fe3080632062485f5639443..2e7f7ab739e41c46072a69e787bf4e44f560ae55 100644 (file)
@@ -2082,7 +2082,7 @@ static void adjust_branches(struct bpf_prog *prog, int pos, int delta)
                /* adjust offset of jmps if necessary */
                if (i < pos && i + insn->off + 1 > pos)
                        insn->off += delta;
-               else if (i > pos && i + insn->off + 1 < pos)
+               else if (i > pos + delta && i + insn->off + 1 <= pos + delta)
                        insn->off -= delta;
        }
 }
index c03a640ef6da265db01b93c2970ab6b2da7abd67..d27904c193daa1d8a8680522093254cfde376177 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/atomic.h>
+#include <linux/cpuset.h>
 #include <net/sock.h>
 
 /*
@@ -2739,6 +2740,7 @@ out_unlock_rcu:
 out_unlock_threadgroup:
        percpu_up_write(&cgroup_threadgroup_rwsem);
        cgroup_kn_unlock(of->kn);
+       cpuset_post_attach_flush();
        return ret ?: nbytes;
 }
 
@@ -4655,14 +4657,15 @@ static void css_free_work_fn(struct work_struct *work)
 
        if (ss) {
                /* css free path */
+               struct cgroup_subsys_state *parent = css->parent;
                int id = css->id;
 
-               if (css->parent)
-                       css_put(css->parent);
-
                ss->css_free(css);
                cgroup_idr_remove(&ss->css_idr, id);
                cgroup_put(cgrp);
+
+               if (parent)
+                       css_put(parent);
        } else {
                /* cgroup free path */
                atomic_dec(&cgrp->root->nr_cgrps);
@@ -4758,6 +4761,7 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
        INIT_LIST_HEAD(&css->sibling);
        INIT_LIST_HEAD(&css->children);
        css->serial_nr = css_serial_nr_next++;
+       atomic_set(&css->online_cnt, 0);
 
        if (cgroup_parent(cgrp)) {
                css->parent = cgroup_css(cgroup_parent(cgrp), ss);
@@ -4780,6 +4784,10 @@ static int online_css(struct cgroup_subsys_state *css)
        if (!ret) {
                css->flags |= CSS_ONLINE;
                rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
+
+               atomic_inc(&css->online_cnt);
+               if (css->parent)
+                       atomic_inc(&css->parent->online_cnt);
        }
        return ret;
 }
@@ -5017,10 +5025,15 @@ static void css_killed_work_fn(struct work_struct *work)
                container_of(work, struct cgroup_subsys_state, destroy_work);
 
        mutex_lock(&cgroup_mutex);
-       offline_css(css);
-       mutex_unlock(&cgroup_mutex);
 
-       css_put(css);
+       do {
+               offline_css(css);
+               css_put(css);
+               /* @css can't go away while we're holding cgroup_mutex */
+               css = css->parent;
+       } while (css && atomic_dec_and_test(&css->online_cnt));
+
+       mutex_unlock(&cgroup_mutex);
 }
 
 /* css kill confirmation processing requires process context, bounce */
@@ -5029,8 +5042,10 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
        struct cgroup_subsys_state *css =
                container_of(ref, struct cgroup_subsys_state, refcnt);
 
-       INIT_WORK(&css->destroy_work, css_killed_work_fn);
-       queue_work(cgroup_destroy_wq, &css->destroy_work);
+       if (atomic_dec_and_test(&css->online_cnt)) {
+               INIT_WORK(&css->destroy_work, css_killed_work_fn);
+               queue_work(cgroup_destroy_wq, &css->destroy_work);
+       }
 }
 
 /**
index 3e945fcd81796f954a7e1c81ae95e78bd1a91dba..41989ab4db571cbf93d1a12738bc9afc3411e019 100644 (file)
@@ -287,6 +287,8 @@ static struct cpuset top_cpuset = {
 static DEFINE_MUTEX(cpuset_mutex);
 static DEFINE_SPINLOCK(callback_lock);
 
+static struct workqueue_struct *cpuset_migrate_mm_wq;
+
 /*
  * CPU / memory hotplug is handled asynchronously.
  */
@@ -972,31 +974,51 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
 }
 
 /*
- * cpuset_migrate_mm
- *
- *    Migrate memory region from one set of nodes to another.
- *
- *    Temporarilly set tasks mems_allowed to target nodes of migration,
- *    so that the migration code can allocate pages on these nodes.
- *
- *    While the mm_struct we are migrating is typically from some
- *    other task, the task_struct mems_allowed that we are hacking
- *    is for our current task, which must allocate new pages for that
- *    migrating memory region.
+ * Migrate memory region from one set of nodes to another.  This is
+ * performed asynchronously as it can be called from process migration path
+ * holding locks involved in process management.  All mm migrations are
+ * performed in the queued order and can be waited for by flushing
+ * cpuset_migrate_mm_wq.
  */
 
+struct cpuset_migrate_mm_work {
+       struct work_struct      work;
+       struct mm_struct        *mm;
+       nodemask_t              from;
+       nodemask_t              to;
+};
+
+static void cpuset_migrate_mm_workfn(struct work_struct *work)
+{
+       struct cpuset_migrate_mm_work *mwork =
+               container_of(work, struct cpuset_migrate_mm_work, work);
+
+       /* on a wq worker, no need to worry about %current's mems_allowed */
+       do_migrate_pages(mwork->mm, &mwork->from, &mwork->to, MPOL_MF_MOVE_ALL);
+       mmput(mwork->mm);
+       kfree(mwork);
+}
+
 static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
                                                        const nodemask_t *to)
 {
-       struct task_struct *tsk = current;
-
-       tsk->mems_allowed = *to;
+       struct cpuset_migrate_mm_work *mwork;
 
-       do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
+       mwork = kzalloc(sizeof(*mwork), GFP_KERNEL);
+       if (mwork) {
+               mwork->mm = mm;
+               mwork->from = *from;
+               mwork->to = *to;
+               INIT_WORK(&mwork->work, cpuset_migrate_mm_workfn);
+               queue_work(cpuset_migrate_mm_wq, &mwork->work);
+       } else {
+               mmput(mm);
+       }
+}
 
-       rcu_read_lock();
-       guarantee_online_mems(task_cs(tsk), &tsk->mems_allowed);
-       rcu_read_unlock();
+void cpuset_post_attach_flush(void)
+{
+       flush_workqueue(cpuset_migrate_mm_wq);
 }
 
 /*
@@ -1097,7 +1119,8 @@ static void update_tasks_nodemask(struct cpuset *cs)
                mpol_rebind_mm(mm, &cs->mems_allowed);
                if (migrate)
                        cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
-               mmput(mm);
+               else
+                       mmput(mm);
        }
        css_task_iter_end(&it);
 
@@ -1545,11 +1568,11 @@ static void cpuset_attach(struct cgroup_taskset *tset)
                         * @old_mems_allowed is the right nodesets that we
                         * migrate mm from.
                         */
-                       if (is_memory_migrate(cs)) {
+                       if (is_memory_migrate(cs))
                                cpuset_migrate_mm(mm, &oldcs->old_mems_allowed,
                                                  &cpuset_attach_nodemask_to);
-                       }
-                       mmput(mm);
+                       else
+                               mmput(mm);
                }
        }
 
@@ -1714,6 +1737,7 @@ out_unlock:
        mutex_unlock(&cpuset_mutex);
        kernfs_unbreak_active_protection(of->kn);
        css_put(&cs->css);
+       flush_workqueue(cpuset_migrate_mm_wq);
        return retval ?: nbytes;
 }
 
@@ -2359,6 +2383,9 @@ void __init cpuset_init_smp(void)
        top_cpuset.effective_mems = node_states[N_MEMORY];
 
        register_hotmemory_notifier(&cpuset_track_online_nodes_nb);
+
+       cpuset_migrate_mm_wq = alloc_ordered_workqueue("cpuset_migrate_mm", 0);
+       BUG_ON(!cpuset_migrate_mm_wq);
 }
 
 /**
index 5946460b24250a264f75c442099bb52ca06b0269..614614821f00a02928439b068903904d81233808 100644 (file)
@@ -64,8 +64,17 @@ static void remote_function(void *data)
        struct task_struct *p = tfc->p;
 
        if (p) {
-               tfc->ret = -EAGAIN;
-               if (task_cpu(p) != smp_processor_id() || !task_curr(p))
+               /* -EAGAIN */
+               if (task_cpu(p) != smp_processor_id())
+                       return;
+
+               /*
+                * Now that we're on right CPU with IRQs disabled, we can test
+                * if we hit the right task without races.
+                */
+
+               tfc->ret = -ESRCH; /* No such (running) process */
+               if (p != current)
                        return;
        }
 
@@ -92,13 +101,17 @@ task_function_call(struct task_struct *p, remote_function_f func, void *info)
                .p      = p,
                .func   = func,
                .info   = info,
-               .ret    = -ESRCH, /* No such (running) process */
+               .ret    = -EAGAIN,
        };
+       int ret;
 
-       if (task_curr(p))
-               smp_call_function_single(task_cpu(p), remote_function, &data, 1);
+       do {
+               ret = smp_call_function_single(task_cpu(p), remote_function, &data, 1);
+               if (!ret)
+                       ret = data.ret;
+       } while (ret == -EAGAIN);
 
-       return data.ret;
+       return ret;
 }
 
 /**
@@ -169,19 +182,6 @@ static bool is_kernel_event(struct perf_event *event)
  *    rely on ctx->is_active and therefore cannot use event_function_call().
  *    See perf_install_in_context().
  *
- * This is because we need a ctx->lock serialized variable (ctx->is_active)
- * to reliably determine if a particular task/context is scheduled in. The
- * task_curr() use in task_function_call() is racy in that a remote context
- * switch is not a single atomic operation.
- *
- * As is, the situation is 'safe' because we set rq->curr before we do the
- * actual context switch. This means that task_curr() will fail early, but
- * we'll continue spinning on ctx->is_active until we've passed
- * perf_event_task_sched_out().
- *
- * Without this ctx->lock serialized variable we could have race where we find
- * the task (and hence the context) would not be active while in fact they are.
- *
  * If ctx->nr_events, then ctx->is_active and cpuctx->task_ctx are set.
  */
 
@@ -212,7 +212,7 @@ static int event_function(void *info)
         */
        if (ctx->task) {
                if (ctx->task != current) {
-                       ret = -EAGAIN;
+                       ret = -ESRCH;
                        goto unlock;
                }
 
@@ -276,10 +276,10 @@ static void event_function_call(struct perf_event *event, event_f func, void *da
                return;
        }
 
-again:
        if (task == TASK_TOMBSTONE)
                return;
 
+again:
        if (!task_function_call(task, event_function, &efs))
                return;
 
@@ -289,13 +289,15 @@ again:
         * a concurrent perf_event_context_sched_out().
         */
        task = ctx->task;
-       if (task != TASK_TOMBSTONE) {
-               if (ctx->is_active) {
-                       raw_spin_unlock_irq(&ctx->lock);
-                       goto again;
-               }
-               func(event, NULL, ctx, data);
+       if (task == TASK_TOMBSTONE) {
+               raw_spin_unlock_irq(&ctx->lock);
+               return;
        }
+       if (ctx->is_active) {
+               raw_spin_unlock_irq(&ctx->lock);
+               goto again;
+       }
+       func(event, NULL, ctx, data);
        raw_spin_unlock_irq(&ctx->lock);
 }
 
@@ -314,6 +316,7 @@ again:
 enum event_type_t {
        EVENT_FLEXIBLE = 0x1,
        EVENT_PINNED = 0x2,
+       EVENT_TIME = 0x4,
        EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
 };
 
@@ -321,7 +324,13 @@ enum event_type_t {
  * perf_sched_events : >0 events exist
  * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
  */
-struct static_key_deferred perf_sched_events __read_mostly;
+
+static void perf_sched_delayed(struct work_struct *work);
+DEFINE_STATIC_KEY_FALSE(perf_sched_events);
+static DECLARE_DELAYED_WORK(perf_sched_work, perf_sched_delayed);
+static DEFINE_MUTEX(perf_sched_mutex);
+static atomic_t perf_sched_count;
+
 static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
 static DEFINE_PER_CPU(int, perf_sched_cb_usages);
 
@@ -1288,16 +1297,18 @@ static u64 perf_event_time(struct perf_event *event)
 
 /*
  * Update the total_time_enabled and total_time_running fields for a event.
- * The caller of this function needs to hold the ctx->lock.
  */
 static void update_event_times(struct perf_event *event)
 {
        struct perf_event_context *ctx = event->ctx;
        u64 run_end;
 
+       lockdep_assert_held(&ctx->lock);
+
        if (event->state < PERF_EVENT_STATE_INACTIVE ||
            event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
                return;
+
        /*
         * in cgroup mode, time_enabled represents
         * the time the event was enabled AND active
@@ -1645,7 +1656,7 @@ out:
 
 static bool is_orphaned_event(struct perf_event *event)
 {
-       return event->state == PERF_EVENT_STATE_EXIT;
+       return event->state == PERF_EVENT_STATE_DEAD;
 }
 
 static inline int pmu_filter_match(struct perf_event *event)
@@ -1690,14 +1701,14 @@ event_sched_out(struct perf_event *event,
 
        perf_pmu_disable(event->pmu);
 
+       event->tstamp_stopped = tstamp;
+       event->pmu->del(event, 0);
+       event->oncpu = -1;
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
                event->state = PERF_EVENT_STATE_OFF;
        }
-       event->tstamp_stopped = tstamp;
-       event->pmu->del(event, 0);
-       event->oncpu = -1;
 
        if (!is_software_event(event))
                cpuctx->active_oncpu--;
@@ -1732,7 +1743,6 @@ group_sched_out(struct perf_event *group_event,
 }
 
 #define DETACH_GROUP   0x01UL
-#define DETACH_STATE   0x02UL
 
 /*
  * Cross CPU call to remove a performance event
@@ -1752,8 +1762,6 @@ __perf_remove_from_context(struct perf_event *event,
        if (flags & DETACH_GROUP)
                perf_group_detach(event);
        list_del_event(event, ctx);
-       if (flags & DETACH_STATE)
-               event->state = PERF_EVENT_STATE_EXIT;
 
        if (!ctx->nr_events && ctx->is_active) {
                ctx->is_active = 0;
@@ -2063,14 +2071,27 @@ static void add_event_to_ctx(struct perf_event *event,
        event->tstamp_stopped = tstamp;
 }
 
-static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
-                              struct perf_event_context *ctx);
+static void ctx_sched_out(struct perf_event_context *ctx,
+                         struct perf_cpu_context *cpuctx,
+                         enum event_type_t event_type);
 static void
 ctx_sched_in(struct perf_event_context *ctx,
             struct perf_cpu_context *cpuctx,
             enum event_type_t event_type,
             struct task_struct *task);
 
+static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
+                              struct perf_event_context *ctx)
+{
+       if (!cpuctx->task_ctx)
+               return;
+
+       if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
+               return;
+
+       ctx_sched_out(ctx, cpuctx, EVENT_ALL);
+}
+
 static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
                                struct perf_event_context *ctx,
                                struct task_struct *task)
@@ -2097,49 +2118,68 @@ static void ctx_resched(struct perf_cpu_context *cpuctx,
 /*
  * Cross CPU call to install and enable a performance event
  *
- * Must be called with ctx->mutex held
+ * Very similar to remote_function() + event_function() but cannot assume that
+ * things like ctx->is_active and cpuctx->task_ctx are set.
  */
 static int  __perf_install_in_context(void *info)
 {
-       struct perf_event_context *ctx = info;
+       struct perf_event *event = info;
+       struct perf_event_context *ctx = event->ctx;
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
        struct perf_event_context *task_ctx = cpuctx->task_ctx;
+       bool activate = true;
+       int ret = 0;
 
        raw_spin_lock(&cpuctx->ctx.lock);
        if (ctx->task) {
                raw_spin_lock(&ctx->lock);
-               /*
-                * If we hit the 'wrong' task, we've since scheduled and
-                * everything should be sorted, nothing to do!
-                */
                task_ctx = ctx;
-               if (ctx->task != current)
+
+               /* If we're on the wrong CPU, try again */
+               if (task_cpu(ctx->task) != smp_processor_id()) {
+                       ret = -ESRCH;
                        goto unlock;
+               }
 
                /*
-                * If task_ctx is set, it had better be to us.
+                * If we're on the right CPU, see if the task we target is
+                * current, if not we don't have to activate the ctx, a future
+                * context switch will do that for us.
                 */
-               WARN_ON_ONCE(cpuctx->task_ctx != ctx && cpuctx->task_ctx);
+               if (ctx->task != current)
+                       activate = false;
+               else
+                       WARN_ON_ONCE(cpuctx->task_ctx && cpuctx->task_ctx != ctx);
+
        } else if (task_ctx) {
                raw_spin_lock(&task_ctx->lock);
        }
 
-       ctx_resched(cpuctx, task_ctx);
+       if (activate) {
+               ctx_sched_out(ctx, cpuctx, EVENT_TIME);
+               add_event_to_ctx(event, ctx);
+               ctx_resched(cpuctx, task_ctx);
+       } else {
+               add_event_to_ctx(event, ctx);
+       }
+
 unlock:
        perf_ctx_unlock(cpuctx, task_ctx);
 
-       return 0;
+       return ret;
 }
 
 /*
- * Attach a performance event to a context
+ * Attach a performance event to a context.
+ *
+ * Very similar to event_function_call, see comment there.
  */
 static void
 perf_install_in_context(struct perf_event_context *ctx,
                        struct perf_event *event,
                        int cpu)
 {
-       struct task_struct *task = NULL;
+       struct task_struct *task = READ_ONCE(ctx->task);
 
        lockdep_assert_held(&ctx->mutex);
 
@@ -2147,40 +2187,46 @@ perf_install_in_context(struct perf_event_context *ctx,
        if (event->cpu != -1)
                event->cpu = cpu;
 
+       if (!task) {
+               cpu_function_call(cpu, __perf_install_in_context, event);
+               return;
+       }
+
+       /*
+        * Should not happen, we validate the ctx is still alive before calling.
+        */
+       if (WARN_ON_ONCE(task == TASK_TOMBSTONE))
+               return;
+
        /*
         * Installing events is tricky because we cannot rely on ctx->is_active
         * to be set in case this is the nr_events 0 -> 1 transition.
-        *
-        * So what we do is we add the event to the list here, which will allow
-        * a future context switch to DTRT and then send a racy IPI. If the IPI
-        * fails to hit the right task, this means a context switch must have
-        * happened and that will have taken care of business.
         */
-       raw_spin_lock_irq(&ctx->lock);
-       task = ctx->task;
+again:
        /*
-        * Worse, we cannot even rely on the ctx actually existing anymore. If
-        * between find_get_context() and perf_install_in_context() the task
-        * went through perf_event_exit_task() its dead and we should not be
-        * adding new events.
+        * Cannot use task_function_call() because we need to run on the task's
+        * CPU regardless of whether its current or not.
         */
-       if (task == TASK_TOMBSTONE) {
+       if (!cpu_function_call(task_cpu(task), __perf_install_in_context, event))
+               return;
+
+       raw_spin_lock_irq(&ctx->lock);
+       task = ctx->task;
+       if (WARN_ON_ONCE(task == TASK_TOMBSTONE)) {
+               /*
+                * Cannot happen because we already checked above (which also
+                * cannot happen), and we hold ctx->mutex, which serializes us
+                * against perf_event_exit_task_context().
+                */
                raw_spin_unlock_irq(&ctx->lock);
                return;
        }
-       update_context_time(ctx);
+       raw_spin_unlock_irq(&ctx->lock);
        /*
-        * Update cgrp time only if current cgrp matches event->cgrp.
-        * Must be done before calling add_event_to_ctx().
+        * Since !ctx->is_active doesn't mean anything, we must IPI
+        * unconditionally.
         */
-       update_cgrp_time_from_event(event);
-       add_event_to_ctx(event, ctx);
-       raw_spin_unlock_irq(&ctx->lock);
-
-       if (task)
-               task_function_call(task, __perf_install_in_context, ctx);
-       else
-               cpu_function_call(cpu, __perf_install_in_context, ctx);
+       goto again;
 }
 
 /*
@@ -2219,17 +2265,18 @@ static void __perf_event_enable(struct perf_event *event,
            event->state <= PERF_EVENT_STATE_ERROR)
                return;
 
-       update_context_time(ctx);
+       if (ctx->is_active)
+               ctx_sched_out(ctx, cpuctx, EVENT_TIME);
+
        __perf_event_mark_enabled(event);
 
        if (!ctx->is_active)
                return;
 
        if (!event_filter_match(event)) {
-               if (is_cgroup_event(event)) {
-                       perf_cgroup_set_timestamp(current, ctx); // XXX ?
+               if (is_cgroup_event(event))
                        perf_cgroup_defer_enabled(event);
-               }
+               ctx_sched_in(ctx, cpuctx, EVENT_TIME, current);
                return;
        }
 
@@ -2237,8 +2284,10 @@ static void __perf_event_enable(struct perf_event *event,
         * If the event is in a group and isn't the group leader,
         * then don't put it on unless the group is on.
         */
-       if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE)
+       if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE) {
+               ctx_sched_in(ctx, cpuctx, EVENT_TIME, current);
                return;
+       }
 
        task_ctx = cpuctx->task_ctx;
        if (ctx->task)
@@ -2344,24 +2393,33 @@ static void ctx_sched_out(struct perf_event_context *ctx,
        }
 
        ctx->is_active &= ~event_type;
+       if (!(ctx->is_active & EVENT_ALL))
+               ctx->is_active = 0;
+
        if (ctx->task) {
                WARN_ON_ONCE(cpuctx->task_ctx != ctx);
                if (!ctx->is_active)
                        cpuctx->task_ctx = NULL;
        }
 
-       update_context_time(ctx);
-       update_cgrp_time_from_cpuctx(cpuctx);
-       if (!ctx->nr_active)
+       is_active ^= ctx->is_active; /* changed bits */
+
+       if (is_active & EVENT_TIME) {
+               /* update (and stop) ctx time */
+               update_context_time(ctx);
+               update_cgrp_time_from_cpuctx(cpuctx);
+       }
+
+       if (!ctx->nr_active || !(is_active & EVENT_ALL))
                return;
 
        perf_pmu_disable(ctx->pmu);
-       if ((is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) {
+       if (is_active & EVENT_PINNED) {
                list_for_each_entry(event, &ctx->pinned_groups, group_entry)
                        group_sched_out(event, cpuctx, ctx);
        }
 
-       if ((is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) {
+       if (is_active & EVENT_FLEXIBLE) {
                list_for_each_entry(event, &ctx->flexible_groups, group_entry)
                        group_sched_out(event, cpuctx, ctx);
        }
@@ -2641,18 +2699,6 @@ void __perf_event_task_sched_out(struct task_struct *task,
                perf_cgroup_sched_out(task, next);
 }
 
-static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
-                              struct perf_event_context *ctx)
-{
-       if (!cpuctx->task_ctx)
-               return;
-
-       if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
-               return;
-
-       ctx_sched_out(ctx, cpuctx, EVENT_ALL);
-}
-
 /*
  * Called with IRQs disabled
  */
@@ -2735,7 +2781,7 @@ ctx_sched_in(struct perf_event_context *ctx,
        if (likely(!ctx->nr_events))
                return;
 
-       ctx->is_active |= event_type;
+       ctx->is_active |= (event_type | EVENT_TIME);
        if (ctx->task) {
                if (!is_active)
                        cpuctx->task_ctx = ctx;
@@ -2743,18 +2789,24 @@ ctx_sched_in(struct perf_event_context *ctx,
                        WARN_ON_ONCE(cpuctx->task_ctx != ctx);
        }
 
-       now = perf_clock();
-       ctx->timestamp = now;
-       perf_cgroup_set_timestamp(task, ctx);
+       is_active ^= ctx->is_active; /* changed bits */
+
+       if (is_active & EVENT_TIME) {
+               /* start ctx time */
+               now = perf_clock();
+               ctx->timestamp = now;
+               perf_cgroup_set_timestamp(task, ctx);
+       }
+
        /*
         * First go through the list and put on any pinned groups
         * in order to give them the best chance of going on.
         */
-       if (!(is_active & EVENT_PINNED) && (event_type & EVENT_PINNED))
+       if (is_active & EVENT_PINNED)
                ctx_pinned_sched_in(ctx, cpuctx);
 
        /* Then walk through the lower prio flexible groups */
-       if (!(is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE))
+       if (is_active & EVENT_FLEXIBLE)
                ctx_flexible_sched_in(ctx, cpuctx);
 }
 
@@ -3120,6 +3172,7 @@ static void perf_event_enable_on_exec(int ctxn)
 
        cpuctx = __get_cpu_context(ctx);
        perf_ctx_lock(cpuctx, ctx);
+       ctx_sched_out(ctx, cpuctx, EVENT_TIME);
        list_for_each_entry(event, &ctx->event_list, event_entry)
                enabled |= event_enable_on_exec(event, ctx);
 
@@ -3537,12 +3590,22 @@ static void unaccount_event(struct perf_event *event)
        if (has_branch_stack(event))
                dec = true;
 
-       if (dec)
-               static_key_slow_dec_deferred(&perf_sched_events);
+       if (dec) {
+               if (!atomic_add_unless(&perf_sched_count, -1, 1))
+                       schedule_delayed_work(&perf_sched_work, HZ);
+       }
 
        unaccount_event_cpu(event, event->cpu);
 }
 
+static void perf_sched_delayed(struct work_struct *work)
+{
+       mutex_lock(&perf_sched_mutex);
+       if (atomic_dec_and_test(&perf_sched_count))
+               static_branch_disable(&perf_sched_events);
+       mutex_unlock(&perf_sched_mutex);
+}
+
 /*
  * The following implement mutual exclusion of events on "exclusive" pmus
  * (PERF_PMU_CAP_EXCLUSIVE). Such pmus can only have one event scheduled
@@ -3752,30 +3815,42 @@ static void put_event(struct perf_event *event)
  */
 int perf_event_release_kernel(struct perf_event *event)
 {
-       struct perf_event_context *ctx;
+       struct perf_event_context *ctx = event->ctx;
        struct perf_event *child, *tmp;
 
+       /*
+        * If we got here through err_file: fput(event_file); we will not have
+        * attached to a context yet.
+        */
+       if (!ctx) {
+               WARN_ON_ONCE(event->attach_state &
+                               (PERF_ATTACH_CONTEXT|PERF_ATTACH_GROUP));
+               goto no_ctx;
+       }
+
        if (!is_kernel_event(event))
                perf_remove_from_owner(event);
 
        ctx = perf_event_ctx_lock(event);
        WARN_ON_ONCE(ctx->parent_ctx);
-       perf_remove_from_context(event, DETACH_GROUP | DETACH_STATE);
-       perf_event_ctx_unlock(event, ctx);
+       perf_remove_from_context(event, DETACH_GROUP);
 
+       raw_spin_lock_irq(&ctx->lock);
        /*
-        * At this point we must have event->state == PERF_EVENT_STATE_EXIT,
-        * either from the above perf_remove_from_context() or through
-        * perf_event_exit_event().
+        * Mark this even as STATE_DEAD, there is no external reference to it
+        * anymore.
         *
-        * Therefore, anybody acquiring event->child_mutex after the below
-        * loop _must_ also see this, most importantly inherit_event() which
-        * will avoid placing more children on the list.
+        * Anybody acquiring event->child_mutex after the below loop _must_
+        * also see this, most importantly inherit_event() which will avoid
+        * placing more children on the list.
         *
         * Thus this guarantees that we will in fact observe and kill _ALL_
         * child events.
         */
-       WARN_ON_ONCE(event->state != PERF_EVENT_STATE_EXIT);
+       event->state = PERF_EVENT_STATE_DEAD;
+       raw_spin_unlock_irq(&ctx->lock);
+
+       perf_event_ctx_unlock(event, ctx);
 
 again:
        mutex_lock(&event->child_mutex);
@@ -3830,8 +3905,8 @@ again:
        }
        mutex_unlock(&event->child_mutex);
 
-       /* Must be the last reference */
-       put_event(event);
+no_ctx:
+       put_event(event); /* Must be the 'last' reference */
        return 0;
 }
 EXPORT_SYMBOL_GPL(perf_event_release_kernel);
@@ -3988,7 +4063,7 @@ static bool is_event_hup(struct perf_event *event)
 {
        bool no_children;
 
-       if (event->state != PERF_EVENT_STATE_EXIT)
+       if (event->state > PERF_EVENT_STATE_EXIT)
                return false;
 
        mutex_lock(&event->child_mutex);
@@ -7769,8 +7844,28 @@ static void account_event(struct perf_event *event)
        if (is_cgroup_event(event))
                inc = true;
 
-       if (inc)
-               static_key_slow_inc(&perf_sched_events.key);
+       if (inc) {
+               if (atomic_inc_not_zero(&perf_sched_count))
+                       goto enabled;
+
+               mutex_lock(&perf_sched_mutex);
+               if (!atomic_read(&perf_sched_count)) {
+                       static_branch_enable(&perf_sched_events);
+                       /*
+                        * Guarantee that all CPUs observe they key change and
+                        * call the perf scheduling hooks before proceeding to
+                        * install events that need them.
+                        */
+                       synchronize_sched();
+               }
+               /*
+                * Now that we have waited for the sync_sched(), allow further
+                * increments to by-pass the mutex.
+                */
+               atomic_inc(&perf_sched_count);
+               mutex_unlock(&perf_sched_mutex);
+       }
+enabled:
 
        account_event_cpu(event, event->cpu);
 }
@@ -8389,10 +8484,19 @@ SYSCALL_DEFINE5(perf_event_open,
        if (move_group) {
                gctx = group_leader->ctx;
                mutex_lock_double(&gctx->mutex, &ctx->mutex);
+               if (gctx->task == TASK_TOMBSTONE) {
+                       err = -ESRCH;
+                       goto err_locked;
+               }
        } else {
                mutex_lock(&ctx->mutex);
        }
 
+       if (ctx->task == TASK_TOMBSTONE) {
+               err = -ESRCH;
+               goto err_locked;
+       }
+
        if (!perf_event_validate_size(event)) {
                err = -E2BIG;
                goto err_locked;
@@ -8509,7 +8613,12 @@ err_context:
        perf_unpin_context(ctx);
        put_ctx(ctx);
 err_alloc:
-       free_event(event);
+       /*
+        * If event_file is set, the fput() above will have called ->release()
+        * and that will take care of freeing the event.
+        */
+       if (!event_file)
+               free_event(event);
 err_cpus:
        put_online_cpus();
 err_task:
@@ -8563,12 +8672,14 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
+       if (ctx->task == TASK_TOMBSTONE) {
+               err = -ESRCH;
+               goto err_unlock;
+       }
+
        if (!exclusive_event_installable(event, ctx)) {
-               mutex_unlock(&ctx->mutex);
-               perf_unpin_context(ctx);
-               put_ctx(ctx);
                err = -EBUSY;
-               goto err_free;
+               goto err_unlock;
        }
 
        perf_install_in_context(ctx, event, cpu);
@@ -8577,6 +8688,10 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 
        return event;
 
+err_unlock:
+       mutex_unlock(&ctx->mutex);
+       perf_unpin_context(ctx);
+       put_ctx(ctx);
 err_free:
        free_event(event);
 err:
@@ -8695,7 +8810,7 @@ perf_event_exit_event(struct perf_event *child_event,
        if (parent_event)
                perf_group_detach(child_event);
        list_del_event(child_event, child_ctx);
-       child_event->state = PERF_EVENT_STATE_EXIT; /* see perf_event_release_kernel() */
+       child_event->state = PERF_EVENT_STATE_EXIT; /* is_event_hup() */
        raw_spin_unlock_irq(&child_ctx->lock);
 
        /*
@@ -9206,7 +9321,7 @@ static void perf_event_init_cpu(int cpu)
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
        mutex_lock(&swhash->hlist_mutex);
-       if (swhash->hlist_refcount > 0) {
+       if (swhash->hlist_refcount > 0 && !swevent_hlist_deref(swhash)) {
                struct swevent_hlist *hlist;
 
                hlist = kzalloc_node(sizeof(*hlist), GFP_KERNEL, cpu_to_node(cpu));
@@ -9282,11 +9397,9 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
        switch (action & ~CPU_TASKS_FROZEN) {
 
        case CPU_UP_PREPARE:
-       case CPU_DOWN_FAILED:
                perf_event_init_cpu(cpu);
                break;
 
-       case CPU_UP_CANCELED:
        case CPU_DOWN_PREPARE:
                perf_event_exit_cpu(cpu);
                break;
@@ -9315,9 +9428,6 @@ void __init perf_event_init(void)
        ret = init_hw_breakpoint();
        WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
 
-       /* do not patch jump label more than once per second */
-       jump_label_rate_limit(&perf_sched_events, HZ);
-
        /*
         * Build time assertion that we keep the data_head at the intended
         * location.  IOW, validation we got the __reserved[] size right.
index 60ace56618f6c222de90e569bf1702b6dba05e26..716547fdb8731dcc395d70f2664ec6fb22378db6 100644 (file)
@@ -292,7 +292,7 @@ LIST_HEAD(all_lock_classes);
 #define __classhashfn(key)     hash_long((unsigned long)key, CLASSHASH_BITS)
 #define classhashentry(key)    (classhash_table + __classhashfn((key)))
 
-static struct list_head classhash_table[CLASSHASH_SIZE];
+static struct hlist_head classhash_table[CLASSHASH_SIZE];
 
 /*
  * We put the lock dependency chains into a hash-table as well, to cache
@@ -303,7 +303,7 @@ static struct list_head classhash_table[CLASSHASH_SIZE];
 #define __chainhashfn(chain)   hash_long(chain, CHAINHASH_BITS)
 #define chainhashentry(chain)  (chainhash_table + __chainhashfn((chain)))
 
-static struct list_head chainhash_table[CHAINHASH_SIZE];
+static struct hlist_head chainhash_table[CHAINHASH_SIZE];
 
 /*
  * The hash key of the lock dependency chains is a hash itself too:
@@ -666,7 +666,7 @@ static inline struct lock_class *
 look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
 {
        struct lockdep_subclass_key *key;
-       struct list_head *hash_head;
+       struct hlist_head *hash_head;
        struct lock_class *class;
 
 #ifdef CONFIG_DEBUG_LOCKDEP
@@ -719,7 +719,7 @@ look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return NULL;
 
-       list_for_each_entry_rcu(class, hash_head, hash_entry) {
+       hlist_for_each_entry_rcu(class, hash_head, hash_entry) {
                if (class->key == key) {
                        /*
                         * Huh! same key, different name? Did someone trample
@@ -742,7 +742,7 @@ static inline struct lock_class *
 register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
 {
        struct lockdep_subclass_key *key;
-       struct list_head *hash_head;
+       struct hlist_head *hash_head;
        struct lock_class *class;
 
        DEBUG_LOCKS_WARN_ON(!irqs_disabled());
@@ -774,7 +774,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
         * We have to do the hash-walk again, to avoid races
         * with another CPU:
         */
-       list_for_each_entry_rcu(class, hash_head, hash_entry) {
+       hlist_for_each_entry_rcu(class, hash_head, hash_entry) {
                if (class->key == key)
                        goto out_unlock_set;
        }
@@ -805,7 +805,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
         * We use RCU's safe list-add method to make
         * parallel walking of the hash-list safe:
         */
-       list_add_tail_rcu(&class->hash_entry, hash_head);
+       hlist_add_head_rcu(&class->hash_entry, hash_head);
        /*
         * Add it to the global list of classes:
         */
@@ -1822,7 +1822,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next,
  */
 static int
 check_prev_add(struct task_struct *curr, struct held_lock *prev,
-              struct held_lock *next, int distance, int trylock_loop)
+              struct held_lock *next, int distance, int *stack_saved)
 {
        struct lock_list *entry;
        int ret;
@@ -1883,8 +1883,11 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
                }
        }
 
-       if (!trylock_loop && !save_trace(&trace))
-               return 0;
+       if (!*stack_saved) {
+               if (!save_trace(&trace))
+                       return 0;
+               *stack_saved = 1;
+       }
 
        /*
         * Ok, all validations passed, add the new lock
@@ -1907,6 +1910,8 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
         * Debugging printouts:
         */
        if (verbose(hlock_class(prev)) || verbose(hlock_class(next))) {
+               /* We drop graph lock, so another thread can overwrite trace. */
+               *stack_saved = 0;
                graph_unlock();
                printk("\n new dependency: ");
                print_lock_name(hlock_class(prev));
@@ -1929,7 +1934,7 @@ static int
 check_prevs_add(struct task_struct *curr, struct held_lock *next)
 {
        int depth = curr->lockdep_depth;
-       int trylock_loop = 0;
+       int stack_saved = 0;
        struct held_lock *hlock;
 
        /*
@@ -1956,7 +1961,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
                 */
                if (hlock->read != 2 && hlock->check) {
                        if (!check_prev_add(curr, hlock, next,
-                                               distance, trylock_loop))
+                                               distance, &stack_saved))
                                return 0;
                        /*
                         * Stop after the first non-trylock entry,
@@ -1979,7 +1984,6 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
                if (curr->held_locks[depth].irq_context !=
                                curr->held_locks[depth-1].irq_context)
                        break;
-               trylock_loop = 1;
        }
        return 1;
 out_bug:
@@ -2017,7 +2021,7 @@ static inline int lookup_chain_cache(struct task_struct *curr,
                                     u64 chain_key)
 {
        struct lock_class *class = hlock_class(hlock);
-       struct list_head *hash_head = chainhashentry(chain_key);
+       struct hlist_head *hash_head = chainhashentry(chain_key);
        struct lock_chain *chain;
        struct held_lock *hlock_curr;
        int i, j;
@@ -2033,7 +2037,7 @@ static inline int lookup_chain_cache(struct task_struct *curr,
         * We can walk it lock-free, because entries only get added
         * to the hash:
         */
-       list_for_each_entry_rcu(chain, hash_head, entry) {
+       hlist_for_each_entry_rcu(chain, hash_head, entry) {
                if (chain->chain_key == chain_key) {
 cache_hit:
                        debug_atomic_inc(chain_lookup_hits);
@@ -2057,7 +2061,7 @@ cache_hit:
        /*
         * We have to walk the chain again locked - to avoid duplicates:
         */
-       list_for_each_entry(chain, hash_head, entry) {
+       hlist_for_each_entry(chain, hash_head, entry) {
                if (chain->chain_key == chain_key) {
                        graph_unlock();
                        goto cache_hit;
@@ -2091,7 +2095,7 @@ cache_hit:
                }
                chain_hlocks[chain->base + j] = class - lock_classes;
        }
-       list_add_tail_rcu(&chain->entry, hash_head);
+       hlist_add_head_rcu(&chain->entry, hash_head);
        debug_atomic_inc(chain_lookup_misses);
        inc_chains();
 
@@ -3875,7 +3879,7 @@ void lockdep_reset(void)
        nr_process_chains = 0;
        debug_locks = 1;
        for (i = 0; i < CHAINHASH_SIZE; i++)
-               INIT_LIST_HEAD(chainhash_table + i);
+               INIT_HLIST_HEAD(chainhash_table + i);
        raw_local_irq_restore(flags);
 }
 
@@ -3894,7 +3898,7 @@ static void zap_class(struct lock_class *class)
        /*
         * Unhash the class and remove it from the all_lock_classes list:
         */
-       list_del_rcu(&class->hash_entry);
+       hlist_del_rcu(&class->hash_entry);
        list_del_rcu(&class->lock_entry);
 
        RCU_INIT_POINTER(class->key, NULL);
@@ -3917,7 +3921,7 @@ static inline int within(const void *addr, void *start, unsigned long size)
 void lockdep_free_key_range(void *start, unsigned long size)
 {
        struct lock_class *class;
-       struct list_head *head;
+       struct hlist_head *head;
        unsigned long flags;
        int i;
        int locked;
@@ -3930,9 +3934,7 @@ void lockdep_free_key_range(void *start, unsigned long size)
         */
        for (i = 0; i < CLASSHASH_SIZE; i++) {
                head = classhash_table + i;
-               if (list_empty(head))
-                       continue;
-               list_for_each_entry_rcu(class, head, hash_entry) {
+               hlist_for_each_entry_rcu(class, head, hash_entry) {
                        if (within(class->key, start, size))
                                zap_class(class);
                        else if (within(class->name, start, size))
@@ -3962,7 +3964,7 @@ void lockdep_free_key_range(void *start, unsigned long size)
 void lockdep_reset_lock(struct lockdep_map *lock)
 {
        struct lock_class *class;
-       struct list_head *head;
+       struct hlist_head *head;
        unsigned long flags;
        int i, j;
        int locked;
@@ -3987,9 +3989,7 @@ void lockdep_reset_lock(struct lockdep_map *lock)
        locked = graph_lock();
        for (i = 0; i < CLASSHASH_SIZE; i++) {
                head = classhash_table + i;
-               if (list_empty(head))
-                       continue;
-               list_for_each_entry_rcu(class, head, hash_entry) {
+               hlist_for_each_entry_rcu(class, head, hash_entry) {
                        int match = 0;
 
                        for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
@@ -4027,10 +4027,10 @@ void lockdep_init(void)
                return;
 
        for (i = 0; i < CLASSHASH_SIZE; i++)
-               INIT_LIST_HEAD(classhash_table + i);
+               INIT_HLIST_HEAD(classhash_table + i);
 
        for (i = 0; i < CHAINHASH_SIZE; i++)
-               INIT_LIST_HEAD(chainhash_table + i);
+               INIT_HLIST_HEAD(chainhash_table + i);
 
        lockdep_initialized = 1;
 }
index 70ee3775de24ebcf2e80ab2fdad21eaad24dd2fe..b981a7b023f04c356df5b852f60caeae232fdf45 100644 (file)
@@ -114,7 +114,7 @@ EXPORT_SYMBOL(memunmap);
 
 static void devm_memremap_release(struct device *dev, void *res)
 {
-       memunmap(res);
+       memunmap(*(void **)res);
 }
 
 static int devm_memremap_match(struct device *dev, void *res, void *match_data)
@@ -136,8 +136,10 @@ void *devm_memremap(struct device *dev, resource_size_t offset,
        if (addr) {
                *ptr = addr;
                devres_add(dev, ptr);
-       } else
+       } else {
                devres_free(ptr);
+               return ERR_PTR(-ENXIO);
+       }
 
        return addr;
 }
@@ -150,7 +152,7 @@ void devm_memunmap(struct device *dev, void *addr)
 }
 EXPORT_SYMBOL(devm_memunmap);
 
-pfn_t phys_to_pfn_t(phys_addr_t addr, unsigned long flags)
+pfn_t phys_to_pfn_t(phys_addr_t addr, u64 flags)
 {
        return __pfn_to_pfn_t(addr >> PAGE_SHIFT, flags);
 }
index 8358f4697c0c3aea77aba802833660d4082b7c13..794ebe8e878d55cf9a0b94a1ae7a994ac4dec80b 100644 (file)
@@ -303,6 +303,9 @@ struct load_info {
        struct _ddebug *debug;
        unsigned int num_debug;
        bool sig_ok;
+#ifdef CONFIG_KALLSYMS
+       unsigned long mod_kallsyms_init_off;
+#endif
        struct {
                unsigned int sym, str, mod, vers, info, pcpu;
        } index;
@@ -981,6 +984,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
                mod->exit();
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
+       ftrace_release_mod(mod);
+
        async_synchronize_full();
 
        /* Store the name of the last unloaded module for diagnostic purposes */
@@ -2480,10 +2485,21 @@ static void layout_symtab(struct module *mod, struct load_info *info)
        strsect->sh_flags |= SHF_ALLOC;
        strsect->sh_entsize = get_offset(mod, &mod->init_layout.size, strsect,
                                         info->index.str) | INIT_OFFSET_MASK;
-       mod->init_layout.size = debug_align(mod->init_layout.size);
        pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
+
+       /* We'll tack temporary mod_kallsyms on the end. */
+       mod->init_layout.size = ALIGN(mod->init_layout.size,
+                                     __alignof__(struct mod_kallsyms));
+       info->mod_kallsyms_init_off = mod->init_layout.size;
+       mod->init_layout.size += sizeof(struct mod_kallsyms);
+       mod->init_layout.size = debug_align(mod->init_layout.size);
 }
 
+/*
+ * We use the full symtab and strtab which layout_symtab arranged to
+ * be appended to the init section.  Later we switch to the cut-down
+ * core-only ones.
+ */
 static void add_kallsyms(struct module *mod, const struct load_info *info)
 {
        unsigned int i, ndst;
@@ -2492,29 +2508,34 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
        char *s;
        Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
 
-       mod->symtab = (void *)symsec->sh_addr;
-       mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
+       /* Set up to point into init section. */
+       mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off;
+
+       mod->kallsyms->symtab = (void *)symsec->sh_addr;
+       mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
        /* Make sure we get permanent strtab: don't use info->strtab. */
-       mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
+       mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
 
        /* Set types up while we still have access to sections. */
-       for (i = 0; i < mod->num_symtab; i++)
-               mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
-
-       mod->core_symtab = dst = mod->core_layout.base + info->symoffs;
-       mod->core_strtab = s = mod->core_layout.base + info->stroffs;
-       src = mod->symtab;
-       for (ndst = i = 0; i < mod->num_symtab; i++) {
+       for (i = 0; i < mod->kallsyms->num_symtab; i++)
+               mod->kallsyms->symtab[i].st_info
+                       = elf_type(&mod->kallsyms->symtab[i], info);
+
+       /* Now populate the cut down core kallsyms for after init. */
+       mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs;
+       mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs;
+       src = mod->kallsyms->symtab;
+       for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
                if (i == 0 ||
                    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
                                   info->index.pcpu)) {
                        dst[ndst] = src[i];
-                       dst[ndst++].st_name = s - mod->core_strtab;
-                       s += strlcpy(s, &mod->strtab[src[i].st_name],
+                       dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
+                       s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
                                     KSYM_NAME_LEN) + 1;
                }
        }
-       mod->core_num_syms = ndst;
+       mod->core_kallsyms.num_symtab = ndst;
 }
 #else
 static inline void layout_symtab(struct module *mod, struct load_info *info)
@@ -3263,9 +3284,8 @@ static noinline int do_init_module(struct module *mod)
        module_put(mod);
        trim_init_extable(mod);
 #ifdef CONFIG_KALLSYMS
-       mod->num_symtab = mod->core_num_syms;
-       mod->symtab = mod->core_symtab;
-       mod->strtab = mod->core_strtab;
+       /* Switch to core kallsyms now init is done: kallsyms may be walking! */
+       rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
 #endif
        mod_tree_remove_init(mod);
        disable_ro_nx(&mod->init_layout);
@@ -3295,6 +3315,7 @@ fail:
        module_put(mod);
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
+       ftrace_release_mod(mod);
        free_module(mod);
        wake_up_all(&module_wq);
        return ret;
@@ -3371,6 +3392,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
        mod->state = MODULE_STATE_COMING;
        mutex_unlock(&module_mutex);
 
+       ftrace_module_enable(mod);
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_COMING, mod);
        return 0;
@@ -3496,7 +3518,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        /* Module is ready to execute: parsing args may do that. */
        after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-                                 -32768, 32767, NULL,
+                                 -32768, 32767, mod,
                                  unknown_module_param_cb);
        if (IS_ERR(after_dashes)) {
                err = PTR_ERR(after_dashes);
@@ -3627,6 +3649,11 @@ static inline int is_arm_mapping_symbol(const char *str)
               && (str[2] == '\0' || str[2] == '.');
 }
 
+static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
+{
+       return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
+}
+
 static const char *get_ksymbol(struct module *mod,
                               unsigned long addr,
                               unsigned long *size,
@@ -3634,6 +3661,7 @@ static const char *get_ksymbol(struct module *mod,
 {
        unsigned int i, best = 0;
        unsigned long nextval;
+       struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
 
        /* At worse, next value is at end of module */
        if (within_module_init(addr, mod))
@@ -3643,32 +3671,32 @@ static const char *get_ksymbol(struct module *mod,
 
        /* Scan for closest preceding symbol, and next symbol. (ELF
           starts real symbols at 1). */
-       for (i = 1; i < mod->num_symtab; i++) {
-               if (mod->symtab[i].st_shndx == SHN_UNDEF)
+       for (i = 1; i < kallsyms->num_symtab; i++) {
+               if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
                        continue;
 
                /* We ignore unnamed symbols: they're uninformative
                 * and inserted at a whim. */
-               if (mod->symtab[i].st_value <= addr
-                   && mod->symtab[i].st_value > mod->symtab[best].st_value
-                   && *(mod->strtab + mod->symtab[i].st_name) != '\0'
-                   && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
+               if (*symname(kallsyms, i) == '\0'
+                   || is_arm_mapping_symbol(symname(kallsyms, i)))
+                       continue;
+
+               if (kallsyms->symtab[i].st_value <= addr
+                   && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value)
                        best = i;
-               if (mod->symtab[i].st_value > addr
-                   && mod->symtab[i].st_value < nextval
-                   && *(mod->strtab + mod->symtab[i].st_name) != '\0'
-                   && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
-                       nextval = mod->symtab[i].st_value;
+               if (kallsyms->symtab[i].st_value > addr
+                   && kallsyms->symtab[i].st_value < nextval)
+                       nextval = kallsyms->symtab[i].st_value;
        }
 
        if (!best)
                return NULL;
 
        if (size)
-               *size = nextval - mod->symtab[best].st_value;
+               *size = nextval - kallsyms->symtab[best].st_value;
        if (offset)
-               *offset = addr - mod->symtab[best].st_value;
-       return mod->strtab + mod->symtab[best].st_name;
+               *offset = addr - kallsyms->symtab[best].st_value;
+       return symname(kallsyms, best);
 }
 
 /* For kallsyms to ask for address resolution.  NULL means not found.  Careful
@@ -3758,19 +3786,21 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
 
        preempt_disable();
        list_for_each_entry_rcu(mod, &modules, list) {
+               struct mod_kallsyms *kallsyms;
+
                if (mod->state == MODULE_STATE_UNFORMED)
                        continue;
-               if (symnum < mod->num_symtab) {
-                       *value = mod->symtab[symnum].st_value;
-                       *type = mod->symtab[symnum].st_info;
-                       strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
-                               KSYM_NAME_LEN);
+               kallsyms = rcu_dereference_sched(mod->kallsyms);
+               if (symnum < kallsyms->num_symtab) {
+                       *value = kallsyms->symtab[symnum].st_value;
+                       *type = kallsyms->symtab[symnum].st_info;
+                       strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
                        strlcpy(module_name, mod->name, MODULE_NAME_LEN);
                        *exported = is_exported(name, *value, mod);
                        preempt_enable();
                        return 0;
                }
-               symnum -= mod->num_symtab;
+               symnum -= kallsyms->num_symtab;
        }
        preempt_enable();
        return -ERANGE;
@@ -3779,11 +3809,12 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
 static unsigned long mod_find_symname(struct module *mod, const char *name)
 {
        unsigned int i;
+       struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
 
-       for (i = 0; i < mod->num_symtab; i++)
-               if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0 &&
-                   mod->symtab[i].st_info != 'U')
-                       return mod->symtab[i].st_value;
+       for (i = 0; i < kallsyms->num_symtab; i++)
+               if (strcmp(name, symname(kallsyms, i)) == 0 &&
+                   kallsyms->symtab[i].st_info != 'U')
+                       return kallsyms->symtab[i].st_value;
        return 0;
 }
 
@@ -3822,11 +3853,14 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
        module_assert_mutex();
 
        list_for_each_entry(mod, &modules, list) {
+               /* We hold module_mutex: no need for rcu_dereference_sched */
+               struct mod_kallsyms *kallsyms = mod->kallsyms;
+
                if (mod->state == MODULE_STATE_UNFORMED)
                        continue;
-               for (i = 0; i < mod->num_symtab; i++) {
-                       ret = fn(data, mod->strtab + mod->symtab[i].st_name,
-                                mod, mod->symtab[i].st_value);
+               for (i = 0; i < kallsyms->num_symtab; i++) {
+                       ret = fn(data, symname(kallsyms, i),
+                                mod, kallsyms->symtab[i].st_value);
                        if (ret != 0)
                                return ret;
                }
index 09c0597840b02dc260c65baafdd1fde0715bcbb4..3669d1bfc4254213e0e42dacab374624d74cdd5c 100644 (file)
@@ -1083,9 +1083,10 @@ struct resource * __request_region(struct resource *parent,
                if (!conflict)
                        break;
                if (conflict != parent) {
-                       parent = conflict;
-                       if (!(conflict->flags & IORESOURCE_BUSY))
+                       if (!(conflict->flags & IORESOURCE_BUSY)) {
+                               parent = conflict;
                                continue;
+                       }
                }
                if (conflict->flags & flags & IORESOURCE_MUXED) {
                        add_wait_queue(&muxed_resource_wait, &wait);
index cd64c979d0e1857aceb8f9f4383c507ad5fa6809..57b939c81bce5d06fa587df8915f05affbe22b82 100644 (file)
@@ -420,7 +420,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
         * entity.
         */
        if (dl_time_before(dl_se->deadline, rq_clock(rq))) {
-               printk_deferred_once("sched: DL replenish lagged to much\n");
+               printk_deferred_once("sched: DL replenish lagged too much\n");
                dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
                dl_se->runtime = pi_se->dl_runtime;
        }
index eca592f977b260689dc48911f867375b20ad5c8b..57a6eea8469408e7aba78669107eb3a1740362e4 100644 (file)
@@ -4961,7 +4961,7 @@ void ftrace_release_mod(struct module *mod)
        mutex_unlock(&ftrace_lock);
 }
 
-static void ftrace_module_enable(struct module *mod)
+void ftrace_module_enable(struct module *mod)
 {
        struct dyn_ftrace *rec;
        struct ftrace_page *pg;
@@ -5038,38 +5038,8 @@ void ftrace_module_init(struct module *mod)
        ftrace_process_locs(mod, mod->ftrace_callsites,
                            mod->ftrace_callsites + mod->num_ftrace_callsites);
 }
-
-static int ftrace_module_notify(struct notifier_block *self,
-                               unsigned long val, void *data)
-{
-       struct module *mod = data;
-
-       switch (val) {
-       case MODULE_STATE_COMING:
-               ftrace_module_enable(mod);
-               break;
-       case MODULE_STATE_GOING:
-               ftrace_release_mod(mod);
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-#else
-static int ftrace_module_notify(struct notifier_block *self,
-                               unsigned long val, void *data)
-{
-       return 0;
-}
 #endif /* CONFIG_MODULES */
 
-struct notifier_block ftrace_module_nb = {
-       .notifier_call = ftrace_module_notify,
-       .priority = INT_MIN,    /* Run after anything that can remove kprobes */
-};
-
 void __init ftrace_init(void)
 {
        extern unsigned long __start_mcount_loc[];
@@ -5098,10 +5068,6 @@ void __init ftrace_init(void)
                                  __start_mcount_loc,
                                  __stop_mcount_loc);
 
-       ret = register_module_notifier(&ftrace_module_nb);
-       if (ret)
-               pr_warning("Failed to register trace ftrace module exit notifier\n");
-
        set_ftrace_early_filters();
 
        return;
index f333e57c4614a2a6aaac04061003f73cd3a6d844..05ddc0820771eb7bc456aab9e2f0e5167ce7f023 100644 (file)
@@ -97,16 +97,16 @@ trace_find_event_field(struct trace_event_call *call, char *name)
        struct ftrace_event_field *field;
        struct list_head *head;
 
-       field = __find_event_field(&ftrace_generic_fields, name);
+       head = trace_get_fields(call);
+       field = __find_event_field(head, name);
        if (field)
                return field;
 
-       field = __find_event_field(&ftrace_common_fields, name);
+       field = __find_event_field(&ftrace_generic_fields, name);
        if (field)
                return field;
 
-       head = trace_get_fields(call);
-       return __find_event_field(head, name);
+       return __find_event_field(&ftrace_common_fields, name);
 }
 
 static int __trace_define_field(struct list_head *head, const char *type,
@@ -171,8 +171,10 @@ static int trace_define_generic_fields(void)
 {
        int ret;
 
-       __generic_field(int, cpu, FILTER_OTHER);
-       __generic_field(char *, comm, FILTER_PTR_STRING);
+       __generic_field(int, CPU, FILTER_CPU);
+       __generic_field(int, cpu, FILTER_CPU);
+       __generic_field(char *, COMM, FILTER_COMM);
+       __generic_field(char *, comm, FILTER_COMM);
 
        return ret;
 }
@@ -869,7 +871,8 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
                 * The ftrace subsystem is for showing formats only.
                 * They can not be enabled or disabled via the event files.
                 */
-               if (call->class && call->class->reg)
+               if (call->class && call->class->reg &&
+                   !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
                        return file;
        }
 
index f93a219b18daaa92ed314ad7ac4ba8e0ed3c4c09..6816302542b28158a4756373f5b3a57ed1a907fa 100644 (file)
@@ -1043,13 +1043,14 @@ static int init_pred(struct filter_parse_state *ps,
                return -EINVAL;
        }
 
-       if (is_string_field(field)) {
+       if (field->filter_type == FILTER_COMM) {
+               filter_build_regex(pred);
+               fn = filter_pred_comm;
+               pred->regex.field_len = TASK_COMM_LEN;
+       } else if (is_string_field(field)) {
                filter_build_regex(pred);
 
-               if (!strcmp(field->name, "comm")) {
-                       fn = filter_pred_comm;
-                       pred->regex.field_len = TASK_COMM_LEN;
-               } else if (field->filter_type == FILTER_STATIC_STRING) {
+               if (field->filter_type == FILTER_STATIC_STRING) {
                        fn = filter_pred_string;
                        pred->regex.field_len = field->size;
                } else if (field->filter_type == FILTER_DYN_STRING)
@@ -1072,7 +1073,7 @@ static int init_pred(struct filter_parse_state *ps,
                }
                pred->val = val;
 
-               if (!strcmp(field->name, "cpu"))
+               if (field->filter_type == FILTER_CPU)
                        fn = filter_pred_cpu;
                else
                        fn = select_comparison_fn(pred->op, field->size,
index 202df6cffccaab333c02facc56b28082b09e5e42..2a1abbaca10ec96126f3d8e380244214f77ee2a8 100644 (file)
@@ -156,7 +156,11 @@ check_stack(unsigned long ip, unsigned long *stack)
                for (; p < top && i < stack_trace_max.nr_entries; p++) {
                        if (stack_dump_trace[i] == ULONG_MAX)
                                break;
-                       if (*p == stack_dump_trace[i]) {
+                       /*
+                        * The READ_ONCE_NOCHECK is used to let KASAN know that
+                        * this is not a stack-out-of-bounds error.
+                        */
+                       if ((READ_ONCE_NOCHECK(*p)) == stack_dump_trace[i]) {
                                stack_dump_trace[x] = stack_dump_trace[i++];
                                this_size = stack_trace_index[x++] =
                                        (top - p) * sizeof(unsigned long);
index 61a0264e28f9b5917c0e8a60bb9668b21e59c4b2..7ff5dc7d2ac5f47395bc3be8484c642c5d577b6b 100644 (file)
@@ -301,7 +301,23 @@ static DEFINE_SPINLOCK(wq_mayday_lock);    /* protects wq->maydays list */
 static LIST_HEAD(workqueues);          /* PR: list of all workqueues */
 static bool workqueue_freezing;                /* PL: have wqs started freezing? */
 
-static cpumask_var_t wq_unbound_cpumask; /* PL: low level cpumask for all unbound wqs */
+/* PL: allowable cpus for unbound wqs and work items */
+static cpumask_var_t wq_unbound_cpumask;
+
+/* CPU where unbound work was last round robin scheduled from this CPU */
+static DEFINE_PER_CPU(int, wq_rr_cpu_last);
+
+/*
+ * Local execution of unbound work items is no longer guaranteed.  The
+ * following always forces round-robin CPU selection on unbound work items
+ * to uncover usages which depend on it.
+ */
+#ifdef CONFIG_DEBUG_WQ_FORCE_RR_CPU
+static bool wq_debug_force_rr_cpu = true;
+#else
+static bool wq_debug_force_rr_cpu = false;
+#endif
+module_param_named(debug_force_rr_cpu, wq_debug_force_rr_cpu, bool, 0644);
 
 /* the per-cpu worker pools */
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS],
@@ -570,6 +586,16 @@ static struct pool_workqueue *unbound_pwq_by_node(struct workqueue_struct *wq,
                                                  int node)
 {
        assert_rcu_or_wq_mutex_or_pool_mutex(wq);
+
+       /*
+        * XXX: @node can be NUMA_NO_NODE if CPU goes offline while a
+        * delayed item is pending.  The plan is to keep CPU -> NODE
+        * mapping valid and stable across CPU on/offlines.  Once that
+        * happens, this workaround can be removed.
+        */
+       if (unlikely(node == NUMA_NO_NODE))
+               return wq->dfl_pwq;
+
        return rcu_dereference_raw(wq->numa_pwq_tbl[node]);
 }
 
@@ -1298,6 +1324,39 @@ static bool is_chained_work(struct workqueue_struct *wq)
        return worker && worker->current_pwq->wq == wq;
 }
 
+/*
+ * When queueing an unbound work item to a wq, prefer local CPU if allowed
+ * by wq_unbound_cpumask.  Otherwise, round robin among the allowed ones to
+ * avoid perturbing sensitive tasks.
+ */
+static int wq_select_unbound_cpu(int cpu)
+{
+       static bool printed_dbg_warning;
+       int new_cpu;
+
+       if (likely(!wq_debug_force_rr_cpu)) {
+               if (cpumask_test_cpu(cpu, wq_unbound_cpumask))
+                       return cpu;
+       } else if (!printed_dbg_warning) {
+               pr_warn("workqueue: round-robin CPU selection forced, expect performance impact\n");
+               printed_dbg_warning = true;
+       }
+
+       if (cpumask_empty(wq_unbound_cpumask))
+               return cpu;
+
+       new_cpu = __this_cpu_read(wq_rr_cpu_last);
+       new_cpu = cpumask_next_and(new_cpu, wq_unbound_cpumask, cpu_online_mask);
+       if (unlikely(new_cpu >= nr_cpu_ids)) {
+               new_cpu = cpumask_first_and(wq_unbound_cpumask, cpu_online_mask);
+               if (unlikely(new_cpu >= nr_cpu_ids))
+                       return cpu;
+       }
+       __this_cpu_write(wq_rr_cpu_last, new_cpu);
+
+       return new_cpu;
+}
+
 static void __queue_work(int cpu, struct workqueue_struct *wq,
                         struct work_struct *work)
 {
@@ -1323,7 +1382,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
                return;
 retry:
        if (req_cpu == WORK_CPU_UNBOUND)
-               cpu = raw_smp_processor_id();
+               cpu = wq_select_unbound_cpu(raw_smp_processor_id());
 
        /* pwq which will be used unless @work is executing elsewhere */
        if (!(wq->flags & WQ_UNBOUND))
@@ -1464,13 +1523,13 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
        timer_stats_timer_set_start_info(&dwork->timer);
 
        dwork->wq = wq;
-       /* timer isn't guaranteed to run in this cpu, record earlier */
-       if (cpu == WORK_CPU_UNBOUND)
-               cpu = raw_smp_processor_id();
        dwork->cpu = cpu;
        timer->expires = jiffies + delay;
 
-       add_timer_on(timer, cpu);
+       if (unlikely(cpu != WORK_CPU_UNBOUND))
+               add_timer_on(timer, cpu);
+       else
+               add_timer(timer);
 }
 
 /**
@@ -2355,7 +2414,8 @@ static void check_flush_dependency(struct workqueue_struct *target_wq,
        WARN_ONCE(current->flags & PF_MEMALLOC,
                  "workqueue: PF_MEMALLOC task %d(%s) is flushing !WQ_MEM_RECLAIM %s:%pf",
                  current->pid, current->comm, target_wq->name, target_func);
-       WARN_ONCE(worker && (worker->current_pwq->wq->flags & WQ_MEM_RECLAIM),
+       WARN_ONCE(worker && ((worker->current_pwq->wq->flags &
+                             (WQ_MEM_RECLAIM | __WQ_LEGACY)) == WQ_MEM_RECLAIM),
                  "workqueue: WQ_MEM_RECLAIM %s:%pf is flushing !WQ_MEM_RECLAIM %s:%pf",
                  worker->current_pwq->wq->name, worker->current_func,
                  target_wq->name, target_func);
index ecb9e75614bf87f1e368074d6ef84bfe3f1003b8..8bfd1aca7a3d01a9887700b3f90d1d5697a9dab4 100644 (file)
@@ -1400,6 +1400,21 @@ config RCU_EQS_DEBUG
 
 endmenu # "RCU Debugging"
 
+config DEBUG_WQ_FORCE_RR_CPU
+       bool "Force round-robin CPU selection for unbound work items"
+       depends on DEBUG_KERNEL
+       default n
+       help
+         Workqueue used to implicitly guarantee that work items queued
+         without explicit CPU specified are put on the local CPU.  This
+         guarantee is no longer true and while local CPU is still
+         preferred work items may be put on foreign CPUs.  Kernel
+         parameter "workqueue.debug_force_rr_cpu" is added to force
+         round-robin CPU selection to flush out usages which depend on the
+         now broken guarantee.  This config option enables the debug
+         feature by default.  When enabled, memory and cache locality will
+         be impacted.
+
 config DEBUG_BLOCK_EXT_DEVT
         bool "Force extended block device numbers and spread them"
        depends on DEBUG_KERNEL
index 49518fb48cabb6d8c35b4a90b7d17917ebbfb211..e07c1ba9ba1339a80dac79d59255d80d600b096e 100644 (file)
@@ -18,6 +18,8 @@ config UBSAN_SANITIZE_ALL
          This option activates instrumentation for the entire kernel.
          If you don't enable this option, you have to explicitly specify
          UBSAN_SANITIZE := y for the files/directories you want to check for UB.
+         Enabling this option will get kernel image size increased
+         significantly.
 
 config UBSAN_ALIGNMENT
        bool "Enable checking of pointers alignment"
@@ -25,5 +27,5 @@ config UBSAN_ALIGNMENT
        default y if !HAVE_EFFICIENT_UNALIGNED_ACCESS
        help
          This option enables detection of unaligned memory accesses.
-         Enabling this option on architectures that support unalligned
+         Enabling this option on architectures that support unaligned
          accesses may produce a lot of false positives.
index d74cf7a29afdb043112fee5c9ad7b37a631a9985..0507fa5d84c534917d0842a453bdbcaba386422a 100644 (file)
@@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *k, struct klist_iter *i,
                          struct klist_node *n)
 {
        i->i_klist = k;
-       i->i_cur = n;
-       if (n)
-               kref_get(&n->n_ref);
+       i->i_cur = NULL;
+       if (n && kref_get_unless_zero(&n->n_ref))
+               i->i_cur = n;
 }
 EXPORT_SYMBOL_GPL(klist_iter_init_node);
 
index bafa9933fa768d6f76e4ade1296c873a3c38c139..004fc70fc56a3d06947f9e89c60e40e272ce551c 100644 (file)
@@ -598,9 +598,9 @@ EXPORT_SYMBOL(sg_miter_next);
  *
  * Description:
  *   Stops mapping iterator @miter.  @miter should have been started
- *   started using sg_miter_start().  A stopped iteration can be
- *   resumed by calling sg_miter_next() on it.  This is useful when
- *   resources (kmap) need to be released during iteration.
+ *   using sg_miter_start().  A stopped iteration can be resumed by
+ *   calling sg_miter_next() on it.  This is useful when resources (kmap)
+ *   need to be released during iteration.
  *
  * Context:
  *   Preemption disabled if the SG_MITER_ATOMIC is set.  Don't care
index 6f500ef2301d893c9b2c737747fc355974ff4a19..f0b323abb4c64a566700d9d265f4451174847eaa 100644 (file)
@@ -49,3 +49,65 @@ ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
         }
 }
 EXPORT_SYMBOL(ucs2_strncmp);
+
+unsigned long
+ucs2_utf8size(const ucs2_char_t *src)
+{
+       unsigned long i;
+       unsigned long j = 0;
+
+       for (i = 0; i < ucs2_strlen(src); i++) {
+               u16 c = src[i];
+
+               if (c >= 0x800)
+                       j += 3;
+               else if (c >= 0x80)
+                       j += 2;
+               else
+                       j += 1;
+       }
+
+       return j;
+}
+EXPORT_SYMBOL(ucs2_utf8size);
+
+/*
+ * copy at most maxlength bytes of whole utf8 characters to dest from the
+ * ucs2 string src.
+ *
+ * The return value is the number of characters copied, not including the
+ * final NUL character.
+ */
+unsigned long
+ucs2_as_utf8(u8 *dest, const ucs2_char_t *src, unsigned long maxlength)
+{
+       unsigned int i;
+       unsigned long j = 0;
+       unsigned long limit = ucs2_strnlen(src, maxlength);
+
+       for (i = 0; maxlength && i < limit; i++) {
+               u16 c = src[i];
+
+               if (c >= 0x800) {
+                       if (maxlength < 3)
+                               break;
+                       maxlength -= 3;
+                       dest[j++] = 0xe0 | (c & 0xf000) >> 12;
+                       dest[j++] = 0x80 | (c & 0x0fc0) >> 6;
+                       dest[j++] = 0x80 | (c & 0x003f);
+               } else if (c >= 0x80) {
+                       if (maxlength < 2)
+                               break;
+                       maxlength -= 2;
+                       dest[j++] = 0xc0 | (c & 0x7c0) >> 6;
+                       dest[j++] = 0x80 | (c & 0x03f);
+               } else {
+                       maxlength -= 1;
+                       dest[j++] = c & 0x7f;
+               }
+       }
+       if (maxlength)
+               dest[j] = '\0';
+       return j;
+}
+EXPORT_SYMBOL(ucs2_as_utf8);
index 48ff9c36644d64c324c5c243212f282e406dce2f..f44e178e6edec22e2f7c405f8cb433b2be935f83 100644 (file)
@@ -1590,22 +1590,23 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                        return buf;
                }
        case 'K':
-               /*
-                * %pK cannot be used in IRQ context because its test
-                * for CAP_SYSLOG would be meaningless.
-                */
-               if (kptr_restrict && (in_irq() || in_serving_softirq() ||
-                                     in_nmi())) {
-                       if (spec.field_width == -1)
-                               spec.field_width = default_width;
-                       return string(buf, end, "pK-error", spec);
-               }
-
                switch (kptr_restrict) {
                case 0:
                        /* Always print %pK values */
                        break;
                case 1: {
+                       const struct cred *cred;
+
+                       /*
+                        * kptr_restrict==1 cannot be used in IRQ context
+                        * because its test for CAP_SYSLOG would be meaningless.
+                        */
+                       if (in_irq() || in_serving_softirq() || in_nmi()) {
+                               if (spec.field_width == -1)
+                                       spec.field_width = default_width;
+                               return string(buf, end, "pK-error", spec);
+                       }
+
                        /*
                         * Only print the real pointer value if the current
                         * process has CAP_SYSLOG and is running with the
@@ -1615,8 +1616,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                         * leak pointer values if a binary opens a file using
                         * %pK and then elevates privileges before reading it.
                         */
-                       const struct cred *cred = current_cred();
-
+                       cred = current_cred();
                        if (!has_capability_noaudit(current, CAP_SYSLOG) ||
                            !uid_eq(cred->euid, cred->uid) ||
                            !gid_eq(cred->egid, cred->gid))
index 926c76d56388d12ea723b68add1e5b7ab6613842..c554d173a65fa640186b058e5e97be68b48c7ea5 100644 (file)
@@ -328,7 +328,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
        return 0;
 
 out_destroy_stat:
-       while (--i)
+       while (i--)
                percpu_counter_destroy(&wb->stat[i]);
        fprop_local_destroy_percpu(&wb->completions);
 out_put_cong:
index bc943867d68c68dab4109fe715c8d37d6c72757a..3461d97ecb30bfe18d1ed50729e5147aa2ad7e6d 100644 (file)
@@ -446,7 +446,8 @@ int filemap_write_and_wait(struct address_space *mapping)
 {
        int err = 0;
 
-       if (mapping->nrpages) {
+       if ((!dax_mapping(mapping) && mapping->nrpages) ||
+           (dax_mapping(mapping) && mapping->nrexceptional)) {
                err = filemap_fdatawrite(mapping);
                /*
                 * Even if the above returned error, the pages may be
@@ -482,13 +483,8 @@ int filemap_write_and_wait_range(struct address_space *mapping,
 {
        int err = 0;
 
-       if (dax_mapping(mapping) && mapping->nrexceptional) {
-               err = dax_writeback_mapping_range(mapping, lstart, lend);
-               if (err)
-                       return err;
-       }
-
-       if (mapping->nrpages) {
+       if ((!dax_mapping(mapping) && mapping->nrpages) ||
+           (dax_mapping(mapping) && mapping->nrexceptional)) {
                err = __filemap_fdatawrite_range(mapping, lstart, lend,
                                                 WB_SYNC_ALL);
                /* See comment of filemap_write_and_wait() */
@@ -1890,6 +1886,7 @@ EXPORT_SYMBOL(generic_file_read_iter);
  * page_cache_read - adds requested page to the page cache if not already there
  * @file:      file to read
  * @offset:    page index
+ * @gfp_mask:  memory allocation flags
  *
  * This adds the requested page to the page cache if it isn't already there,
  * and schedules an I/O to read in its contents from disk.
index 08fc0ba2207e555a9c734524cd607dc8f53e644a..e10a4fee88d2bcf1f4bba89285391cbadfb96098 100644 (file)
@@ -1700,7 +1700,8 @@ bool move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
                pmd = pmdp_huge_get_and_clear(mm, old_addr, old_pmd);
                VM_BUG_ON(!pmd_none(*new_pmd));
 
-               if (pmd_move_must_withdraw(new_ptl, old_ptl)) {
+               if (pmd_move_must_withdraw(new_ptl, old_ptl) &&
+                               vma_is_anonymous(vma)) {
                        pgtable_t pgtable;
                        pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
                        pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
@@ -2835,6 +2836,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
        pgtable_t pgtable;
        pmd_t _pmd;
        bool young, write, dirty;
+       unsigned long addr;
        int i;
 
        VM_BUG_ON(haddr & ~HPAGE_PMD_MASK);
@@ -2860,10 +2862,11 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
        young = pmd_young(*pmd);
        dirty = pmd_dirty(*pmd);
 
+       pmdp_huge_split_prepare(vma, haddr, pmd);
        pgtable = pgtable_trans_huge_withdraw(mm, pmd);
        pmd_populate(mm, &_pmd, pgtable);
 
-       for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+       for (i = 0, addr = haddr; i < HPAGE_PMD_NR; i++, addr += PAGE_SIZE) {
                pte_t entry, *pte;
                /*
                 * Note that NUMA hinting access restrictions are not
@@ -2884,9 +2887,9 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
                }
                if (dirty)
                        SetPageDirty(page + i);
-               pte = pte_offset_map(&_pmd, haddr);
+               pte = pte_offset_map(&_pmd, addr);
                BUG_ON(!pte_none(*pte));
-               set_pte_at(mm, haddr, pte, entry);
+               set_pte_at(mm, addr, pte, entry);
                atomic_inc(&page[i]._mapcount);
                pte_unmap(pte);
        }
@@ -2936,7 +2939,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
        pmd_populate(mm, pmd, pgtable);
 
        if (freeze) {
-               for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+               for (i = 0; i < HPAGE_PMD_NR; i++) {
                        page_remove_rmap(page + i, false);
                        put_page(page + i);
                }
index 06ae13e869d0f088cdddc0862aa315ce8d488443..01f2b48c8618a9f973eeb11f2162b75bb8cf67d4 100644 (file)
@@ -2630,8 +2630,10 @@ static int __init hugetlb_init(void)
                        hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
        }
        default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size));
-       if (default_hstate_max_huge_pages)
-               default_hstate.max_huge_pages = default_hstate_max_huge_pages;
+       if (default_hstate_max_huge_pages) {
+               if (!default_hstate.max_huge_pages)
+                       default_hstate.max_huge_pages = default_hstate_max_huge_pages;
+       }
 
        hugetlb_init_hstates();
        gather_bootmem_prealloc();
index 635451abc8f7c9b84663535678a26a9b0848c89d..8132787ae4d509d475ed6a77705076ddfee30630 100644 (file)
@@ -3404,8 +3404,18 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(pmd_none(*pmd)) &&
            unlikely(__pte_alloc(mm, vma, pmd, address)))
                return VM_FAULT_OOM;
-       /* if an huge pmd materialized from under us just retry later */
-       if (unlikely(pmd_trans_huge(*pmd) || pmd_devmap(*pmd)))
+       /*
+        * If a huge pmd materialized under us just retry later.  Use
+        * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd
+        * didn't become pmd_trans_huge under us and then back to pmd_none, as
+        * a result of MADV_DONTNEED running immediately after a huge pmd fault
+        * in a different thread of this mm, in turn leading to a misleading
+        * pmd_trans_huge() retval.  All we have to ensure is that it is a
+        * regular pmd that we can walk with pte_offset_map() and we can do that
+        * through an atomic read in C, which is what pmd_trans_unstable()
+        * provides.
+        */
+       if (unlikely(pmd_trans_unstable(pmd) || pmd_devmap(*pmd)))
                return 0;
        /*
         * A regular pmd is established and it can't morph into a huge pmd
index b1034f9c77e7d5a9bdbe60692396e5584c6991fc..3ad0fea5c4387c5b6ff1d8fb513b73488b9180f2 100644 (file)
@@ -1582,7 +1582,7 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
                                         (GFP_HIGHUSER_MOVABLE |
                                          __GFP_THISNODE | __GFP_NOMEMALLOC |
                                          __GFP_NORETRY | __GFP_NOWARN) &
-                                        ~(__GFP_IO | __GFP_FS), 0);
+                                        ~__GFP_RECLAIM, 0);
 
        return newpage;
 }
index 2f2415a7a688da595a996a01d0ae0e1f0f955454..76d1ec29149bf25f5e6ffe3e56e86467efccc641 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2664,12 +2664,29 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        if (!vma || !(vma->vm_flags & VM_SHARED))
                goto out;
 
-       if (start < vma->vm_start || start + size > vma->vm_end)
+       if (start < vma->vm_start)
                goto out;
 
-       if (pgoff == linear_page_index(vma, start)) {
-               ret = 0;
-               goto out;
+       if (start + size > vma->vm_end) {
+               struct vm_area_struct *next;
+
+               for (next = vma->vm_next; next; next = next->vm_next) {
+                       /* hole between vmas ? */
+                       if (next->vm_start != next->vm_prev->vm_end)
+                               goto out;
+
+                       if (next->vm_file != vma->vm_file)
+                               goto out;
+
+                       if (next->vm_flags != vma->vm_flags)
+                               goto out;
+
+                       if (start + size <= next->vm_end)
+                               break;
+               }
+
+               if (!next)
+                       goto out;
        }
 
        prot |= vma->vm_flags & VM_READ ? PROT_READ : 0;
@@ -2679,9 +2696,16 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        flags &= MAP_NONBLOCK;
        flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE;
        if (vma->vm_flags & VM_LOCKED) {
+               struct vm_area_struct *tmp;
                flags |= MAP_LOCKED;
+
                /* drop PG_Mlocked flag for over-mapped range */
-               munlock_vma_pages_range(vma, start, start + size);
+               for (tmp = vma; tmp->vm_start >= start + size;
+                               tmp = tmp->vm_next) {
+                       munlock_vma_pages_range(tmp,
+                                       max(tmp->vm_start, start),
+                                       min(tmp->vm_end, start + size));
+               }
        }
 
        file = get_file(vma->vm_file);
index 8eb7bb40dc40b6e8e89d05fbb7e05f8c836e05da..f7cb3d4d9c2eb55d74738e374faa3bfa37251686 100644 (file)
@@ -160,9 +160,11 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                }
 
                if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
-                       if (next - addr != HPAGE_PMD_SIZE)
+                       if (next - addr != HPAGE_PMD_SIZE) {
                                split_huge_pmd(vma, pmd, addr);
-                       else {
+                               if (pmd_none(*pmd))
+                                       continue;
+                       } else {
                                int nr_ptes = change_huge_pmd(vma, pmd, addr,
                                                newprot, prot_numa);
 
index d77946a997f798ecc25ccaee2886139ff9d9a587..8eeba02fc99137b5a47996750159de8a455e2c4d 100644 (file)
@@ -210,6 +210,8 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
                                }
                        }
                        split_huge_pmd(vma, old_pmd, old_addr);
+                       if (pmd_none(*old_pmd))
+                               continue;
                        VM_BUG_ON(pmd_trans_huge(*old_pmd));
                }
                if (pmd_none(*new_pmd) && __pte_alloc(new_vma->vm_mm, new_vma,
index 9d4767698a1cd6988d4f71b37ef3f384eff5b3b1..06a005b979a763cb4afbf0e57fe9c7f70d2c0c92 100644 (file)
@@ -90,9 +90,9 @@ pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
  * ARCHes with special requirements for evicting THP backing TLB entries can
  * implement this. Otherwise also, it can help optimize normal TLB flush in
  * THP regime. stock flush_tlb_range() typically has optimization to nuke the
- * entire TLB TLB if flush span is greater than a threshhold, which will
+ * entire TLB if flush span is greater than a threshold, which will
  * likely be true for a single huge page. Thus a single thp flush will
- * invalidate the entire TLB which is not desitable.
+ * invalidate the entire TLB which is not desirable.
  * e.g. see arch/arc: flush_pmd_tlb_range
  */
 #define flush_pmd_tlb_range(vma, addr, end)    flush_tlb_range(vma, addr, end)
@@ -195,7 +195,9 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
        VM_BUG_ON(address & ~HPAGE_PMD_MASK);
        VM_BUG_ON(pmd_trans_huge(*pmdp));
        pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
-       flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+
+       /* collapse entails shooting down ptes not pmd */
+       flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
        return pmd;
 }
 #endif
index 6ecc697a8bc4670a3910fdcdc155196ee71a539a..621fbcb35a366abf0d979cf48c5476cff1e609f5 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2275,7 +2275,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 
        err = setup_cpu_cache(cachep, gfp);
        if (err) {
-               __kmem_cache_shutdown(cachep);
+               __kmem_cache_release(cachep);
                return err;
        }
 
@@ -2413,13 +2413,14 @@ int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate)
 }
 
 int __kmem_cache_shutdown(struct kmem_cache *cachep)
+{
+       return __kmem_cache_shrink(cachep, false);
+}
+
+void __kmem_cache_release(struct kmem_cache *cachep)
 {
        int i;
        struct kmem_cache_node *n;
-       int rc = __kmem_cache_shrink(cachep, false);
-
-       if (rc)
-               return rc;
 
        free_percpu(cachep->cpu_cache);
 
@@ -2430,7 +2431,6 @@ int __kmem_cache_shutdown(struct kmem_cache *cachep)
                kfree(n);
                cachep->node[i] = NULL;
        }
-       return 0;
 }
 
 /*
index 834ad240c0bb13980fbe10fb29aba166dcff3f28..2eedacea439de698bdf2103f54ae936fe40de48d 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -140,6 +140,7 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size,
 #define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS)
 
 int __kmem_cache_shutdown(struct kmem_cache *);
+void __kmem_cache_release(struct kmem_cache *);
 int __kmem_cache_shrink(struct kmem_cache *, bool);
 void slab_kmem_cache_release(struct kmem_cache *);
 
index b50aef01ccf7ea97aa621dc63cfd66e111ee3dae..065b7bdabdc30c5b763b368d84e2057fcde3eb5a 100644 (file)
@@ -693,6 +693,7 @@ static inline int shutdown_memcg_caches(struct kmem_cache *s,
 
 void slab_kmem_cache_release(struct kmem_cache *s)
 {
+       __kmem_cache_release(s);
        destroy_memcg_params(s);
        kfree_const(s->name);
        kmem_cache_free(kmem_cache, s);
index 17e8f8cc7c534adca165f6d0e9b546e2f8484148..5ec158054ffe0b2ddf20c01276403f1984108dcb 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -630,6 +630,10 @@ int __kmem_cache_shutdown(struct kmem_cache *c)
        return 0;
 }
 
+void __kmem_cache_release(struct kmem_cache *c)
+{
+}
+
 int __kmem_cache_shrink(struct kmem_cache *d, bool deactivate)
 {
        return 0;
index 2e1355ac056b02a51778b2b1eef770b276626309..d8fbd4a6ed599882489143665ca750eb7613fd65 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1592,18 +1592,12 @@ static inline void add_partial(struct kmem_cache_node *n,
        __add_partial(n, page, tail);
 }
 
-static inline void
-__remove_partial(struct kmem_cache_node *n, struct page *page)
-{
-       list_del(&page->lru);
-       n->nr_partial--;
-}
-
 static inline void remove_partial(struct kmem_cache_node *n,
                                        struct page *page)
 {
        lockdep_assert_held(&n->list_lock);
-       __remove_partial(n, page);
+       list_del(&page->lru);
+       n->nr_partial--;
 }
 
 /*
@@ -3184,6 +3178,12 @@ static void free_kmem_cache_nodes(struct kmem_cache *s)
        }
 }
 
+void __kmem_cache_release(struct kmem_cache *s)
+{
+       free_percpu(s->cpu_slab);
+       free_kmem_cache_nodes(s);
+}
+
 static int init_kmem_cache_nodes(struct kmem_cache *s)
 {
        int node;
@@ -3443,28 +3443,31 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
 
 /*
  * Attempt to free all partial slabs on a node.
- * This is called from kmem_cache_close(). We must be the last thread
- * using the cache and therefore we do not need to lock anymore.
+ * This is called from __kmem_cache_shutdown(). We must take list_lock
+ * because sysfs file might still access partial list after the shutdowning.
  */
 static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
 {
        struct page *page, *h;
 
+       BUG_ON(irqs_disabled());
+       spin_lock_irq(&n->list_lock);
        list_for_each_entry_safe(page, h, &n->partial, lru) {
                if (!page->inuse) {
-                       __remove_partial(n, page);
+                       remove_partial(n, page);
                        discard_slab(s, page);
                } else {
                        list_slab_objects(s, page,
-                       "Objects remaining in %s on kmem_cache_close()");
+                       "Objects remaining in %s on __kmem_cache_shutdown()");
                }
        }
+       spin_unlock_irq(&n->list_lock);
 }
 
 /*
  * Release all resources used by a slab cache.
  */
-static inline int kmem_cache_close(struct kmem_cache *s)
+int __kmem_cache_shutdown(struct kmem_cache *s)
 {
        int node;
        struct kmem_cache_node *n;
@@ -3476,16 +3479,9 @@ static inline int kmem_cache_close(struct kmem_cache *s)
                if (n->nr_partial || slabs_node(s, node))
                        return 1;
        }
-       free_percpu(s->cpu_slab);
-       free_kmem_cache_nodes(s);
        return 0;
 }
 
-int __kmem_cache_shutdown(struct kmem_cache *s)
-{
-       return kmem_cache_close(s);
-}
-
 /********************************************************************
  *             Kmalloc subsystem
  *******************************************************************/
@@ -3980,7 +3976,7 @@ int __kmem_cache_create(struct kmem_cache *s, unsigned long flags)
        memcg_propagate_slab_attrs(s);
        err = sysfs_slab_add(s);
        if (err)
-               kmem_cache_close(s);
+               __kmem_cache_release(s);
 
        return err;
 }
index d5871ac493eb10c984b9e74f2beee3049bc79645..f066781be3c856b8ae192c6b74d614597297a872 100644 (file)
@@ -1625,7 +1625,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 
                rt = atrtr_find(&at_hint);
        }
-       err = ENETUNREACH;
+       err = -ENETUNREACH;
        if (!rt)
                goto out;
 
index e6c8382c79ba86dfea5078a37f692f74ebffb01c..ccf70bed0d0cc0c8636d21ba7f8508bbbf9cd4e7 100644 (file)
@@ -527,11 +527,12 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
                 * gets dereferenced.
                 */
                spin_lock_bh(&bat_priv->gw.list_lock);
-               hlist_del_init_rcu(&gw_node->list);
+               if (!hlist_unhashed(&gw_node->list)) {
+                       hlist_del_init_rcu(&gw_node->list);
+                       batadv_gw_node_free_ref(gw_node);
+               }
                spin_unlock_bh(&bat_priv->gw.list_lock);
 
-               batadv_gw_node_free_ref(gw_node);
-
                curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
                if (gw_node == curr_gw)
                        batadv_gw_reselect(bat_priv);
index 01acccc4d2185806ae6dd37b2f0f091d9a0b92a0..57f7107169f58c5e772887a6260d070b1eb9fc1e 100644 (file)
@@ -75,6 +75,28 @@ out:
        return hard_iface;
 }
 
+/**
+ * batadv_mutual_parents - check if two devices are each others parent
+ * @dev1: 1st net_device
+ * @dev2: 2nd net_device
+ *
+ * veth devices come in pairs and each is the parent of the other!
+ *
+ * Return: true if the devices are each others parent, otherwise false
+ */
+static bool batadv_mutual_parents(const struct net_device *dev1,
+                                 const struct net_device *dev2)
+{
+       int dev1_parent_iflink = dev_get_iflink(dev1);
+       int dev2_parent_iflink = dev_get_iflink(dev2);
+
+       if (!dev1_parent_iflink || !dev2_parent_iflink)
+               return false;
+
+       return (dev1_parent_iflink == dev2->ifindex) &&
+              (dev2_parent_iflink == dev1->ifindex);
+}
+
 /**
  * batadv_is_on_batman_iface - check if a device is a batman iface descendant
  * @net_dev: the device to check
@@ -108,6 +130,9 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
        if (WARN(!parent_dev, "Cannot find parent device"))
                return false;
 
+       if (batadv_mutual_parents(net_dev, parent_dev))
+               return false;
+
        ret = batadv_is_on_batman_iface(parent_dev);
 
        return ret;
index cdfc85fa2743c78d4e0e3e269085ec5d6f1fb22f..0e80fd1461ab9062fed09a11373ea0f9a2817752 100644 (file)
@@ -303,9 +303,11 @@ static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
 
        if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
                spin_lock_bh(&orig_node->vlan_list_lock);
-               hlist_del_init_rcu(&vlan->list);
+               if (!hlist_unhashed(&vlan->list)) {
+                       hlist_del_init_rcu(&vlan->list);
+                       batadv_orig_node_vlan_free_ref(vlan);
+               }
                spin_unlock_bh(&orig_node->vlan_list_lock);
-               batadv_orig_node_vlan_free_ref(vlan);
        }
 
        batadv_orig_node_vlan_free_ref(vlan);
index 47bcef7547967ce544ff0cf5ea7dabecdd080d90..883c821a9e784851a89c00e3874b7d9da9628a69 100644 (file)
@@ -4112,8 +4112,10 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
                        break;
                }
 
-               *req_complete = bt_cb(skb)->hci.req_complete;
-               *req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
+               if (bt_cb(skb)->hci.req_flags & HCI_REQ_SKB)
+                       *req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
+               else
+                       *req_complete = bt_cb(skb)->hci.req_complete;
                kfree_skb(skb);
        }
        spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
index 30e105f57f0d9a59e1ce03de8531b90718ac8e29..74c278e0022545729641c5741bbd3d07cd6b36b5 100644 (file)
@@ -425,8 +425,8 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
        mp = br_mdb_ip_get(mdb, group);
        if (!mp) {
                mp = br_multicast_new_group(br, port, group);
-               err = PTR_ERR(mp);
-               if (IS_ERR(mp))
+               err = PTR_ERR_OR_ZERO(mp);
+               if (err)
                        return err;
        }
 
index 61d7617d924912347325a5db483172794e6df33a..b82440e1fcb4f3fe8a25e121416360cc23f8fada 100644 (file)
@@ -159,7 +159,7 @@ static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt)
                tmppkt = NULL;
 
                /* Verify that length is correct */
-               err = EPROTO;
+               err = -EPROTO;
                if (rfml->pdu_size != cfpkt_getlen(pkt) - RFM_HEAD_SIZE + 1)
                        goto out;
        }
index 9cfedf565f5b236b5ede7974466cf62af6ad995c..9382619a405b8da854c82b041a137a670399567f 100644 (file)
@@ -1197,6 +1197,13 @@ static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor,
        return new_piece;
 }
 
+static size_t sizeof_footer(struct ceph_connection *con)
+{
+       return (con->peer_features & CEPH_FEATURE_MSG_AUTH) ?
+           sizeof(struct ceph_msg_footer) :
+           sizeof(struct ceph_msg_footer_old);
+}
+
 static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
 {
        BUG_ON(!msg);
@@ -2335,9 +2342,9 @@ static int read_partial_message(struct ceph_connection *con)
                        ceph_pr_addr(&con->peer_addr.in_addr),
                        seq, con->in_seq + 1);
                con->in_base_pos = -front_len - middle_len - data_len -
-                       sizeof(m->footer);
+                       sizeof_footer(con);
                con->in_tag = CEPH_MSGR_TAG_READY;
-               return 0;
+               return 1;
        } else if ((s64)seq - (s64)con->in_seq > 1) {
                pr_err("read_partial_message bad seq %lld expected %lld\n",
                       seq, con->in_seq + 1);
@@ -2360,10 +2367,10 @@ static int read_partial_message(struct ceph_connection *con)
                        /* skip this message */
                        dout("alloc_msg said skip message\n");
                        con->in_base_pos = -front_len - middle_len - data_len -
-                               sizeof(m->footer);
+                               sizeof_footer(con);
                        con->in_tag = CEPH_MSGR_TAG_READY;
                        con->in_seq++;
-                       return 0;
+                       return 1;
                }
 
                BUG_ON(!con->in_msg);
index 3534e12683d3b2b6efa9988faff9e9b3249e6fa6..5bc053778feddd0e35fe73480317be25345da61c 100644 (file)
@@ -2853,8 +2853,8 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
        mutex_lock(&osdc->request_mutex);
        req = __lookup_request(osdc, tid);
        if (!req) {
-               pr_warn("%s osd%d tid %llu unknown, skipping\n",
-                       __func__, osd->o_osd, tid);
+               dout("%s osd%d tid %llu unknown, skipping\n", __func__,
+                    osd->o_osd, tid);
                m = NULL;
                *skip = 1;
                goto out;
index 8cba3d852f251c503b193823b71b27aaef3fb3ae..0ef061b2badcd1334d2146735c30e32b7b39998c 100644 (file)
@@ -5379,12 +5379,12 @@ void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
 {
        struct netdev_adjacent *lower;
 
-       lower = list_entry((*iter)->next, struct netdev_adjacent, list);
+       lower = list_entry(*iter, struct netdev_adjacent, list);
 
        if (&lower->list == &dev->adj_list.lower)
                return NULL;
 
-       *iter = &lower->list;
+       *iter = lower->list.next;
 
        return lower->dev;
 }
@@ -7422,8 +7422,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
        setup(dev);
 
-       if (!dev->tx_queue_len)
+       if (!dev->tx_queue_len) {
                dev->priv_flags |= IFF_NO_QUEUE;
+               dev->tx_queue_len = 1;
+       }
 
        dev->num_tx_queues = txqs;
        dev->real_num_tx_queues = txqs;
index d79699c9d1b9eb9f250254e360b2d5a7b4ff6e34..12e7003320107dbb2b86f4fa1cfd20a8d59e8ed5 100644 (file)
@@ -208,7 +208,6 @@ ip:
        case htons(ETH_P_IPV6): {
                const struct ipv6hdr *iph;
                struct ipv6hdr _iph;
-               __be32 flow_label;
 
 ipv6:
                iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
@@ -230,8 +229,12 @@ ipv6:
                        key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
                }
 
-               flow_label = ip6_flowlabel(iph);
-               if (flow_label) {
+               if ((dissector_uses_key(flow_dissector,
+                                       FLOW_DISSECTOR_KEY_FLOW_LABEL) ||
+                    (flags & FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)) &&
+                   ip6_flowlabel(iph)) {
+                       __be32 flow_label = ip6_flowlabel(iph);
+
                        if (dissector_uses_key(flow_dissector,
                                               FLOW_DISSECTOR_KEY_FLOW_LABEL)) {
                                key_tags = skb_flow_dissector_target(flow_dissector,
@@ -396,6 +399,13 @@ ip_proto_again:
                                goto out_bad;
                        proto = eth->h_proto;
                        nhoff += sizeof(*eth);
+
+                       /* Cap headers that we access via pointers at the
+                        * end of the Ethernet header as our maximum alignment
+                        * at that point is only 2 bytes.
+                        */
+                       if (NET_IP_ALIGN)
+                               hlen = nhoff;
                }
 
                key_control->flags |= FLOW_DIS_ENCAPSULATION;
index 14596fb3717270d62fa70544b7ec2496de96e1ce..2696aefdc148887138d46f98dc0a678ce2699512 100644 (file)
@@ -87,6 +87,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
                *fplp = fpl;
                fpl->count = 0;
                fpl->max = SCM_MAX_FD;
+               fpl->user = NULL;
        }
        fpp = &fpl->fp[fpl->count];
 
@@ -107,6 +108,10 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
                *fpp++ = file;
                fpl->count++;
        }
+
+       if (!fpl->user)
+               fpl->user = get_uid(current_user());
+
        return num;
 }
 
@@ -119,6 +124,7 @@ void __scm_destroy(struct scm_cookie *scm)
                scm->fp = NULL;
                for (i=fpl->count-1; i>=0; i--)
                        fput(fpl->fp[i]);
+               free_uid(fpl->user);
                kfree(fpl);
        }
 }
@@ -336,6 +342,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
                for (i = 0; i < fpl->count; i++)
                        get_file(fpl->fp[i]);
                new_fpl->max = new_fpl->count;
+               new_fpl->user = get_uid(fpl->user);
        }
        return new_fpl;
 }
index b2df375ec9c2173a8132b8efa1c3062f0510284b..5bf88f58bee7405ff65f80487a64339b92a91bcb 100644 (file)
@@ -79,6 +79,8 @@
 
 struct kmem_cache *skbuff_head_cache __read_mostly;
 static struct kmem_cache *skbuff_fclone_cache __read_mostly;
+int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
+EXPORT_SYMBOL(sysctl_max_skb_frags);
 
 /**
  *     skb_panic - private function for out-of-line support
index 95b6139d710c46825d1e43f825188d81fcb70f60..a6beb7b6ae556dff501413d6661d9c4655502e36 100644 (file)
@@ -26,6 +26,7 @@ static int zero = 0;
 static int one = 1;
 static int min_sndbuf = SOCK_MIN_SNDBUF;
 static int min_rcvbuf = SOCK_MIN_RCVBUF;
+static int max_skb_frags = MAX_SKB_FRAGS;
 
 static int net_msg_warn;       /* Unused, but still a sysctl */
 
@@ -392,6 +393,15 @@ static struct ctl_table net_core_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
+       {
+               .procname       = "max_skb_frags",
+               .data           = &sysctl_max_skb_frags,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &one,
+               .extra2         = &max_skb_frags,
+       },
        { }
 };
 
index 5684e14932bd47e97b9d547307bfc50230e7be7d..902d606324a04ff81adbdc301a1ed58baa3f61f9 100644 (file)
@@ -824,26 +824,26 @@ lookup:
 
        if (sk->sk_state == DCCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
-               struct sock *nsk = NULL;
+               struct sock *nsk;
 
                sk = req->rsk_listener;
-               if (likely(sk->sk_state == DCCP_LISTEN)) {
-                       nsk = dccp_check_req(sk, skb, req);
-               } else {
+               if (unlikely(sk->sk_state != DCCP_LISTEN)) {
                        inet_csk_reqsk_queue_drop_and_put(sk, req);
                        goto lookup;
                }
+               sock_hold(sk);
+               nsk = dccp_check_req(sk, skb, req);
                if (!nsk) {
                        reqsk_put(req);
-                       goto discard_it;
+                       goto discard_and_relse;
                }
                if (nsk == sk) {
-                       sock_hold(sk);
                        reqsk_put(req);
                } else if (dccp_child_process(sk, nsk, skb)) {
                        dccp_v4_ctl_send_reset(sk, skb);
-                       goto discard_it;
+                       goto discard_and_relse;
                } else {
+                       sock_put(sk);
                        return 0;
                }
        }
index 9c6d0508e63a2ab7f13105cd91ea8c027c4a7557..b8608b71a66d34894722c17121754c403c74d946 100644 (file)
@@ -691,26 +691,26 @@ lookup:
 
        if (sk->sk_state == DCCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
-               struct sock *nsk = NULL;
+               struct sock *nsk;
 
                sk = req->rsk_listener;
-               if (likely(sk->sk_state == DCCP_LISTEN)) {
-                       nsk = dccp_check_req(sk, skb, req);
-               } else {
+               if (unlikely(sk->sk_state != DCCP_LISTEN)) {
                        inet_csk_reqsk_queue_drop_and_put(sk, req);
                        goto lookup;
                }
+               sock_hold(sk);
+               nsk = dccp_check_req(sk, skb, req);
                if (!nsk) {
                        reqsk_put(req);
-                       goto discard_it;
+                       goto discard_and_relse;
                }
                if (nsk == sk) {
-                       sock_hold(sk);
                        reqsk_put(req);
                } else if (dccp_child_process(sk, nsk, skb)) {
                        dccp_v6_ctl_send_reset(sk, skb);
-                       goto discard_it;
+                       goto discard_and_relse;
                } else {
+                       sock_put(sk);
                        return 0;
                }
        }
index 40b9ca72aae3da05c924b2d7adaa0825acfd398d..ab24521beb4d52ceb4bf09e846983954d54a67f0 100644 (file)
@@ -1194,7 +1194,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        if (ret) {
                netdev_err(master, "error %d registering interface %s\n",
                           ret, slave_dev->name);
-               phy_disconnect(p->phy);
                ds->ports[port] = NULL;
                free_netdev(slave_dev);
                return ret;
@@ -1205,6 +1204,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        ret = dsa_slave_phy_setup(p, slave_dev);
        if (ret) {
                netdev_err(master, "error %d setting up slave phy\n", ret);
+               unregister_netdev(slave_dev);
                free_netdev(slave_dev);
                return ret;
        }
index cebd9d31e65a4a7539cab0bef71887736bc188f7..f6303b17546b3535d035b7f662cf43e2b2d59280 100644 (file)
@@ -1847,7 +1847,7 @@ static int inet_netconf_get_devconf(struct sk_buff *in_skb,
        if (err < 0)
                goto errout;
 
-       err = EINVAL;
+       err = -EINVAL;
        if (!tb[NETCONFA_IFINDEX])
                goto errout;
 
index 46b9c887bede0568ec378d3b809dda8fa463a166..64148914803a8443ecc0de2a45c141ae72cc0258 100644 (file)
@@ -789,14 +789,16 @@ static void inet_child_forget(struct sock *sk, struct request_sock *req,
        reqsk_put(req);
 }
 
-void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req,
-                             struct sock *child)
+struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
+                                     struct request_sock *req,
+                                     struct sock *child)
 {
        struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
 
        spin_lock(&queue->rskq_lock);
        if (unlikely(sk->sk_state != TCP_LISTEN)) {
                inet_child_forget(sk, req, child);
+               child = NULL;
        } else {
                req->sk = child;
                req->dl_next = NULL;
@@ -808,6 +810,7 @@ void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req,
                sk_acceptq_added(sk);
        }
        spin_unlock(&queue->rskq_lock);
+       return child;
 }
 EXPORT_SYMBOL(inet_csk_reqsk_queue_add);
 
@@ -817,11 +820,8 @@ struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child,
        if (own_req) {
                inet_csk_reqsk_queue_drop(sk, req);
                reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
-               inet_csk_reqsk_queue_add(sk, req, child);
-               /* Warning: caller must not call reqsk_put(req);
-                * child stole last reference on it.
-                */
-               return child;
+               if (inet_csk_reqsk_queue_add(sk, req, child))
+                       return child;
        }
        /* Too bad, another child took ownership of the request, undo. */
        bh_unlock_sock(child);
index 7c51c4e1661f9aafc63829cf58b3b5ec28ed859e..41ba68de46d890c8fabc490bb07e7d45c26b7ed6 100644 (file)
@@ -1054,8 +1054,9 @@ static const struct net_device_ops gre_tap_netdev_ops = {
 static void ipgre_tap_setup(struct net_device *dev)
 {
        ether_setup(dev);
-       dev->netdev_ops         = &gre_tap_netdev_ops;
-       dev->priv_flags         |= IFF_LIVE_ADDR_CHANGE;
+       dev->netdev_ops = &gre_tap_netdev_ops;
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
        ip_tunnel_setup(dev, gre_tap_net_id);
 }
 
@@ -1240,6 +1241,14 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
        err = ipgre_newlink(net, dev, tb, NULL);
        if (err < 0)
                goto out;
+
+       /* openvswitch users expect packet sizes to be unrestricted,
+        * so set the largest MTU we can.
+        */
+       err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
+       if (err)
+               goto out;
+
        return dev;
 out:
        free_netdev(dev);
index 5f73a7c03e27d334c771f144825c4a2f718d71ba..a50124260f5a4aaa98a3e4a582dbcbdbc236e370 100644 (file)
@@ -249,6 +249,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
                switch (cmsg->cmsg_type) {
                case IP_RETOPTS:
                        err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+
+                       /* Our caller is responsible for freeing ipc->opt */
                        err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg),
                                             err < 40 ? err : 40);
                        if (err)
index c7bd72e9b544848d10a490b010e0a30c4d5e4c21..89e8861e05fcb1d371c371c1784b89499b69d9df 100644 (file)
@@ -943,17 +943,31 @@ done:
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
 
-int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+       int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
 
-       if (new_mtu < 68 ||
-           new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
+       if (new_mtu < 68)
                return -EINVAL;
+
+       if (new_mtu > max_mtu) {
+               if (strict)
+                       return -EINVAL;
+
+               new_mtu = max_mtu;
+       }
+
        dev->mtu = new_mtu;
        return 0;
 }
+EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
+
+int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+{
+       return __ip_tunnel_change_mtu(dev, new_mtu, true);
+}
 EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
 
 static void ip_tunnel_dev_free(struct net_device *dev)
index c117b21b937de778dffa484d589141ea31e1b6bc..d3a27165f9cca0f20f68616295cfbf683fb4adc0 100644 (file)
@@ -746,8 +746,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sock_net(sk), msg, &ipc, false);
-               if (err)
+               if (unlikely(err)) {
+                       kfree(ipc.opt);
                        return err;
+               }
                if (ipc.opt)
                        free = 1;
        }
index bc35f1842512bef8e4d87e76542d7bf11f8946fa..7113bae4e6a0c02726e0e11c33415b6779b7d04b 100644 (file)
@@ -547,8 +547,10 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        if (msg->msg_controllen) {
                err = ip_cmsg_send(net, msg, &ipc, false);
-               if (err)
+               if (unlikely(err)) {
+                       kfree(ipc.opt);
                        goto out;
+               }
                if (ipc.opt)
                        free = 1;
        }
index 85f184e429c63c8c426f58c779dc3544cf2e2a54..02c62299d717b9f6c38a5227e3b3ae376e0015b6 100644 (file)
@@ -129,6 +129,7 @@ static int ip_rt_mtu_expires __read_mostly  = 10 * 60 * HZ;
 static int ip_rt_min_pmtu __read_mostly                = 512 + 20 + 20;
 static int ip_rt_min_advmss __read_mostly      = 256;
 
+static int ip_rt_gc_timeout __read_mostly      = RT_GC_TIMEOUT;
 /*
  *     Interface to generic destination cache.
  */
@@ -755,7 +756,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
                                struct fib_nh *nh = &FIB_RES_NH(res);
 
                                update_or_create_fnhe(nh, fl4->daddr, new_gw,
-                                                     0, 0);
+                                               0, jiffies + ip_rt_gc_timeout);
                        }
                        if (kill_route)
                                rt->dst.obsolete = DST_OBSOLETE_KILL;
@@ -1556,6 +1557,36 @@ static void ip_handle_martian_source(struct net_device *dev,
 #endif
 }
 
+static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
+{
+       struct fnhe_hash_bucket *hash;
+       struct fib_nh_exception *fnhe, __rcu **fnhe_p;
+       u32 hval = fnhe_hashfun(daddr);
+
+       spin_lock_bh(&fnhe_lock);
+
+       hash = rcu_dereference_protected(nh->nh_exceptions,
+                                        lockdep_is_held(&fnhe_lock));
+       hash += hval;
+
+       fnhe_p = &hash->chain;
+       fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock));
+       while (fnhe) {
+               if (fnhe->fnhe_daddr == daddr) {
+                       rcu_assign_pointer(*fnhe_p, rcu_dereference_protected(
+                               fnhe->fnhe_next, lockdep_is_held(&fnhe_lock)));
+                       fnhe_flush_routes(fnhe);
+                       kfree_rcu(fnhe, rcu);
+                       break;
+               }
+               fnhe_p = &fnhe->fnhe_next;
+               fnhe = rcu_dereference_protected(fnhe->fnhe_next,
+                                                lockdep_is_held(&fnhe_lock));
+       }
+
+       spin_unlock_bh(&fnhe_lock);
+}
+
 /* called in rcu_read_lock() section */
 static int __mkroute_input(struct sk_buff *skb,
                           const struct fib_result *res,
@@ -1609,11 +1640,20 @@ static int __mkroute_input(struct sk_buff *skb,
 
        fnhe = find_exception(&FIB_RES_NH(*res), daddr);
        if (do_cache) {
-               if (fnhe)
+               if (fnhe) {
                        rth = rcu_dereference(fnhe->fnhe_rth_input);
-               else
-                       rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+                       if (rth && rth->dst.expires &&
+                           time_after(jiffies, rth->dst.expires)) {
+                               ip_del_fnhe(&FIB_RES_NH(*res), daddr);
+                               fnhe = NULL;
+                       } else {
+                               goto rt_cache;
+                       }
+               }
+
+               rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
 
+rt_cache:
                if (rt_cache_valid(rth)) {
                        skb_dst_set_noref(skb, &rth->dst);
                        goto out;
@@ -2014,19 +2054,29 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
                struct fib_nh *nh = &FIB_RES_NH(*res);
 
                fnhe = find_exception(nh, fl4->daddr);
-               if (fnhe)
+               if (fnhe) {
                        prth = &fnhe->fnhe_rth_output;
-               else {
-                       if (unlikely(fl4->flowi4_flags &
-                                    FLOWI_FLAG_KNOWN_NH &&
-                                    !(nh->nh_gw &&
-                                      nh->nh_scope == RT_SCOPE_LINK))) {
-                               do_cache = false;
-                               goto add;
+                       rth = rcu_dereference(*prth);
+                       if (rth && rth->dst.expires &&
+                           time_after(jiffies, rth->dst.expires)) {
+                               ip_del_fnhe(nh, fl4->daddr);
+                               fnhe = NULL;
+                       } else {
+                               goto rt_cache;
                        }
-                       prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
                }
+
+               if (unlikely(fl4->flowi4_flags &
+                            FLOWI_FLAG_KNOWN_NH &&
+                            !(nh->nh_gw &&
+                              nh->nh_scope == RT_SCOPE_LINK))) {
+                       do_cache = false;
+                       goto add;
+               }
+               prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
                rth = rcu_dereference(*prth);
+
+rt_cache:
                if (rt_cache_valid(rth)) {
                        dst_hold(&rth->dst);
                        return rth;
@@ -2569,7 +2619,6 @@ void ip_rt_multicast_event(struct in_device *in_dev)
 }
 
 #ifdef CONFIG_SYSCTL
-static int ip_rt_gc_timeout __read_mostly      = RT_GC_TIMEOUT;
 static int ip_rt_gc_interval __read_mostly  = 60 * HZ;
 static int ip_rt_gc_min_interval __read_mostly = HZ / 2;
 static int ip_rt_gc_elasticity __read_mostly   = 8;
index 19746b3fcbbe68db18d774c1f0178e2e5a418952..483ffdf5aa4dd4ad41809ef73ca2ec815df131c7 100644 (file)
@@ -940,7 +940,7 @@ new_segment:
 
                i = skb_shinfo(skb)->nr_frags;
                can_coalesce = skb_can_coalesce(skb, i, page, offset);
-               if (!can_coalesce && i >= MAX_SKB_FRAGS) {
+               if (!can_coalesce && i >= sysctl_max_skb_frags) {
                        tcp_mark_push(tp, skb);
                        goto new_segment;
                }
@@ -1213,7 +1213,7 @@ new_segment:
 
                        if (!skb_can_coalesce(skb, i, pfrag->page,
                                              pfrag->offset)) {
-                               if (i == MAX_SKB_FRAGS || !sg) {
+                               if (i == sysctl_max_skb_frags || !sg) {
                                        tcp_mark_push(tp, skb);
                                        goto new_segment;
                                }
@@ -2950,7 +2950,7 @@ static void __tcp_alloc_md5sig_pool(void)
                        struct crypto_hash *hash;
 
                        hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
-                       if (IS_ERR_OR_NULL(hash))
+                       if (IS_ERR(hash))
                                return;
                        per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash;
                }
index 1c2a73406261921fbea84333eabe3867106f980a..3b2c8e90a475d91bc30ca5fd8b75f23285eac07d 100644 (file)
@@ -2896,7 +2896,10 @@ static void tcp_update_rtt_min(struct sock *sk, u32 rtt_us)
 {
        const u32 now = tcp_time_stamp, wlen = sysctl_tcp_min_rtt_wlen * HZ;
        struct rtt_meas *m = tcp_sk(sk)->rtt_min;
-       struct rtt_meas rttm = { .rtt = (rtt_us ? : 1), .ts = now };
+       struct rtt_meas rttm = {
+               .rtt = likely(rtt_us) ? rtt_us : jiffies_to_usecs(1),
+               .ts = now,
+       };
        u32 elapsed;
 
        /* Check if the new measurement updates the 1st, 2nd, or 3rd choices */
index a4d523709ab30a2171edf76b296d3f8e01fef7e4..487ac67059e237bab05d2291dd8e0a82f26e2bb0 100644 (file)
@@ -311,7 +311,7 @@ static void do_redirect(struct sk_buff *skb, struct sock *sk)
 
 
 /* handle ICMP messages on TCP_NEW_SYN_RECV request sockets */
-void tcp_req_err(struct sock *sk, u32 seq)
+void tcp_req_err(struct sock *sk, u32 seq, bool abort)
 {
        struct request_sock *req = inet_reqsk(sk);
        struct net *net = sock_net(sk);
@@ -323,7 +323,7 @@ void tcp_req_err(struct sock *sk, u32 seq)
 
        if (seq != tcp_rsk(req)->snt_isn) {
                NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
-       } else {
+       } else if (abort) {
                /*
                 * Still in SYN_RECV, just remove it silently.
                 * There is no good way to pass the error to the newly
@@ -383,7 +383,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
        }
        seq = ntohl(th->seq);
        if (sk->sk_state == TCP_NEW_SYN_RECV)
-               return tcp_req_err(sk, seq);
+               return tcp_req_err(sk, seq,
+                                 type == ICMP_PARAMETERPROB ||
+                                 type == ICMP_TIME_EXCEEDED ||
+                                 (type == ICMP_DEST_UNREACH &&
+                                  (code == ICMP_NET_UNREACH ||
+                                   code == ICMP_HOST_UNREACH)));
 
        bh_lock_sock(sk);
        /* If too many ICMPs get dropped on busy
@@ -1592,28 +1597,30 @@ process:
 
        if (sk->sk_state == TCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
-               struct sock *nsk = NULL;
+               struct sock *nsk;
 
                sk = req->rsk_listener;
-               if (tcp_v4_inbound_md5_hash(sk, skb))
-                       goto discard_and_relse;
-               if (likely(sk->sk_state == TCP_LISTEN)) {
-                       nsk = tcp_check_req(sk, skb, req, false);
-               } else {
+               if (unlikely(tcp_v4_inbound_md5_hash(sk, skb))) {
+                       reqsk_put(req);
+                       goto discard_it;
+               }
+               if (unlikely(sk->sk_state != TCP_LISTEN)) {
                        inet_csk_reqsk_queue_drop_and_put(sk, req);
                        goto lookup;
                }
+               sock_hold(sk);
+               nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
-                       goto discard_it;
+                       goto discard_and_relse;
                }
                if (nsk == sk) {
-                       sock_hold(sk);
                        reqsk_put(req);
                } else if (tcp_child_process(sk, nsk, skb)) {
                        tcp_v4_send_reset(nsk, skb);
-                       goto discard_it;
+                       goto discard_and_relse;
                } else {
+                       sock_put(sk);
                        return 0;
                }
        }
index be0b21852b138ebc5eed9caf37740cbe1cb1abe0..95d2f198017ef1a6db687ddfe405a13830a37f3f 100644 (file)
@@ -1048,8 +1048,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sock_net(sk), msg, &ipc,
                                   sk->sk_family == AF_INET6);
-               if (err)
+               if (unlikely(err)) {
+                       kfree(ipc.opt);
                        return err;
+               }
                if (ipc.opt)
                        free = 1;
                connected = 0;
index 38eeddedfc21baa843b315d720cc94a28b6af605..bdd7eac4307a0802fb767e843c92dd81aa730d3a 100644 (file)
@@ -583,7 +583,7 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
        if (err < 0)
                goto errout;
 
-       err = EINVAL;
+       err = -EINVAL;
        if (!tb[NETCONFA_IFINDEX])
                goto errout;
 
@@ -3538,6 +3538,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
 {
        struct inet6_dev *idev = ifp->idev;
        struct net_device *dev = idev->dev;
+       bool notify = false;
 
        addrconf_join_solict(dev, &ifp->addr);
 
@@ -3583,7 +3584,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
                        /* Because optimistic nodes can use this address,
                         * notify listeners. If DAD fails, RTM_DELADDR is sent.
                         */
-                       ipv6_ifa_notify(RTM_NEWADDR, ifp);
+                       notify = true;
                }
        }
 
@@ -3591,6 +3592,8 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
 out:
        spin_unlock(&ifp->lock);
        read_unlock_bh(&idev->lock);
+       if (notify)
+               ipv6_ifa_notify(RTM_NEWADDR, ifp);
 }
 
 static void addrconf_dad_start(struct inet6_ifaddr *ifp)
index 1f9ebe3cbb4ac042edd0b05754d1fc03cdfe73cd..dc2db4f7b182c4ebc1a8a51487a3d2e893955df9 100644 (file)
@@ -540,12 +540,13 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                }
                spin_lock_bh(&ip6_sk_fl_lock);
                for (sflp = &np->ipv6_fl_list;
-                    (sfl = rcu_dereference(*sflp)) != NULL;
+                    (sfl = rcu_dereference_protected(*sflp,
+                                                     lockdep_is_held(&ip6_sk_fl_lock))) != NULL;
                     sflp = &sfl->next) {
                        if (sfl->fl->label == freq.flr_label) {
                                if (freq.flr_label == (np->flow_label&IPV6_FLOWLABEL_MASK))
                                        np->flow_label &= ~IPV6_FLOWLABEL_MASK;
-                               *sflp = rcu_dereference(sfl->next);
+                               *sflp = sfl->next;
                                spin_unlock_bh(&ip6_sk_fl_lock);
                                fl_release(sfl->fl);
                                kfree_rcu(sfl, rcu);
index f37f18b6b40c9547e24902f4af88bdf6f154f394..a69aad1e29d1ebb2429650cc083f0e4dd2bcaf86 100644 (file)
@@ -1512,6 +1512,7 @@ static void ip6gre_tap_setup(struct net_device *dev)
        dev->destructor = ip6gre_dev_free;
 
        dev->features |= NETIF_F_NETNS_LOCAL;
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 }
 
 static int ip6gre_newlink(struct net *src_net, struct net_device *dev,
index 31ba7ca19757083a1a83f8388b87be5695b1ba98..051b6a6bfff6ca7c0dd42ceb43a417260a11bd23 100644 (file)
 #include <net/ipv6.h>
 #include <net/netfilter/ipv6/nf_nat_masquerade.h>
 
+#define MAX_WORK_COUNT 16
+
+static atomic_t v6_worker_count;
+
 unsigned int
 nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
                       const struct net_device *out)
@@ -78,14 +82,78 @@ static struct notifier_block masq_dev_notifier = {
        .notifier_call  = masq_device_event,
 };
 
+struct masq_dev_work {
+       struct work_struct work;
+       struct net *net;
+       int ifindex;
+};
+
+static void iterate_cleanup_work(struct work_struct *work)
+{
+       struct masq_dev_work *w;
+       long index;
+
+       w = container_of(work, struct masq_dev_work, work);
+
+       index = w->ifindex;
+       nf_ct_iterate_cleanup(w->net, device_cmp, (void *)index, 0, 0);
+
+       put_net(w->net);
+       kfree(w);
+       atomic_dec(&v6_worker_count);
+       module_put(THIS_MODULE);
+}
+
+/* ipv6 inet notifier is an atomic notifier, i.e. we cannot
+ * schedule.
+ *
+ * Unfortunately, nf_ct_iterate_cleanup can run for a long
+ * time if there are lots of conntracks and the system
+ * handles high softirq load, so it frequently calls cond_resched
+ * while iterating the conntrack table.
+ *
+ * So we defer nf_ct_iterate_cleanup walk to the system workqueue.
+ *
+ * As we can have 'a lot' of inet_events (depending on amount
+ * of ipv6 addresses being deleted), we also need to add an upper
+ * limit to the number of queued work items.
+ */
 static int masq_inet_event(struct notifier_block *this,
                           unsigned long event, void *ptr)
 {
        struct inet6_ifaddr *ifa = ptr;
-       struct netdev_notifier_info info;
+       const struct net_device *dev;
+       struct masq_dev_work *w;
+       struct net *net;
+
+       if (event != NETDEV_DOWN ||
+           atomic_read(&v6_worker_count) >= MAX_WORK_COUNT)
+               return NOTIFY_DONE;
+
+       dev = ifa->idev->dev;
+       net = maybe_get_net(dev_net(dev));
+       if (!net)
+               return NOTIFY_DONE;
 
-       netdev_notifier_info_init(&info, ifa->idev->dev);
-       return masq_device_event(this, event, &info);
+       if (!try_module_get(THIS_MODULE))
+               goto err_module;
+
+       w = kmalloc(sizeof(*w), GFP_ATOMIC);
+       if (w) {
+               atomic_inc(&v6_worker_count);
+
+               INIT_WORK(&w->work, iterate_cleanup_work);
+               w->ifindex = dev->ifindex;
+               w->net = net;
+               schedule_work(&w->work);
+
+               return NOTIFY_DONE;
+       }
+
+       module_put(THIS_MODULE);
+ err_module:
+       put_net(net);
+       return NOTIFY_DONE;
 }
 
 static struct notifier_block masq_inet_notifier = {
index 006396e31cb0dcedf359c5aaa068ab3d28f7501c..5c8c842730286ea4212222769d124f9e3d611333 100644 (file)
@@ -327,6 +327,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct tcp_sock *tp;
        __u32 seq, snd_una;
        struct sock *sk;
+       bool fatal;
        int err;
 
        sk = __inet6_lookup_established(net, &tcp_hashinfo,
@@ -345,8 +346,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return;
        }
        seq = ntohl(th->seq);
+       fatal = icmpv6_err_convert(type, code, &err);
        if (sk->sk_state == TCP_NEW_SYN_RECV)
-               return tcp_req_err(sk, seq);
+               return tcp_req_err(sk, seq, fatal);
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG)
@@ -400,7 +402,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                goto out;
        }
 
-       icmpv6_err_convert(type, code, &err);
 
        /* Might be for an request_sock */
        switch (sk->sk_state) {
@@ -1386,7 +1387,7 @@ process:
 
        if (sk->sk_state == TCP_NEW_SYN_RECV) {
                struct request_sock *req = inet_reqsk(sk);
-               struct sock *nsk = NULL;
+               struct sock *nsk;
 
                sk = req->rsk_listener;
                tcp_v6_fill_cb(skb, hdr, th);
@@ -1394,24 +1395,24 @@ process:
                        reqsk_put(req);
                        goto discard_it;
                }
-               if (likely(sk->sk_state == TCP_LISTEN)) {
-                       nsk = tcp_check_req(sk, skb, req, false);
-               } else {
+               if (unlikely(sk->sk_state != TCP_LISTEN)) {
                        inet_csk_reqsk_queue_drop_and_put(sk, req);
                        goto lookup;
                }
+               sock_hold(sk);
+               nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
-                       goto discard_it;
+                       goto discard_and_relse;
                }
                if (nsk == sk) {
-                       sock_hold(sk);
                        reqsk_put(req);
                        tcp_v6_restore_cb(skb);
                } else if (tcp_child_process(sk, nsk, skb)) {
                        tcp_v6_send_reset(nsk, skb);
-                       goto discard_it;
+                       goto discard_and_relse;
                } else {
+                       sock_put(sk);
                        return 0;
                }
        }
index f93c5be612a7cb43611708ebb66c25b4db0d27cf..2caaa84ce92dac811c7813ebbb233c9596d03ca0 100644 (file)
@@ -124,8 +124,13 @@ static int l2tp_tunnel_notify(struct genl_family *family,
        ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq,
                                  NLM_F_ACK, tunnel, cmd);
 
-       if (ret >= 0)
-               return genlmsg_multicast_allns(family, msg, 0,  0, GFP_ATOMIC);
+       if (ret >= 0) {
+               ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
+               /* We don't care if no one is listening */
+               if (ret == -ESRCH)
+                       ret = 0;
+               return ret;
+       }
 
        nlmsg_free(msg);
 
@@ -147,8 +152,13 @@ static int l2tp_session_notify(struct genl_family *family,
        ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
                                   NLM_F_ACK, session, cmd);
 
-       if (ret >= 0)
-               return genlmsg_multicast_allns(family, msg, 0,  0, GFP_ATOMIC);
+       if (ret >= 0) {
+               ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
+               /* We don't care if no one is listening */
+               if (ret == -ESRCH)
+                       ret = 0;
+               return ret;
+       }
 
        nlmsg_free(msg);
 
index 8c067e6663a14adf43212eda165c33240bb87985..95e757c377f9598429f136ebd3c951f1bb9da11b 100644 (file)
@@ -891,7 +891,7 @@ config NETFILTER_XT_TARGET_TEE
        depends on IPV6 || IPV6=n
        depends on !NF_CONNTRACK || NF_CONNTRACK
        select NF_DUP_IPV4
-       select NF_DUP_IPV6 if IP6_NF_IPTABLES != n
+       select NF_DUP_IPV6 if IPV6
        ---help---
        This option adds a "TEE" target with which a packet can be cloned and
        this clone be rerouted to another nexthop.
index 58882de06bd74f254033e0f06521f264c18c8d44..f60b4fdeeb8cc4fc600506ecc58e2bdc4cad1654 100644 (file)
@@ -1412,6 +1412,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
                }
                spin_unlock(lockp);
                local_bh_enable();
+               cond_resched();
        }
 
        for_each_possible_cpu(cpu) {
@@ -1424,6 +1425,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
                                set_bit(IPS_DYING_BIT, &ct->status);
                }
                spin_unlock_bh(&pcpu->lock);
+               cond_resched();
        }
        return NULL;
 found:
@@ -1440,6 +1442,8 @@ void nf_ct_iterate_cleanup(struct net *net,
        struct nf_conn *ct;
        unsigned int bucket = 0;
 
+       might_sleep();
+
        while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) {
                /* Time to push up daises... */
                if (del_timer(&ct->timeout))
@@ -1448,6 +1452,7 @@ void nf_ct_iterate_cleanup(struct net *net,
                /* ... else the timer will get him soon. */
 
                nf_ct_put(ct);
+               cond_resched();
        }
 }
 EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup);
index a7ba23353dab938b4048095e50da9eb463dfc477..857ae89633aff80cea1c6ac74355e5e183b4d780 100644 (file)
@@ -311,14 +311,14 @@ replay:
 #endif
                {
                        nfnl_unlock(subsys_id);
-                       netlink_ack(skb, nlh, -EOPNOTSUPP);
+                       netlink_ack(oskb, nlh, -EOPNOTSUPP);
                        return kfree_skb(skb);
                }
        }
 
        if (!ss->commit || !ss->abort) {
                nfnl_unlock(subsys_id);
-               netlink_ack(skb, nlh, -EOPNOTSUPP);
+               netlink_ack(oskb, nlh, -EOPNOTSUPP);
                return kfree_skb(skb);
        }
 
@@ -328,10 +328,12 @@ replay:
                nlh = nlmsg_hdr(skb);
                err = 0;
 
-               if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) ||
-                   skb->len < nlh->nlmsg_len) {
-                       err = -EINVAL;
-                       goto ack;
+               if (nlh->nlmsg_len < NLMSG_HDRLEN ||
+                   skb->len < nlh->nlmsg_len ||
+                   nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
+                       nfnl_err_reset(&err_list);
+                       status |= NFNL_BATCH_FAILURE;
+                       goto done;
                }
 
                /* Only requests are handled by the kernel */
@@ -406,7 +408,7 @@ ack:
                                 * pointing to the batch header.
                                 */
                                nfnl_err_reset(&err_list);
-                               netlink_ack(skb, nlmsg_hdr(oskb), -ENOMEM);
+                               netlink_ack(oskb, nlmsg_hdr(oskb), -ENOMEM);
                                status |= NFNL_BATCH_FAILURE;
                                goto done;
                        }
index 94837d236ab0e9a2fc3baa5d8fe7688a1b399afc..2671b9deb103735ff203999286a8cfbdde434f12 100644 (file)
@@ -312,7 +312,7 @@ static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout)
                        hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode)
                                untimeout(h, timeout);
                }
-               nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
+               spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]);
        }
        local_bh_enable();
 }
index c7808fc19719c4687457d039586f9708179b804e..c9743f78f21999ae01ed735a63c4e856e79cdc37 100644 (file)
@@ -100,7 +100,7 @@ static int nft_counter_init(const struct nft_ctx *ctx,
 
        cpu_stats = netdev_alloc_pcpu_stats(struct nft_counter_percpu);
        if (cpu_stats == NULL)
-               return ENOMEM;
+               return -ENOMEM;
 
        preempt_disable();
        this_cpu = this_cpu_ptr(cpu_stats);
@@ -138,7 +138,7 @@ static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)
        cpu_stats = __netdev_alloc_pcpu_stats(struct nft_counter_percpu,
                                              GFP_ATOMIC);
        if (cpu_stats == NULL)
-               return ENOMEM;
+               return -ENOMEM;
 
        preempt_disable();
        this_cpu = this_cpu_ptr(cpu_stats);
index 3eff7b67cdf2f5277c2004cf48c2f4e37c218068..6e57a3966dc5748a8cbb99cdf28c62ba1d5b90f1 100644 (file)
@@ -38,7 +38,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
        return XT_CONTINUE;
 }
 
-#if IS_ENABLED(CONFIG_NF_DUP_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
 static unsigned int
 tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
@@ -131,7 +131,7 @@ static struct xt_target tee_tg_reg[] __read_mostly = {
                .destroy    = tee_tg_destroy,
                .me         = THIS_MODULE,
        },
-#if IS_ENABLED(CONFIG_NF_DUP_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
        {
                .name       = "TEE",
                .revision   = 1,
index 1605691d94144aee0fc50ffb17be05eca2b59675..5eb7694348b5b82a3e80dc6262912eef441ec88e 100644 (file)
@@ -90,7 +90,9 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
        int err;
        struct vxlan_config conf = {
                .no_share = true,
-               .flags = VXLAN_F_COLLECT_METADATA,
+               .flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX,
+               /* Don't restrict the packets that can be sent by MTU */
+               .mtu = IP_MAX_MTU,
        };
 
        if (!options) {
index b5c2cf2aa6d4bc00e5c4bac2b3326db3d785c8be..af1acf0098666f3ffa8bc5bd168525f550478fef 100644 (file)
@@ -1852,6 +1852,7 @@ reset:
        }
 
        tp = old_tp;
+       protocol = tc_skb_protocol(skb);
        goto reclassify;
 #endif
 }
index ab0d538a74ed593571cfaef02cd1bb7ce872abe6..1099e99a53c485402ddd9c0693ff5cdd707accca 100644 (file)
@@ -60,6 +60,8 @@
 #include <net/inet_common.h>
 #include <net/inet_ecn.h>
 
+#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
+
 /* Global data structures. */
 struct sctp_globals sctp_globals __read_mostly;
 
@@ -1355,6 +1357,8 @@ static __init int sctp_init(void)
        unsigned long limit;
        int max_share;
        int order;
+       int num_entries;
+       int max_entry_order;
 
        sock_skb_cb_check_size(sizeof(struct sctp_ulpevent));
 
@@ -1407,14 +1411,24 @@ static __init int sctp_init(void)
 
        /* Size and allocate the association hash table.
         * The methodology is similar to that of the tcp hash tables.
+        * Though not identical.  Start by getting a goal size
         */
        if (totalram_pages >= (128 * 1024))
                goal = totalram_pages >> (22 - PAGE_SHIFT);
        else
                goal = totalram_pages >> (24 - PAGE_SHIFT);
 
-       for (order = 0; (1UL << order) < goal; order++)
-               ;
+       /* Then compute the page order for said goal */
+       order = get_order(goal);
+
+       /* Now compute the required page order for the maximum sized table we
+        * want to create
+        */
+       max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES *
+                                   sizeof(struct sctp_bind_hashbucket));
+
+       /* Limit the page order by that maximum hash table size */
+       order = min(order, max_entry_order);
 
        /* Allocate and initialize the endpoint hash table.  */
        sctp_ep_hashsize = 64;
@@ -1430,20 +1444,35 @@ static __init int sctp_init(void)
                INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
        }
 
-       /* Allocate and initialize the SCTP port hash table.  */
+       /* Allocate and initialize the SCTP port hash table.
+        * Note that order is initalized to start at the max sized
+        * table we want to support.  If we can't get that many pages
+        * reduce the order and try again
+        */
        do {
-               sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
-                                       sizeof(struct sctp_bind_hashbucket);
-               if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
-                       continue;
                sctp_port_hashtable = (struct sctp_bind_hashbucket *)
                        __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order);
        } while (!sctp_port_hashtable && --order > 0);
+
        if (!sctp_port_hashtable) {
                pr_err("Failed bind hash alloc\n");
                status = -ENOMEM;
                goto err_bhash_alloc;
        }
+
+       /* Now compute the number of entries that will fit in the
+        * port hash space we allocated
+        */
+       num_entries = (1UL << order) * PAGE_SIZE /
+                     sizeof(struct sctp_bind_hashbucket);
+
+       /* And finish by rounding it down to the nearest power of two
+        * this wastes some memory of course, but its needed because
+        * the hash function operates based on the assumption that
+        * that the number of entries is a power of two
+        */
+       sctp_port_hashsize = rounddown_pow_of_two(num_entries);
+
        for (i = 0; i < sctp_port_hashsize; i++) {
                spin_lock_init(&sctp_port_hashtable[i].lock);
                INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
@@ -1452,7 +1481,8 @@ static __init int sctp_init(void)
        if (sctp_transport_hashtable_init())
                goto err_thash_alloc;
 
-       pr_info("Hash tables configured (bind %d)\n", sctp_port_hashsize);
+       pr_info("Hash tables configured (bind %d/%d)\n", sctp_port_hashsize,
+               num_entries);
 
        sctp_sysctl_register();
 
index 5ca2ebfe0be83882fcb841de6fa8029b6455ef85..e878da0949dbfc0012d2e7985bf6e28386678d0f 100644 (file)
@@ -5538,6 +5538,7 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
        struct sctp_hmac_algo_param *hmacs;
        __u16 data_len = 0;
        u32 num_idents;
+       int i;
 
        if (!ep->auth_enable)
                return -EACCES;
@@ -5555,8 +5556,12 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
                return -EFAULT;
        if (put_user(num_idents, &p->shmac_num_idents))
                return -EFAULT;
-       if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
-               return -EFAULT;
+       for (i = 0; i < num_idents; i++) {
+               __u16 hmacid = ntohs(hmacs->hmac_ids[i]);
+
+               if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
+                       return -EFAULT;
+       }
        return 0;
 }
 
index 799e65b944b9019cf7eee177f90f6d67a0fb66dd..cabf586f47d7d0d75a8cb77b44d497e76a34abd7 100644 (file)
@@ -740,7 +740,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
                default:
                        printk(KERN_CRIT "%s: bad return from "
                                "gss_fill_context: %zd\n", __func__, err);
-                       BUG();
+                       gss_msg->msg.errno = -EIO;
                }
                goto err_release_msg;
        }
index 2b32fd602669f1fbc1aa96d61ad076fe688713e1..273bc3a35425ba99351eedb3f99244f0f9c07ab7 100644 (file)
@@ -1225,7 +1225,7 @@ int qword_get(char **bpp, char *dest, int bufsize)
        if (bp[0] == '\\' && bp[1] == 'x') {
                /* HEX STRING */
                bp += 2;
-               while (len < bufsize) {
+               while (len < bufsize - 1) {
                        int h, l;
 
                        h = hex_to_bin(bp[0]);
index cc1251d0729707751d87537e1cbc6567aef1596c..2dcd7640eeb525d6a7f1ba8bd3eab047cda30f75 100644 (file)
@@ -341,6 +341,8 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt,
        rqst->rq_reply_bytes_recvd = 0;
        rqst->rq_bytes_sent = 0;
        rqst->rq_xid = headerp->rm_xid;
+
+       rqst->rq_private_buf.len = size;
        set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
 
        buf = &rqst->rq_rcv_buf;
index 0c2944fb9ae0d34ca8e153d9412c5896b47ffacf..347cdc99ed094ab8326071b69958296641576198 100644 (file)
@@ -1973,8 +1973,10 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
 
        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
                          NLM_F_MULTI, TIPC_NL_LINK_GET);
-       if (!hdr)
+       if (!hdr) {
+               tipc_bcast_unlock(net);
                return -EMSGSIZE;
+       }
 
        attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
        if (!attrs)
index fa97d9649a2851f1e6d5c8a1f39f2e4f7603e61b..9d7a16fc5ca4b6ab3456c5129cde96664a6fb4fd 100644 (file)
@@ -346,12 +346,6 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities)
        skb_queue_head_init(&n->bc_entry.inputq2);
        for (i = 0; i < MAX_BEARERS; i++)
                spin_lock_init(&n->links[i].lock);
-       hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]);
-       list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
-               if (n->addr < temp_node->addr)
-                       break;
-       }
-       list_add_tail_rcu(&n->list, &temp_node->list);
        n->state = SELF_DOWN_PEER_LEAVING;
        n->signature = INVALID_NODE_SIG;
        n->active_links[0] = INVALID_BEARER_ID;
@@ -372,6 +366,12 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities)
        tipc_node_get(n);
        setup_timer(&n->timer, tipc_node_timeout, (unsigned long)n);
        n->keepalive_intv = U32_MAX;
+       hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]);
+       list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
+               if (n->addr < temp_node->addr)
+                       break;
+       }
+       list_add_tail_rcu(&n->list, &temp_node->list);
 exit:
        spin_unlock_bh(&tn->node_list_lock);
        return n;
index 49d5093eb0553a4416af09784b0e012f58cbd124..f75f847e688d4a9ca5b0bde01c3e052c88ca51cb 100644 (file)
@@ -1496,7 +1496,7 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
        UNIXCB(skb).fp = NULL;
 
        for (i = scm->fp->count-1; i >= 0; i--)
-               unix_notinflight(scm->fp->fp[i]);
+               unix_notinflight(scm->fp->user, scm->fp->fp[i]);
 }
 
 static void unix_destruct_scm(struct sk_buff *skb)
@@ -1561,7 +1561,7 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
                return -ENOMEM;
 
        for (i = scm->fp->count - 1; i >= 0; i--)
-               unix_inflight(scm->fp->fp[i]);
+               unix_inflight(scm->fp->user, scm->fp->fp[i]);
        return max_level;
 }
 
@@ -1781,7 +1781,12 @@ restart_locked:
                        goto out_unlock;
        }
 
-       if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
+       /* other == sk && unix_peer(other) != sk if
+        * - unix_peer(sk) == NULL, destination address bound to sk
+        * - unix_peer(sk) == sk by time of get but disconnected before lock
+        */
+       if (other != sk &&
+           unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
                if (timeo) {
                        timeo = unix_wait_for_peer(other, timeo);
 
@@ -2277,13 +2282,15 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
        size_t size = state->size;
        unsigned int last_len;
 
-       err = -EINVAL;
-       if (sk->sk_state != TCP_ESTABLISHED)
+       if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
+               err = -EINVAL;
                goto out;
+       }
 
-       err = -EOPNOTSUPP;
-       if (flags & MSG_OOB)
+       if (unlikely(flags & MSG_OOB)) {
+               err = -EOPNOTSUPP;
                goto out;
+       }
 
        target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
        timeo = sock_rcvtimeo(sk, noblock);
@@ -2305,6 +2312,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
                bool drop_skb;
                struct sk_buff *skb, *last;
 
+redo:
                unix_state_lock(sk);
                if (sock_flag(sk, SOCK_DEAD)) {
                        err = -ECONNRESET;
@@ -2329,9 +2337,11 @@ again:
                                goto unlock;
 
                        unix_state_unlock(sk);
-                       err = -EAGAIN;
-                       if (!timeo)
+                       if (!timeo) {
+                               err = -EAGAIN;
                                break;
+                       }
+
                        mutex_unlock(&u->readlock);
 
                        timeo = unix_stream_data_wait(sk, timeo, last,
@@ -2344,7 +2354,7 @@ again:
                        }
 
                        mutex_lock(&u->readlock);
-                       continue;
+                       goto redo;
 unlock:
                        unix_state_unlock(sk);
                        break;
index c512f64d528766f940b30236bf3e3c8fa2047661..4d9679701a6df5113df3e24a1c9b86e2a63b3710 100644 (file)
@@ -220,7 +220,7 @@ done:
        return skb->len;
 }
 
-static struct sock *unix_lookup_by_ino(int ino)
+static struct sock *unix_lookup_by_ino(unsigned int ino)
 {
        int i;
        struct sock *sk;
index 8fcdc2283af50c5caecd409b79cae6028ca2c836..6a0d48525fcf9a71f54bb43495b200b300f5341e 100644 (file)
@@ -116,7 +116,7 @@ struct sock *unix_get_socket(struct file *filp)
  * descriptor if it is for an AF_UNIX socket.
  */
 
-void unix_inflight(struct file *fp)
+void unix_inflight(struct user_struct *user, struct file *fp)
 {
        struct sock *s = unix_get_socket(fp);
 
@@ -133,11 +133,11 @@ void unix_inflight(struct file *fp)
                }
                unix_tot_inflight++;
        }
-       fp->f_cred->user->unix_inflight++;
+       user->unix_inflight++;
        spin_unlock(&unix_gc_lock);
 }
 
-void unix_notinflight(struct file *fp)
+void unix_notinflight(struct user_struct *user, struct file *fp)
 {
        struct sock *s = unix_get_socket(fp);
 
@@ -152,7 +152,7 @@ void unix_notinflight(struct file *fp)
                        list_del_init(&u->link);
                unix_tot_inflight--;
        }
-       fp->f_cred->user->unix_inflight--;
+       user->unix_inflight--;
        spin_unlock(&unix_gc_lock);
 }
 
index 7fd1220fbfa0bb2477e2b7e6edcf714a5ae6a097..bbe65dcb973834761c30cef249a537ba498898fb 100644 (file)
@@ -1557,8 +1557,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
        if (err < 0)
                goto out;
 
-       prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-
        while (total_written < len) {
                ssize_t written;
 
@@ -1578,7 +1576,9 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                                goto out_wait;
 
                        release_sock(sk);
+                       prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
                        timeout = schedule_timeout(timeout);
+                       finish_wait(sk_sleep(sk), &wait);
                        lock_sock(sk);
                        if (signal_pending(current)) {
                                err = sock_intr_errno(timeout);
@@ -1588,8 +1588,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                                goto out_wait;
                        }
 
-                       prepare_to_wait(sk_sleep(sk), &wait,
-                                       TASK_INTERRUPTIBLE);
                }
 
                /* These checks occur both as part of and after the loop
@@ -1635,7 +1633,6 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
 out_wait:
        if (total_written > 0)
                err = total_written;
-       finish_wait(sk_sleep(sk), &wait);
 out:
        release_sock(sk);
        return err;
@@ -1716,7 +1713,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
        if (err < 0)
                goto out;
 
-       prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 
        while (1) {
                s64 ready = vsock_stream_has_data(vsk);
@@ -1727,7 +1723,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                         */
 
                        err = -ENOMEM;
-                       goto out_wait;
+                       goto out;
                } else if (ready > 0) {
                        ssize_t read;
 
@@ -1750,7 +1746,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                                        vsk, target, read,
                                        !(flags & MSG_PEEK), &recv_data);
                        if (err < 0)
-                               goto out_wait;
+                               goto out;
 
                        if (read >= target || flags & MSG_PEEK)
                                break;
@@ -1773,7 +1769,9 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                                break;
 
                        release_sock(sk);
+                       prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
                        timeout = schedule_timeout(timeout);
+                       finish_wait(sk_sleep(sk), &wait);
                        lock_sock(sk);
 
                        if (signal_pending(current)) {
@@ -1783,9 +1781,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                                err = -EAGAIN;
                                break;
                        }
-
-                       prepare_to_wait(sk_sleep(sk), &wait,
-                                       TASK_INTERRUPTIBLE);
                }
        }
 
@@ -1816,8 +1811,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                err = copied;
        }
 
-out_wait:
-       finish_wait(sk_sleep(sk), &wait);
 out:
        release_sock(sk);
        return err;
diff --git a/scripts/prune-kernel b/scripts/prune-kernel
new file mode 100755 (executable)
index 0000000..ab5034e
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# because I use CONFIG_LOCALVERSION_AUTO, not the same version again and
+# again, /boot and /lib/modules/ eventually fill up.
+# Dumb script to purge that stuff:
+
+for f in "$@"
+do
+        if rpm -qf "/lib/modules/$f" >/dev/null; then
+                echo "keeping $f (installed from rpm)"
+        elif [ $(uname -r) = "$f" ]; then
+                echo "keeping $f (running kernel) "
+        else
+                echo "removing $f"
+                rm -f "/boot/initramfs-$f.img" "/boot/System.map-$f"
+                rm -f "/boot/vmlinuz-$f"   "/boot/config-$f"
+                rm -rf "/lib/modules/$f"
+                new-kernel-pkg --remove $f
+        fi
+done
index f7160253f17faad71c17a86b19833123a2edebd4..e6ea9d4b1de91a8d58e3ccab0fd3cef222ea6fcd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/integrity.h>
 #include <linux/evm.h>
 #include <crypto/hash.h>
+#include <crypto/algapi.h>
 #include "evm.h"
 
 int evm_initialized;
@@ -148,7 +149,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
                                   xattr_value_len, calc.digest);
                if (rc)
                        break;
-               rc = memcmp(xattr_data->digest, calc.digest,
+               rc = crypto_memneq(xattr_data->digest, calc.digest,
                            sizeof(calc.digest));
                if (rc)
                        rc = -EINVAL;
index f8110cfd80ff64bf05ef428f03dff935e6d704c4..f1ab71504e1d59e1c6aaa7c0d22870e371ec85b3 100644 (file)
@@ -3249,7 +3249,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
 
 static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
 {
-       struct inode_security_struct *isec = inode_security(inode);
+       struct inode_security_struct *isec = inode_security_novalidate(inode);
        *secid = isec->sid;
 }
 
index 2bbb41822d8ec8882f8dacbbb4c5f8a1feac59ca..8495b93681906bd39f4065723461cddac2e7d347 100644 (file)
@@ -83,6 +83,7 @@ static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
        { TCPDIAG_GETSOCK,      NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
        { DCCPDIAG_GETSOCK,     NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
        { SOCK_DIAG_BY_FAMILY,  NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
+       { SOCK_DESTROY,         NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE },
 };
 
 static struct nlmsg_perm nlmsg_xfrm_perms[] =
index b9c0910fb8c4ead97559c7f9c1737e76b2d5cf7f..0608f216f3592fc597c85c2c92594b891e499647 100644 (file)
@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 {
         unsigned char reserved[128];
 };
 
+#ifdef CONFIG_X86_X32
+/* x32 has a different alignment for 64bit values from ia32 */
+struct snd_ctl_elem_value_x32 {
+       struct snd_ctl_elem_id id;
+       unsigned int indirect;  /* bit-field causes misalignment */
+       union {
+               s32 integer[128];
+               unsigned char data[512];
+               s64 integer64[64];
+       } value;
+       unsigned char reserved[128];
+};
+#endif /* CONFIG_X86_X32 */
 
 /* get the value type and count of the control */
 static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
@@ -219,9 +232,11 @@ static int get_elem_size(int type, int count)
 
 static int copy_ctl_value_from_user(struct snd_card *card,
                                    struct snd_ctl_elem_value *data,
-                                   struct snd_ctl_elem_value32 __user *data32,
+                                   void __user *userdata,
+                                   void __user *valuep,
                                    int *typep, int *countp)
 {
+       struct snd_ctl_elem_value32 __user *data32 = userdata;
        int i, type, size;
        int uninitialized_var(count);
        unsigned int indirect;
@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card,
        if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
            type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                for (i = 0; i < count; i++) {
+                       s32 __user *intp = valuep;
                        int val;
-                       if (get_user(val, &data32->value.integer[i]))
+                       if (get_user(val, &intp[i]))
                                return -EFAULT;
                        data->value.integer.value[i] = val;
                }
@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card,
                        dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
                        return -EINVAL;
                }
-               if (copy_from_user(data->value.bytes.data,
-                                  data32->value.data, size))
+               if (copy_from_user(data->value.bytes.data, valuep, size))
                        return -EFAULT;
        }
 
@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card,
 }
 
 /* restore the value to 32bit */
-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
+static int copy_ctl_value_to_user(void __user *userdata,
+                                 void __user *valuep,
                                  struct snd_ctl_elem_value *data,
                                  int type, int count)
 {
@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
        if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
            type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                for (i = 0; i < count; i++) {
+                       s32 __user *intp = valuep;
                        int val;
                        val = data->value.integer.value[i];
-                       if (put_user(val, &data32->value.integer[i]))
+                       if (put_user(val, &intp[i]))
                                return -EFAULT;
                }
        } else {
                size = get_elem_size(type, count);
-               if (copy_to_user(data32->value.data,
-                                data->value.bytes.data, size))
+               if (copy_to_user(valuep, data->value.bytes.data, size))
                        return -EFAULT;
        }
        return 0;
 }
 
-static int snd_ctl_elem_read_user_compat(struct snd_card *card, 
-                                        struct snd_ctl_elem_value32 __user *data32)
+static int ctl_elem_read_user(struct snd_card *card,
+                             void __user *userdata, void __user *valuep)
 {
        struct snd_ctl_elem_value *data;
        int err, type, count;
@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
        if (data == NULL)
                return -ENOMEM;
 
-       if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+       err = copy_ctl_value_from_user(card, data, userdata, valuep,
+                                      &type, &count);
+       if (err < 0)
                goto error;
 
        snd_power_lock(card);
@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
                err = snd_ctl_elem_read(card, data);
        snd_power_unlock(card);
        if (err >= 0)
-               err = copy_ctl_value_to_user(data32, data, type, count);
+               err = copy_ctl_value_to_user(userdata, valuep, data,
+                                            type, count);
  error:
        kfree(data);
        return err;
 }
 
-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
-                                         struct snd_ctl_elem_value32 __user *data32)
+static int ctl_elem_write_user(struct snd_ctl_file *file,
+                              void __user *userdata, void __user *valuep)
 {
        struct snd_ctl_elem_value *data;
        struct snd_card *card = file->card;
@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
        if (data == NULL)
                return -ENOMEM;
 
-       if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+       err = copy_ctl_value_from_user(card, data, userdata, valuep,
+                                      &type, &count);
+       if (err < 0)
                goto error;
 
        snd_power_lock(card);
@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
                err = snd_ctl_elem_write(card, file, data);
        snd_power_unlock(card);
        if (err >= 0)
-               err = copy_ctl_value_to_user(data32, data, type, count);
+               err = copy_ctl_value_to_user(userdata, valuep, data,
+                                            type, count);
  error:
        kfree(data);
        return err;
 }
 
+static int snd_ctl_elem_read_user_compat(struct snd_card *card,
+                                        struct snd_ctl_elem_value32 __user *data32)
+{
+       return ctl_elem_read_user(card, data32, &data32->value);
+}
+
+static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
+                                         struct snd_ctl_elem_value32 __user *data32)
+{
+       return ctl_elem_write_user(file, data32, &data32->value);
+}
+
+#ifdef CONFIG_X86_X32
+static int snd_ctl_elem_read_user_x32(struct snd_card *card,
+                                     struct snd_ctl_elem_value_x32 __user *data32)
+{
+       return ctl_elem_read_user(card, data32, &data32->value);
+}
+
+static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file,
+                                      struct snd_ctl_elem_value_x32 __user *data32)
+{
+       return ctl_elem_write_user(file, data32, &data32->value);
+}
+#endif /* CONFIG_X86_X32 */
+
 /* add or replace a user control */
 static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
                                   struct snd_ctl_elem_info32 __user *data32,
@@ -393,6 +441,10 @@ enum {
        SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
        SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
        SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32),
+#ifdef CONFIG_X86_X32
+       SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32),
+       SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns
                return snd_ctl_elem_add_compat(ctl, argp, 0);
        case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
                return snd_ctl_elem_add_compat(ctl, argp, 1);
+#ifdef CONFIG_X86_X32
+       case SNDRV_CTL_IOCTL_ELEM_READ_X32:
+               return snd_ctl_elem_read_user_x32(ctl->card, argp);
+       case SNDRV_CTL_IOCTL_ELEM_WRITE_X32:
+               return snd_ctl_elem_write_user_x32(ctl, argp);
+#endif /* CONFIG_X86_X32 */
        }
 
        down_read(&snd_ioctl_rwsem);
index 9630e9f72b7ba2ad77f50a516ecc559c0c200975..1f64ab0c2a95a291638406e62daa15ad6a172db3 100644 (file)
@@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream
        return err;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */
+static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
+                                    struct snd_pcm_channel_info __user *src);
+#define snd_pcm_ioctl_channel_info_x32(s, p)   \
+       snd_pcm_channel_info_user(s, p)
+#endif /* CONFIG_X86_X32 */
+
 struct snd_pcm_status32 {
        s32 state;
        struct compat_timespec trigger_tstamp;
@@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
        return err;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_pcm_status_x32 {
+       s32 state;
+       u32 rsvd; /* alignment */
+       struct timespec trigger_tstamp;
+       struct timespec tstamp;
+       u32 appl_ptr;
+       u32 hw_ptr;
+       s32 delay;
+       u32 avail;
+       u32 avail_max;
+       u32 overrange;
+       s32 suspended_state;
+       u32 audio_tstamp_data;
+       struct timespec audio_tstamp;
+       struct timespec driver_tstamp;
+       u32 audio_tstamp_accuracy;
+       unsigned char reserved[52-2*sizeof(struct timespec)];
+} __packed;
+
+#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
+
+static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
+                                  struct snd_pcm_status_x32 __user *src,
+                                  bool ext)
+{
+       struct snd_pcm_status status;
+       int err;
+
+       memset(&status, 0, sizeof(status));
+       /*
+        * with extension, parameters are read/write,
+        * get audio_tstamp_data from user,
+        * ignore rest of status structure
+        */
+       if (ext && get_user(status.audio_tstamp_data,
+                               (u32 __user *)(&src->audio_tstamp_data)))
+               return -EFAULT;
+       err = snd_pcm_status(substream, &status);
+       if (err < 0)
+               return err;
+
+       if (clear_user(src, sizeof(*src)))
+               return -EFAULT;
+       if (put_user(status.state, &src->state) ||
+           put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
+           put_timespec(&status.tstamp, &src->tstamp) ||
+           put_user(status.appl_ptr, &src->appl_ptr) ||
+           put_user(status.hw_ptr, &src->hw_ptr) ||
+           put_user(status.delay, &src->delay) ||
+           put_user(status.avail, &src->avail) ||
+           put_user(status.avail_max, &src->avail_max) ||
+           put_user(status.overrange, &src->overrange) ||
+           put_user(status.suspended_state, &src->suspended_state) ||
+           put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
+           put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
+           put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
+           put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
+               return -EFAULT;
+
+       return err;
+}
+#endif /* CONFIG_X86_X32 */
+
 /* both for HW_PARAMS and HW_REFINE */
 static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
                                          int refine, 
@@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
        return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_pcm_mmap_status_x32 {
+       s32 state;
+       s32 pad1;
+       u32 hw_ptr;
+       u32 pad2; /* alignment */
+       struct timespec tstamp;
+       s32 suspended_state;
+       struct timespec audio_tstamp;
+} __packed;
+
+struct snd_pcm_mmap_control_x32 {
+       u32 appl_ptr;
+       u32 avail_min;
+};
+
+struct snd_pcm_sync_ptr_x32 {
+       u32 flags;
+       u32 rsvd; /* alignment */
+       union {
+               struct snd_pcm_mmap_status_x32 status;
+               unsigned char reserved[64];
+       } s;
+       union {
+               struct snd_pcm_mmap_control_x32 control;
+               unsigned char reserved[64];
+       } c;
+} __packed;
+
+static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
+                                     struct snd_pcm_sync_ptr_x32 __user *src)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       volatile struct snd_pcm_mmap_status *status;
+       volatile struct snd_pcm_mmap_control *control;
+       u32 sflags;
+       struct snd_pcm_mmap_control scontrol;
+       struct snd_pcm_mmap_status sstatus;
+       snd_pcm_uframes_t boundary;
+       int err;
+
+       if (snd_BUG_ON(!runtime))
+               return -EINVAL;
+
+       if (get_user(sflags, &src->flags) ||
+           get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+           get_user(scontrol.avail_min, &src->c.control.avail_min))
+               return -EFAULT;
+       if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
+               err = snd_pcm_hwsync(substream);
+               if (err < 0)
+                       return err;
+       }
+       status = runtime->status;
+       control = runtime->control;
+       boundary = recalculate_boundary(runtime);
+       if (!boundary)
+               boundary = 0x7fffffff;
+       snd_pcm_stream_lock_irq(substream);
+       /* FIXME: we should consider the boundary for the sync from app */
+       if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
+               control->appl_ptr = scontrol.appl_ptr;
+       else
+               scontrol.appl_ptr = control->appl_ptr % boundary;
+       if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+               control->avail_min = scontrol.avail_min;
+       else
+               scontrol.avail_min = control->avail_min;
+       sstatus.state = status->state;
+       sstatus.hw_ptr = status->hw_ptr % boundary;
+       sstatus.tstamp = status->tstamp;
+       sstatus.suspended_state = status->suspended_state;
+       sstatus.audio_tstamp = status->audio_tstamp;
+       snd_pcm_stream_unlock_irq(substream);
+       if (put_user(sstatus.state, &src->s.status.state) ||
+           put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
+           put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
+           put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+           put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) ||
+           put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+           put_user(scontrol.avail_min, &src->c.control.avail_min))
+               return -EFAULT;
+
+       return 0;
+}
+#endif /* CONFIG_X86_X32 */
 
 /*
  */
@@ -487,7 +647,12 @@ enum {
        SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
        SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
        SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
-
+#ifdef CONFIG_X86_X32
+       SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info),
+       SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32),
+       SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32),
+       SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
                return snd_pcm_ioctl_rewind_compat(substream, argp);
        case SNDRV_PCM_IOCTL_FORWARD32:
                return snd_pcm_ioctl_forward_compat(substream, argp);
+#ifdef CONFIG_X86_X32
+       case SNDRV_PCM_IOCTL_STATUS_X32:
+               return snd_pcm_status_user_x32(substream, argp, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT_X32:
+               return snd_pcm_status_user_x32(substream, argp, true);
+       case SNDRV_PCM_IOCTL_SYNC_PTR_X32:
+               return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
+       case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32:
+               return snd_pcm_ioctl_channel_info_x32(substream, argp);
+#endif /* CONFIG_X86_X32 */
        }
 
        return -ENOIOCTLCMD;
index ebe8444de6c6ea8f44a5cacfb39b963939d9880d..53dc37357bca9dea5450d818f2bcee9d71577aec 100644 (file)
@@ -565,3 +565,33 @@ unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
        return rates_a & rates_b;
 }
 EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);
+
+/**
+ * snd_pcm_rate_range_to_bits - converts rate range to SNDRV_PCM_RATE_xxx bit
+ * @rate_min: the minimum sample rate
+ * @rate_max: the maximum sample rate
+ *
+ * This function has an implicit assumption: the rates in the given range have
+ * only the pre-defined rates like 44100 or 16000.
+ *
+ * Return: The SNDRV_PCM_RATE_xxx flag that corresponds to the given rate range,
+ * or SNDRV_PCM_RATE_KNOT for an unknown range.
+ */
+unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min,
+       unsigned int rate_max)
+{
+       unsigned int rates = 0;
+       int i;
+
+       for (i = 0; i < snd_pcm_known_rates.count; i++) {
+               if (snd_pcm_known_rates.list[i] >= rate_min
+                       && snd_pcm_known_rates.list[i] <= rate_max)
+                       rates |= 1 << i;
+       }
+
+       if (!rates)
+               rates = SNDRV_PCM_RATE_KNOT;
+
+       return rates;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_rate_range_to_bits);
index fadd3eb8e8bb2d77264fafec9be05ba54e36af85..9106d8e2300eab3e566f9a3807c469ee02aa7bcd 100644 (file)
@@ -74,6 +74,18 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
 static DEFINE_RWLOCK(snd_pcm_link_rwlock);
 static DECLARE_RWSEM(snd_pcm_link_rwsem);
 
+/* Writer in rwsem may block readers even during its waiting in queue,
+ * and this may lead to a deadlock when the code path takes read sem
+ * twice (e.g. one in snd_pcm_action_nonatomic() and another in
+ * snd_pcm_stream_lock()).  As a (suboptimal) workaround, let writer to
+ * spin until it gets the lock.
+ */
+static inline void down_write_nonblock(struct rw_semaphore *lock)
+{
+       while (!down_write_trylock(lock))
+               cond_resched();
+}
+
 /**
  * snd_pcm_stream_lock - Lock the PCM stream
  * @substream: PCM substream
@@ -1813,7 +1825,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
                res = -ENOMEM;
                goto _nolock;
        }
-       down_write(&snd_pcm_link_rwsem);
+       down_write_nonblock(&snd_pcm_link_rwsem);
        write_lock_irq(&snd_pcm_link_rwlock);
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
            substream->runtime->status->state != substream1->runtime->status->state ||
@@ -1860,7 +1872,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
        struct snd_pcm_substream *s;
        int res = 0;
 
-       down_write(&snd_pcm_link_rwsem);
+       down_write_nonblock(&snd_pcm_link_rwsem);
        write_lock_irq(&snd_pcm_link_rwlock);
        if (!snd_pcm_stream_linked(substream)) {
                res = -EALREADY;
index 5268c1f58c25b7e143b5713a45dac36220558cc5..f69764d7cdd7025d3935143883c162372e3c0c7c 100644 (file)
@@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
        if (err < 0)
                return err;
 
-       if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
-           put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+       if (compat_put_timespec(&status.tstamp, &src->tstamp) ||
            put_user(status.avail, &src->avail) ||
            put_user(status.xruns, &src->xruns))
                return -EFAULT;
@@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
        return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_rawmidi_status_x32 {
+       s32 stream;
+       u32 rsvd; /* alignment */
+       struct timespec tstamp;
+       u32 avail;
+       u32 xruns;
+       unsigned char reserved[16];
+} __attribute__((packed));
+
+#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
+
+static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile,
+                                       struct snd_rawmidi_status_x32 __user *src)
+{
+       int err;
+       struct snd_rawmidi_status status;
+
+       if (rfile->output == NULL)
+               return -EINVAL;
+       if (get_user(status.stream, &src->stream))
+               return -EFAULT;
+
+       switch (status.stream) {
+       case SNDRV_RAWMIDI_STREAM_OUTPUT:
+               err = snd_rawmidi_output_status(rfile->output, &status);
+               break;
+       case SNDRV_RAWMIDI_STREAM_INPUT:
+               err = snd_rawmidi_input_status(rfile->input, &status);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (err < 0)
+               return err;
+
+       if (put_timespec(&status.tstamp, &src->tstamp) ||
+           put_user(status.avail, &src->avail) ||
+           put_user(status.xruns, &src->xruns))
+               return -EFAULT;
+
+       return 0;
+}
+#endif /* CONFIG_X86_X32 */
+
 enum {
        SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
        SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
+#ifdef CONFIG_X86_X32
+       SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign
                return snd_rawmidi_ioctl_params_compat(rfile, argp);
        case SNDRV_RAWMIDI_IOCTL_STATUS32:
                return snd_rawmidi_ioctl_status_compat(rfile, argp);
+#ifdef CONFIG_X86_X32
+       case SNDRV_RAWMIDI_IOCTL_STATUS_X32:
+               return snd_rawmidi_ioctl_status_x32(rfile, argp);
+#endif /* CONFIG_X86_X32 */
        }
        return -ENOIOCTLCMD;
 }
index 8db156b207f187dfc821160cf39d92a8a5521085..8cdf489df80e03ee2cd5652aec627ffa73e9fcc3 100644 (file)
@@ -149,8 +149,6 @@ odev_release(struct inode *inode, struct file *file)
        if ((dp = file->private_data) == NULL)
                return 0;
 
-       snd_seq_oss_drain_write(dp);
-
        mutex_lock(&register_mutex);
        snd_seq_oss_release(dp);
        mutex_unlock(&register_mutex);
index b43924325249c01b0cdd11fc1164572a50369f98..d7b4d016b547584ed337c6d0e29502ad1b12c5bf 100644 (file)
@@ -127,7 +127,6 @@ int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int co
 unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait);
 
 void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
 
 /* */
 void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
index 6779e82b46dd7060bd982137ca75cfcdbbfa989e..92c96a95a903abd82ace8256b77c2c3bb99ff620 100644 (file)
@@ -435,22 +435,6 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp)
 }
 
 
-/*
- * Wait until the queue is empty (if we don't have nonblock)
- */
-void
-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
-{
-       if (! dp->timer->running)
-               return;
-       if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
-           dp->writeq) {
-               while (snd_seq_oss_writeq_sync(dp->writeq))
-                       ;
-       }
-}
-
-
 /*
  * reset sequencer devices
  */
index 801076687bb16f082a8780125c69e879bdef4019..c850345c43b53dd5616b155f34f741d0ca30701c 100644 (file)
@@ -383,15 +383,20 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
 
        if (snd_BUG_ON(!pool))
                return -EINVAL;
-       if (pool->ptr)                  /* should be atomic? */
-               return 0;
 
-       pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
-       if (!pool->ptr)
+       cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
+       if (!cellptr)
                return -ENOMEM;
 
        /* add new cells to the free cell list */
        spin_lock_irqsave(&pool->lock, flags);
+       if (pool->ptr) {
+               spin_unlock_irqrestore(&pool->lock, flags);
+               vfree(cellptr);
+               return 0;
+       }
+
+       pool->ptr = cellptr;
        pool->free = NULL;
 
        for (cell = 0; cell < pool->size; cell++) {
index 921fb2bd8fadb37adf167d6bf52dd97270f005a4..fe686ee41c6da064ad4e1aa43ce172e359da1184 100644 (file)
@@ -535,19 +535,22 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
                                        bool is_src, bool ack)
 {
        struct snd_seq_port_subs_info *grp;
+       struct list_head *list;
+       bool empty;
 
        grp = is_src ? &port->c_src : &port->c_dest;
+       list = is_src ? &subs->src_list : &subs->dest_list;
        down_write(&grp->list_mutex);
        write_lock_irq(&grp->list_lock);
-       if (is_src)
-               list_del(&subs->src_list);
-       else
-               list_del(&subs->dest_list);
+       empty = list_empty(list);
+       if (!empty)
+               list_del_init(list);
        grp->exclusive = 0;
        write_unlock_irq(&grp->list_lock);
        up_write(&grp->list_mutex);
 
-       unsubscribe_port(client, port, grp, &subs->info, ack);
+       if (!empty)
+               unsubscribe_port(client, port, grp, &subs->info, ack);
 }
 
 /* connect two ports */
index 9b513a05765a10985d556b101918ed3783b9ae60..dca817fc78941b5f9109e8117b3fc5adb621562e 100644 (file)
@@ -422,7 +422,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
        spin_lock_irqsave(&timer->lock, flags);
        list_for_each_entry(ts, &ti->slave_active_head, active_list)
                if (ts->ccallback)
-                       ts->ccallback(ti, event + 100, &tstamp, resolution);
+                       ts->ccallback(ts, event + 100, &tstamp, resolution);
        spin_unlock_irqrestore(&timer->lock, flags);
 }
 
@@ -518,9 +518,13 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
                        spin_unlock_irqrestore(&slave_active_lock, flags);
                        return -EBUSY;
                }
+               if (timeri->timer)
+                       spin_lock(&timeri->timer->lock);
                timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
                list_del_init(&timeri->ack_list);
                list_del_init(&timeri->active_list);
+               if (timeri->timer)
+                       spin_unlock(&timeri->timer->lock);
                spin_unlock_irqrestore(&slave_active_lock, flags);
                goto __end;
        }
@@ -1929,6 +1933,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 {
        struct snd_timer_user *tu;
        long result = 0, unit;
+       int qhead;
        int err = 0;
 
        tu = file->private_data;
@@ -1940,7 +1945,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 
                        if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
                                err = -EAGAIN;
-                               break;
+                               goto _error;
                        }
 
                        set_current_state(TASK_INTERRUPTIBLE);
@@ -1955,42 +1960,37 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 
                        if (tu->disconnected) {
                                err = -ENODEV;
-                               break;
+                               goto _error;
                        }
                        if (signal_pending(current)) {
                                err = -ERESTARTSYS;
-                               break;
+                               goto _error;
                        }
                }
 
+               qhead = tu->qhead++;
+               tu->qhead %= tu->queue_size;
                spin_unlock_irq(&tu->qlock);
-               if (err < 0)
-                       goto _error;
 
                if (tu->tread) {
-                       if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
-                                        sizeof(struct snd_timer_tread))) {
+                       if (copy_to_user(buffer, &tu->tqueue[qhead],
+                                        sizeof(struct snd_timer_tread)))
                                err = -EFAULT;
-                               goto _error;
-                       }
                } else {
-                       if (copy_to_user(buffer, &tu->queue[tu->qhead++],
-                                        sizeof(struct snd_timer_read))) {
+                       if (copy_to_user(buffer, &tu->queue[qhead],
+                                        sizeof(struct snd_timer_read)))
                                err = -EFAULT;
-                               goto _error;
-                       }
                }
 
-               tu->qhead %= tu->queue_size;
-
-               result += unit;
-               buffer += unit;
-
                spin_lock_irq(&tu->qlock);
                tu->qused--;
+               if (err < 0)
+                       goto _error;
+               result += unit;
+               buffer += unit;
        }
-       spin_unlock_irq(&tu->qlock);
  _error:
+       spin_unlock_irq(&tu->qlock);
        return result > 0 ? result : err;
 }
 
index e05802ae6e1b1e240a187a43c9f5308fcf7145c0..2e908225d754cfd4f4d23aa40abab01785351456 100644 (file)
@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file,
                                        struct snd_timer_status32 __user *_status)
 {
        struct snd_timer_user *tu;
-       struct snd_timer_status status;
+       struct snd_timer_status32 status;
        
        tu = file->private_data;
        if (snd_BUG_ON(!tu->timeri))
                return -ENXIO;
        memset(&status, 0, sizeof(status));
-       status.tstamp = tu->tstamp;
+       status.tstamp.tv_sec = tu->tstamp.tv_sec;
+       status.tstamp.tv_nsec = tu->tstamp.tv_nsec;
        status.resolution = snd_timer_resolution(tu->timeri);
        status.lost = tu->timeri->lost;
        status.overrun = tu->overrun;
@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file,
        return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has the same struct as x86-64 */
+#define snd_timer_user_status_x32(file, s) \
+       snd_timer_user_status(file, s)
+#endif /* CONFIG_X86_X32 */
+
 /*
  */
 
 enum {
        SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
        SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
+#ifdef CONFIG_X86_X32
+       SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
                return snd_timer_user_info_compat(file, argp);
        case SNDRV_TIMER_IOCTL_STATUS32:
                return snd_timer_user_status_compat(file, argp);
+#ifdef CONFIG_X86_X32
+       case SNDRV_TIMER_IOCTL_STATUS_X32:
+               return snd_timer_user_status_x32(file, argp);
+#endif /* CONFIG_X86_X32 */
        }
        return -ENOIOCTLCMD;
 }
index bde33308f0d6bc697035a627aef2cc24523b195c..c0f8f613f1f1b5e954ffa82b760c82353dd17c80 100644 (file)
@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
 module_param(fake_buffer, bool, 0444);
 MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
 #ifdef CONFIG_HIGH_RES_TIMERS
-module_param(hrtimer, bool, 0444);
+module_param(hrtimer, bool, 0644);
 MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
 #endif
 
@@ -109,6 +109,9 @@ struct dummy_timer_ops {
        snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
 };
 
+#define get_dummy_ops(substream) \
+       (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
+
 struct dummy_model {
        const char *name;
        int (*playback_constraints)(struct snd_pcm_runtime *runtime);
@@ -137,7 +140,6 @@ struct snd_dummy {
        int iobox;
        struct snd_kcontrol *cd_volume_ctl;
        struct snd_kcontrol *cd_switch_ctl;
-       const struct dummy_timer_ops *timer_ops;
 };
 
 /*
@@ -231,6 +233,8 @@ static struct dummy_model *dummy_models[] = {
  */
 
 struct dummy_systimer_pcm {
+       /* ops must be the first item */
+       const struct dummy_timer_ops *timer_ops;
        spinlock_t lock;
        struct timer_list timer;
        unsigned long base_time;
@@ -366,6 +370,8 @@ static const struct dummy_timer_ops dummy_systimer_ops = {
  */
 
 struct dummy_hrtimer_pcm {
+       /* ops must be the first item */
+       const struct dummy_timer_ops *timer_ops;
        ktime_t base_time;
        ktime_t period_time;
        atomic_t running;
@@ -492,31 +498,25 @@ static const struct dummy_timer_ops dummy_hrtimer_ops = {
 
 static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
-               return dummy->timer_ops->start(substream);
+               return get_dummy_ops(substream)->start(substream);
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               return dummy->timer_ops->stop(substream);
+               return get_dummy_ops(substream)->stop(substream);
        }
        return -EINVAL;
 }
 
 static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
 {
-       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
-       return dummy->timer_ops->prepare(substream);
+       return get_dummy_ops(substream)->prepare(substream);
 }
 
 static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
 {
-       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
-       return dummy->timer_ops->pointer(substream);
+       return get_dummy_ops(substream)->pointer(substream);
 }
 
 static struct snd_pcm_hardware dummy_pcm_hardware = {
@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
        struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
        struct dummy_model *model = dummy->model;
        struct snd_pcm_runtime *runtime = substream->runtime;
+       const struct dummy_timer_ops *ops;
        int err;
 
-       dummy->timer_ops = &dummy_systimer_ops;
+       ops = &dummy_systimer_ops;
 #ifdef CONFIG_HIGH_RES_TIMERS
        if (hrtimer)
-               dummy->timer_ops = &dummy_hrtimer_ops;
+               ops = &dummy_hrtimer_ops;
 #endif
 
-       err = dummy->timer_ops->create(substream);
+       err = ops->create(substream);
        if (err < 0)
                return err;
+       get_dummy_ops(substream) = ops;
 
        runtime->hw = dummy->pcm_hw;
        if (substream->pcm->device & 1) {
@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
                        err = model->capture_constraints(substream->runtime);
        }
        if (err < 0) {
-               dummy->timer_ops->free(substream);
+               get_dummy_ops(substream)->free(substream);
                return err;
        }
        return 0;
@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
 
 static int dummy_pcm_close(struct snd_pcm_substream *substream)
 {
-       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-       dummy->timer_ops->free(substream);
+       get_dummy_ops(substream)->free(substream);
        return 0;
 }
 
index b02a5e8cad448c40368b9396dc1c0890c91a3a42..0ac92aba5bc1c9a4c01b1764a6f16a098e3bbae1 100644 (file)
@@ -63,7 +63,7 @@ struct amdtp_dot {
 #define BYTE_PER_SAMPLE (4)
 #define MAGIC_DOT_BYTE (2)
 #define MAGIC_BYTE_OFF(x) (((x) * BYTE_PER_SAMPLE) + MAGIC_DOT_BYTE)
-static const u8 dot_scrt(const u8 idx, const unsigned int off)
+static u8 dot_scrt(const u8 idx, const unsigned int off)
 {
        /*
         * the length of the added pattern only depends on the lower nibble
index 904ce0329fa1ac3d7e3364d66664d6ba60d6b6d8..040a96d1ba8ec1fa1dbfa4521a46e7efb865f435 100644 (file)
@@ -230,6 +230,7 @@ int snd_tscm_transaction_register(struct snd_tscm *tscm)
        return err;
 error:
        fw_core_remove_address_handler(&tscm->async_handler);
+       tscm->async_handler.callback_data = NULL;
        return err;
 }
 
@@ -276,6 +277,9 @@ void snd_tscm_transaction_unregister(struct snd_tscm *tscm)
        __be32 reg;
        unsigned int i;
 
+       if (tscm->async_handler.callback_data == NULL)
+               return;
+
        /* Turn off FireWire LED. */
        reg = cpu_to_be32(0x0000008e);
        snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
@@ -297,6 +301,8 @@ void snd_tscm_transaction_unregister(struct snd_tscm *tscm)
                           &reg, sizeof(reg), 0);
 
        fw_core_remove_address_handler(&tscm->async_handler);
+       tscm->async_handler.callback_data = NULL;
+
        for (i = 0; i < TSCM_MIDI_OUT_PORT_MAX; i++)
                snd_fw_async_midi_port_destroy(&tscm->out_ports[i]);
 }
index ee0bc183950888ba6ade12bb8441fa81be41ec11..e281c338e562d59e861303789d82c319b9a2ae9c 100644 (file)
@@ -21,7 +21,6 @@ static struct snd_tscm_spec model_specs[] = {
                .pcm_playback_analog_channels = 8,
                .midi_capture_ports = 4,
                .midi_playback_ports = 4,
-               .is_controller = true,
        },
        {
                .name = "FW-1082",
@@ -31,9 +30,16 @@ static struct snd_tscm_spec model_specs[] = {
                .pcm_playback_analog_channels = 2,
                .midi_capture_ports = 2,
                .midi_playback_ports = 2,
-               .is_controller = true,
        },
-       /* FW-1804 may be supported. */
+       {
+               .name = "FW-1804",
+               .has_adat = true,
+               .has_spdif = true,
+               .pcm_capture_analog_channels = 8,
+               .pcm_playback_analog_channels = 2,
+               .midi_capture_ports = 2,
+               .midi_playback_ports = 4,
+       },
 };
 
 static int identify_model(struct snd_tscm *tscm)
index 2d028d2bd3bdcdcd8be15a184e555786726c94d8..30ab77e924f7f68f9b939a230109152722ad9057 100644 (file)
@@ -39,7 +39,6 @@ struct snd_tscm_spec {
        unsigned int pcm_playback_analog_channels;
        unsigned int midi_capture_ports;
        unsigned int midi_playback_ports;
-       bool is_controller;
 };
 
 #define TSCM_MIDI_IN_PORT_MAX  4
@@ -72,9 +71,6 @@ struct snd_tscm {
        struct snd_fw_async_midi_port out_ports[TSCM_MIDI_OUT_PORT_MAX];
        u8 running_status[TSCM_MIDI_OUT_PORT_MAX];
        bool on_sysex[TSCM_MIDI_OUT_PORT_MAX];
-
-       /* For control messages. */
-       struct snd_firewire_tascam_status *status;
 };
 
 #define TSCM_ADDR_BASE                 0xffff00000000ull
index b5a17cb510a0b4ee71115973a7d73309e9061b03..8c486235c905253ea0609183d813362a294e42f9 100644 (file)
@@ -426,18 +426,22 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip);
  * @bus: HD-audio core bus
  * @status: INTSTS register value
  * @ask: callback to be called for woken streams
+ *
+ * Returns the bits of handled streams, or zero if no stream is handled.
  */
-void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
+int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
                                    void (*ack)(struct hdac_bus *,
                                                struct hdac_stream *))
 {
        struct hdac_stream *azx_dev;
        u8 sd_status;
+       int handled = 0;
 
        list_for_each_entry(azx_dev, &bus->stream_list, list) {
                if (status & azx_dev->sd_int_sta_mask) {
                        sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
                        snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
+                       handled |= 1 << azx_dev->index;
                        if (!azx_dev->substream || !azx_dev->running ||
                            !(sd_status & SD_INT_COMPLETE))
                                continue;
@@ -445,6 +449,7 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
                                ack(bus, azx_dev);
                }
        }
+       return handled;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq);
 
index 37cf9cee983555ad1a47e4bb43ff2e9db6de39e9..27de8015717d95fdf45ac512a77c60eb32202d67 100644 (file)
@@ -930,6 +930,8 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
        struct azx *chip = dev_id;
        struct hdac_bus *bus = azx_bus(chip);
        u32 status;
+       bool active, handled = false;
+       int repeat = 0; /* count for avoiding endless loop */
 
 #ifdef CONFIG_PM
        if (azx_has_pm_runtime(chip))
@@ -939,33 +941,36 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
 
        spin_lock(&bus->reg_lock);
 
-       if (chip->disabled) {
-               spin_unlock(&bus->reg_lock);
-               return IRQ_NONE;
-       }
-
-       status = azx_readl(chip, INTSTS);
-       if (status == 0 || status == 0xffffffff) {
-               spin_unlock(&bus->reg_lock);
-               return IRQ_NONE;
-       }
+       if (chip->disabled)
+               goto unlock;
 
-       snd_hdac_bus_handle_stream_irq(bus, status, stream_update);
+       do {
+               status = azx_readl(chip, INTSTS);
+               if (status == 0 || status == 0xffffffff)
+                       break;
 
-       /* clear rirb int */
-       status = azx_readb(chip, RIRBSTS);
-       if (status & RIRB_INT_MASK) {
-               if (status & RIRB_INT_RESPONSE) {
-                       if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
-                               udelay(80);
-                       snd_hdac_bus_update_rirb(bus);
+               handled = true;
+               active = false;
+               if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))
+                       active = true;
+
+               /* clear rirb int */
+               status = azx_readb(chip, RIRBSTS);
+               if (status & RIRB_INT_MASK) {
+                       active = true;
+                       if (status & RIRB_INT_RESPONSE) {
+                               if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
+                                       udelay(80);
+                               snd_hdac_bus_update_rirb(bus);
+                       }
+                       azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
                }
-               azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
-       }
+       } while (active && ++repeat < 10);
 
+ unlock:
        spin_unlock(&bus->reg_lock);
 
-       return IRQ_HANDLED;
+       return IRQ_RETVAL(handled);
 }
 EXPORT_SYMBOL_GPL(azx_interrupt);
 
index 30c8efe0f80a3a456bbbe09b6ce05abf810a8552..7ca5b89f088a6922e6acd09c12befae864994320 100644 (file)
@@ -4028,9 +4028,9 @@ static void pin_power_callback(struct hda_codec *codec,
                               struct hda_jack_callback *jack,
                               bool on)
 {
-       if (jack && jack->tbl->nid)
+       if (jack && jack->nid)
                sync_power_state_change(codec,
-                                       set_pin_power_jack(codec, jack->tbl->nid, on));
+                                       set_pin_power_jack(codec, jack->nid, on));
 }
 
 /* callback only doing power up -- called at first */
index 4045dca3d699edd13f06aa9ab7c095948c932a55..e5240cb3749f4186e79f70dfc9e2c6536eaaed1d 100644 (file)
@@ -363,7 +363,10 @@ enum {
                                        ((pci)->device == 0x0d0c) || \
                                        ((pci)->device == 0x160c))
 
-#define IS_BROXTON(pci)        ((pci)->device == 0x5a98)
+#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
+#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
 
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
@@ -540,13 +543,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
 
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                snd_hdac_set_codec_wakeup(bus, true);
-       if (IS_BROXTON(pci)) {
+       if (IS_SKL_PLUS(pci)) {
                pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
                val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
                pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
        }
        azx_init_chip(chip, full_reset);
-       if (IS_BROXTON(pci)) {
+       if (IS_SKL_PLUS(pci)) {
                pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
                val = val | INTEL_HDA_CGCTL_MISCBDCGE;
                pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
@@ -555,7 +558,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
                snd_hdac_set_codec_wakeup(bus, false);
 
        /* reduce dma latency to avoid noise */
-       if (IS_BROXTON(pci))
+       if (IS_BXT(pci))
                bxt_reduce_dma_latency(chip);
 }
 
@@ -977,11 +980,6 @@ static int azx_resume(struct device *dev)
 /* put codec down to D3 at hibernation for Intel SKL+;
  * otherwise BIOS may still access the codec and screw up the driver
  */
-#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
-#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
-#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
-
 static int azx_freeze_noirq(struct device *dev)
 {
        struct pci_dev *pci = to_pci_dev(dev);
@@ -2168,10 +2166,10 @@ static void azx_remove(struct pci_dev *pci)
        struct hda_intel *hda;
 
        if (card) {
-               /* flush the pending probing work */
+               /* cancel the pending probing work */
                chip = card->private_data;
                hda = container_of(chip, struct hda_intel, chip);
-               flush_work(&hda->probe_work);
+               cancel_work_sync(&hda->probe_work);
 
                snd_card_free(card);
        }
index c945e257d368890bcd3f72037568e566c0ba9221..a33234e04d4f7a1fe311ce7db50f1a56e9e1d7d4 100644 (file)
@@ -259,7 +259,7 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
                if (!callback)
                        return ERR_PTR(-ENOMEM);
                callback->func = func;
-               callback->tbl = jack;
+               callback->nid = jack->nid;
                callback->next = jack->callback;
                jack->callback = callback;
        }
index 858708a044f57ef563d79a100c5a92e5f3adaa3d..e9814c0168ea5d77da2922454ed4256d7ad2a30a 100644 (file)
@@ -21,7 +21,7 @@ struct hda_jack_callback;
 typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
 
 struct hda_jack_callback {
-       struct hda_jack_tbl *tbl;
+       hda_nid_t nid;
        hda_jack_callback_fn func;
        unsigned int private_data;      /* arbitrary data */
        struct hda_jack_callback *next;
index 4ef2259f88cae3b1cf328880447dbf528ad42a95..9ceb2bc36e68026bd02dfca8bdca4f9ffab2e849 100644 (file)
@@ -4427,13 +4427,16 @@ static void ca0132_process_dsp_response(struct hda_codec *codec,
 static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
 {
        struct ca0132_spec *spec = codec->spec;
+       struct hda_jack_tbl *tbl;
 
        /* Delay enabling the HP amp, to let the mic-detection
         * state machine run.
         */
        cancel_delayed_work_sync(&spec->unsol_hp_work);
        schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
-       cb->tbl->block_report = 1;
+       tbl = snd_hda_jack_tbl_get(codec, cb->nid);
+       if (tbl)
+               tbl->block_report = 1;
 }
 
 static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
index 1f52b55d77c92d7114ca375d79a43e8f798cc580..bcbc4ee10130a5ee86de2c23815eb85ec8684459 100644 (file)
@@ -448,7 +448,8 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
        eld = &per_pin->sink_eld;
 
        mutex_lock(&per_pin->lock);
-       if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
+       if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
+           eld->eld_size > ELD_MAX_SIZE) {
                mutex_unlock(&per_pin->lock);
                snd_BUG();
                return -EINVAL;
@@ -1193,7 +1194,7 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid)
 static void jack_callback(struct hda_codec *codec,
                          struct hda_jack_callback *jack)
 {
-       check_presence_and_report(codec, jack->tbl->nid);
+       check_presence_and_report(codec, jack->nid);
 }
 
 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -2476,13 +2477,6 @@ static int patch_generic_hdmi(struct hda_codec *codec)
                        is_broxton(codec))
                codec->core.link_power_control = 1;
 
-       if (codec_has_acomp(codec)) {
-               codec->depop_delay = 0;
-               spec->i915_audio_ops.audio_ptr = codec;
-               spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
-               snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
-       }
-
        if (hdmi_parse_codec(codec) < 0) {
                if (spec->i915_bound)
                        snd_hdac_i915_exit(&codec->bus->core);
@@ -2504,6 +2498,18 @@ static int patch_generic_hdmi(struct hda_codec *codec)
 
        init_channel_allocations();
 
+       if (codec_has_acomp(codec)) {
+               codec->depop_delay = 0;
+               spec->i915_audio_ops.audio_ptr = codec;
+               /* intel_audio_codec_enable() or intel_audio_codec_disable()
+                * will call pin_eld_notify with using audio_ptr pointer
+                * We need make sure audio_ptr is really setup
+                */
+               wmb();
+               spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
+               snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
+       }
+
        return 0;
 }
 
index 21992fb7035d456c6bac7124c7a4b350ae88fc64..93d2156b62410935f3c0f945f0d5d8a2fe182eba 100644 (file)
@@ -282,7 +282,7 @@ static void alc_update_knob_master(struct hda_codec *codec,
        uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
        if (!uctl)
                return;
-       val = snd_hda_codec_read(codec, jack->tbl->nid, 0,
+       val = snd_hda_codec_read(codec, jack->nid, 0,
                                 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
        val &= HDA_AMP_VOLMASK;
        uctl->value.integer.value[0] = val;
@@ -1787,7 +1787,6 @@ enum {
        ALC882_FIXUP_NO_PRIMARY_HP,
        ALC887_FIXUP_ASUS_BASS,
        ALC887_FIXUP_BASS_CHMAP,
-       ALC882_FIXUP_DISABLE_AAMIX,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -1949,8 +1948,6 @@ 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 void alc_fixup_disable_aamix(struct hda_codec *codec,
-                                   const struct hda_fixup *fix, int action);
 
 static const struct hda_fixup alc882_fixups[] = {
        [ALC882_FIXUP_ABIT_AW9D_MAX] = {
@@ -2188,10 +2185,6 @@ static const struct hda_fixup alc882_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_bass_chmap,
        },
-       [ALC882_FIXUP_DISABLE_AAMIX] = {
-               .type = HDA_FIXUP_FUNC,
-               .v.func = alc_fixup_disable_aamix,
-       },
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2230,6 +2223,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        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),
+       SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
 
        /* All Apple entries are in codec SSIDs */
        SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
@@ -2259,7 +2253,6 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -3808,6 +3801,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
 
 static void alc_headset_mode_default(struct hda_codec *codec)
 {
+       static struct coef_fw coef0225[] = {
+               UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
+               {}
+       };
        static struct coef_fw coef0255[] = {
                WRITE_COEF(0x45, 0xc089),
                WRITE_COEF(0x45, 0xc489),
@@ -3849,6 +3846,9 @@ static void alc_headset_mode_default(struct hda_codec *codec)
        };
 
        switch (codec->core.vendor_id) {
+       case 0x10ec0225:
+               alc_process_coef_fw(codec, coef0225);
+               break;
        case 0x10ec0255:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
@@ -4756,6 +4756,9 @@ enum {
        ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
        ALC293_FIXUP_LENOVO_SPK_NOISE,
        ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
+       ALC255_FIXUP_DELL_SPK_NOISE,
+       ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+       ALC280_FIXUP_HP_HEADSET_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5375,6 +5378,29 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
        },
+       [ALC255_FIXUP_DELL_SPK_NOISE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
+       [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Disable pass-through path for FRONT 14h */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
+       [ALC280_FIXUP_HP_HEADSET_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5386,6 +5412,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
        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(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
        SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
@@ -5417,6 +5444,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+       SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5477,6 +5505,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
        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),
@@ -5645,10 +5674,10 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {0x21, 0x03211020}
 
 static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
-       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC225_STANDARD_PINS,
                {0x14, 0x901701a0}),
-       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC225_STANDARD_PINS,
                {0x14, 0x901701b0}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
index 2c7c5eb8b1e9514779b78bc278412803862062e9..37b70f8e878f715968c7496e01eeb493f8a2b7a4 100644 (file)
@@ -493,9 +493,9 @@ static void jack_update_power(struct hda_codec *codec,
        if (!spec->num_pwrs)
                return;
 
-       if (jack && jack->tbl->nid) {
-               stac_toggle_power_map(codec, jack->tbl->nid,
-                                     snd_hda_jack_detect(codec, jack->tbl->nid),
+       if (jack && jack->nid) {
+               stac_toggle_power_map(codec, jack->nid,
+                                     snd_hda_jack_detect(codec, jack->nid),
                                      true);
                return;
        }
index 2875b4f6d8c9e6a792638547d4b6850fa620a857..7c8941b8b2defd9b21b8159f1cef333659ce423d 100644 (file)
@@ -2879,7 +2879,7 @@ static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl
 {
        struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 
-       ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
+       ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp);
        return 0;
 }
 
@@ -2891,7 +2891,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl
 
        if (!snd_hdsp_use_is_exclusive(hdsp))
                return -EBUSY;
-       val = ucontrol->value.enumerated.item[0];
+       val = ucontrol->value.integer.value[0];
        spin_lock_irq(&hdsp->lock);
        if (val != hdsp_dds_offset(hdsp))
                change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
index 8bc8016c173d6a6005e33222df1381272bb7819e..a4a999a0317eaefc30eeb2265fd38b784c4afd8a 100644 (file)
@@ -1601,6 +1601,9 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
 {
        u64 n;
 
+       if (snd_BUG_ON(rate <= 0))
+               return;
+
        if (rate >= 112000)
                rate /= 4;
        else if (rate >= 56000)
@@ -2215,6 +2218,8 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
                } else {
                        /* slave mode, return external sample rate */
                        rate = hdspm_external_sample_rate(hdspm);
+                       if (!rate)
+                               rate = hdspm->system_sample_rate;
                }
        }
 
@@ -2260,8 +2265,11 @@ static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
                                            ucontrol)
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+       int rate = ucontrol->value.integer.value[0];
 
-       hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+       if (rate < 27000 || rate > 207000)
+               return -EINVAL;
+       hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
        return 0;
 }
 
@@ -4449,7 +4457,7 @@ static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-       ucontrol->value.enumerated.item[0] = hdspm->tco->term;
+       ucontrol->value.integer.value[0] = hdspm->tco->term;
 
        return 0;
 }
@@ -4460,8 +4468,8 @@ static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-       if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
-               hdspm->tco->term = ucontrol->value.enumerated.item[0];
+       if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
+               hdspm->tco->term = ucontrol->value.integer.value[0];
 
                hdspm_tco_write(hdspm);
 
index ba8def5665c458842d2f333d35e34c2974b2136e..276897033639b0d719d0d4408e1ffb9ec9efe90d 100644 (file)
@@ -285,7 +285,8 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params,
 static int atmel_ssc_startup(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
-       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct platform_device *pdev = to_platform_device(dai->dev);
+       struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id];
        struct atmel_pcm_dma_params *dma_params;
        int dir, dir_mask;
        int ret;
@@ -346,7 +347,8 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
 static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *dai)
 {
-       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct platform_device *pdev = to_platform_device(dai->dev);
+       struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id];
        struct atmel_pcm_dma_params *dma_params;
        int dir, dir_mask;
 
@@ -392,7 +394,8 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
 static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
-       struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+       struct platform_device *pdev = to_platform_device(cpu_dai->dev);
+       struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id];
 
        ssc_p->daifmt = fmt;
        return 0;
@@ -404,7 +407,8 @@ static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
        int div_id, int div)
 {
-       struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+       struct platform_device *pdev = to_platform_device(cpu_dai->dev);
+       struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id];
 
        switch (div_id) {
        case ATMEL_SSC_CMR_DIV:
@@ -445,7 +449,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
        struct snd_soc_dai *dai)
 {
-       int id = dai->id;
+       struct platform_device *pdev = to_platform_device(dai->dev);
+       int id = pdev->id;
        struct atmel_ssc_info *ssc_p = &ssc_info[id];
        struct ssc_device *ssc = ssc_p->ssc;
        struct atmel_pcm_dma_params *dma_params;
@@ -772,7 +777,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
-       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct platform_device *pdev = to_platform_device(dai->dev);
+       struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id];
        struct atmel_pcm_dma_params *dma_params;
        int dir;
 
@@ -795,7 +801,8 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 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 platform_device *pdev = to_platform_device(dai->dev);
+       struct atmel_ssc_info *ssc_p = &ssc_info[pdev->id];
        struct atmel_pcm_dma_params *dma_params;
        int dir;
 
@@ -824,11 +831,12 @@ static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
 static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
 {
        struct atmel_ssc_info *ssc_p;
+       struct platform_device *pdev = to_platform_device(cpu_dai->dev);
 
        if (!cpu_dai->active)
                return 0;
 
-       ssc_p = &ssc_info[cpu_dai->id];
+       ssc_p = &ssc_info[pdev->id];
 
        /* Save the status register before disabling transmit and receive */
        ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
@@ -852,12 +860,13 @@ static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
 static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
 {
        struct atmel_ssc_info *ssc_p;
+       struct platform_device *pdev = to_platform_device(cpu_dai->dev);
        u32 cr;
 
        if (!cpu_dai->active)
                return 0;
 
-       ssc_p = &ssc_info[cpu_dai->id];
+       ssc_p = &ssc_info[pdev->id];
 
        /* restore SSC register settings */
        ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
index 3303d5f58082f68b68b535b2bdf7ce8d14cafcc4..1c1f2210387b26e9551959378f6792f18648652e 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 
 #include <sound/core.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-/* Clock registers */
-#define BCM2835_CLK_PCMCTL_REG  0x00
-#define BCM2835_CLK_PCMDIV_REG  0x04
-
-/* Clock register settings */
-#define BCM2835_CLK_PASSWD             (0x5a000000)
-#define BCM2835_CLK_PASSWD_MASK        (0xff000000)
-#define BCM2835_CLK_MASH(v)            ((v) << 9)
-#define BCM2835_CLK_FLIP               BIT(8)
-#define BCM2835_CLK_BUSY               BIT(7)
-#define BCM2835_CLK_KILL               BIT(5)
-#define BCM2835_CLK_ENAB               BIT(4)
-#define BCM2835_CLK_SRC(v)             (v)
-
-#define BCM2835_CLK_SHIFT              (12)
-#define BCM2835_CLK_DIVI(v)            ((v) << BCM2835_CLK_SHIFT)
-#define BCM2835_CLK_DIVF(v)            (v)
-#define BCM2835_CLK_DIVF_MASK          (0xFFF)
-
-enum {
-       BCM2835_CLK_MASH_0 = 0,
-       BCM2835_CLK_MASH_1,
-       BCM2835_CLK_MASH_2,
-       BCM2835_CLK_MASH_3,
-};
-
-enum {
-       BCM2835_CLK_SRC_GND = 0,
-       BCM2835_CLK_SRC_OSC,
-       BCM2835_CLK_SRC_DBG0,
-       BCM2835_CLK_SRC_DBG1,
-       BCM2835_CLK_SRC_PLLA,
-       BCM2835_CLK_SRC_PLLC,
-       BCM2835_CLK_SRC_PLLD,
-       BCM2835_CLK_SRC_HDMI,
-};
-
-/* Most clocks are not useable (freq = 0) */
-static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = {
-       [BCM2835_CLK_SRC_GND]           = 0,
-       [BCM2835_CLK_SRC_OSC]           = 19200000,
-       [BCM2835_CLK_SRC_DBG0]          = 0,
-       [BCM2835_CLK_SRC_DBG1]          = 0,
-       [BCM2835_CLK_SRC_PLLA]          = 0,
-       [BCM2835_CLK_SRC_PLLC]          = 0,
-       [BCM2835_CLK_SRC_PLLD]          = 500000000,
-       [BCM2835_CLK_SRC_HDMI]          = 0,
-};
-
 /* I2S registers */
 #define BCM2835_I2S_CS_A_REG           0x00
 #define BCM2835_I2S_FIFO_A_REG         0x04
@@ -158,10 +110,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = {
 #define BCM2835_I2S_INT_RXR            BIT(1)
 #define BCM2835_I2S_INT_TXW            BIT(0)
 
-/* I2S DMA interface */
-/* FIXME: Needs IOMMU support */
-#define BCM2835_VCMMU_SHIFT            (0x7E000000 - 0x20000000)
-
 /* General device struct */
 struct bcm2835_i2s_dev {
        struct device                           *dev;
@@ -169,21 +117,23 @@ struct bcm2835_i2s_dev {
        unsigned int                            fmt;
        unsigned int                            bclk_ratio;
 
-       struct regmap *i2s_regmap;
-       struct regmap *clk_regmap;
+       struct regmap                           *i2s_regmap;
+       struct clk                              *clk;
+       bool                                    clk_prepared;
 };
 
 static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev)
 {
-       /* Start the clock if in master mode */
        unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
 
+       if (dev->clk_prepared)
+               return;
+
        switch (master) {
        case SND_SOC_DAIFMT_CBS_CFS:
        case SND_SOC_DAIFMT_CBS_CFM:
-               regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
-                       BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB,
-                       BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB);
+               clk_prepare_enable(dev->clk);
+               dev->clk_prepared = true;
                break;
        default:
                break;
@@ -192,28 +142,9 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev)
 
 static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev)
 {
-       uint32_t clkreg;
-       int timeout = 1000;
-
-       /* Stop clock */
-       regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
-                       BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB,
-                       BCM2835_CLK_PASSWD);
-
-       /* Wait for the BUSY flag going down */
-       while (--timeout) {
-               regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg);
-               if (!(clkreg & BCM2835_CLK_BUSY))
-                       break;
-       }
-
-       if (!timeout) {
-               /* KILL the clock */
-               dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n");
-               regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
-                       BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK,
-                       BCM2835_CLK_KILL | BCM2835_CLK_PASSWD);
-       }
+       if (dev->clk_prepared)
+               clk_disable_unprepare(dev->clk);
+       dev->clk_prepared = false;
 }
 
 static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev,
@@ -223,8 +154,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev,
        uint32_t syncval;
        uint32_t csreg;
        uint32_t i2s_active_state;
-       uint32_t clkreg;
-       uint32_t clk_active_state;
+       bool clk_was_prepared;
        uint32_t off;
        uint32_t clr;
 
@@ -238,15 +168,10 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev,
        regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);
        i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON);
 
-       regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg);
-       clk_active_state = clkreg & BCM2835_CLK_ENAB;
-
        /* Start clock if not running */
-       if (!clk_active_state) {
-               regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
-                       BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB,
-                       BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB);
-       }
+       clk_was_prepared = dev->clk_prepared;
+       if (!clk_was_prepared)
+               bcm2835_i2s_start_clock(dev);
 
        /* Stop I2S module */
        regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0);
@@ -280,7 +205,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev,
                dev_err(dev->dev, "I2S SYNC error!\n");
 
        /* Stop clock if it was not running before */
-       if (!clk_active_state)
+       if (!clk_was_prepared)
                bcm2835_i2s_stop_clock(dev);
 
        /* Restore I2S state */
@@ -309,19 +234,9 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *dai)
 {
        struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
-
        unsigned int sampling_rate = params_rate(params);
        unsigned int data_length, data_delay, bclk_ratio;
        unsigned int ch1pos, ch2pos, mode, format;
-       unsigned int mash = BCM2835_CLK_MASH_1;
-       unsigned int divi, divf, target_frequency;
-       int clk_src = -1;
-       unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
-       bool bit_master =       (master == SND_SOC_DAIFMT_CBS_CFS
-                                       || master == SND_SOC_DAIFMT_CBS_CFM);
-
-       bool frame_master =     (master == SND_SOC_DAIFMT_CBS_CFS
-                                       || master == SND_SOC_DAIFMT_CBM_CFS);
        uint32_t csreg;
 
        /*
@@ -343,11 +258,9 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                data_length = 16;
-               bclk_ratio = 40;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                data_length = 32;
-               bclk_ratio = 80;
                break;
        default:
                return -EINVAL;
@@ -356,69 +269,12 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
        /* If bclk_ratio already set, use that one. */
        if (dev->bclk_ratio)
                bclk_ratio = dev->bclk_ratio;
+       else
+               /* otherwise calculate a fitting block ratio */
+               bclk_ratio = 2 * data_length;
 
-       /*
-        * Clock Settings
-        *
-        * The target frequency of the bit clock is
-        *      sampling rate * frame length
-        *
-        * Integer mode:
-        * Sampling rates that are multiples of 8000 kHz
-        * can be driven by the oscillator of 19.2 MHz
-        * with an integer divider as long as the frame length
-        * is an integer divider of 19200000/8000=2400 as set up above.
-        * This is no longer possible if the sampling rate
-        * is too high (e.g. 192 kHz), because the oscillator is too slow.
-        *
-        * MASH mode:
-        * For all other sampling rates, it is not possible to
-        * have an integer divider. Approximate the clock
-        * with the MASH module that induces a slight frequency
-        * variance. To minimize that it is best to have the fastest
-        * clock here. That is PLLD with 500 MHz.
-        */
-       target_frequency = sampling_rate * bclk_ratio;
-       clk_src = BCM2835_CLK_SRC_OSC;
-       mash = BCM2835_CLK_MASH_0;
-
-       if (bcm2835_clk_freq[clk_src] % target_frequency == 0
-                       && bit_master && frame_master) {
-               divi = bcm2835_clk_freq[clk_src] / target_frequency;
-               divf = 0;
-       } else {
-               uint64_t dividend;
-
-               if (!dev->bclk_ratio) {
-                       /*
-                        * Overwrite bclk_ratio, because the
-                        * above trick is not needed or can
-                        * not be used.
-                        */
-                       bclk_ratio = 2 * data_length;
-               }
-
-               target_frequency = sampling_rate * bclk_ratio;
-
-               clk_src = BCM2835_CLK_SRC_PLLD;
-               mash = BCM2835_CLK_MASH_1;
-
-               dividend = bcm2835_clk_freq[clk_src];
-               dividend <<= BCM2835_CLK_SHIFT;
-               do_div(dividend, target_frequency);
-               divi = dividend >> BCM2835_CLK_SHIFT;
-               divf = dividend & BCM2835_CLK_DIVF_MASK;
-       }
-
-       /* Set clock divider */
-       regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD
-                       | BCM2835_CLK_DIVI(divi)
-                       | BCM2835_CLK_DIVF(divf));
-
-       /* Setup clock, but don't start it yet */
-       regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD
-                       | BCM2835_CLK_MASH(mash)
-                       | BCM2835_CLK_SRC(clk_src));
+       /* set target clock rate*/
+       clk_set_rate(dev->clk, sampling_rate * bclk_ratio);
 
        /* Setup the frame format */
        format = BCM2835_I2S_CHEN;
@@ -692,7 +548,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = {
        .trigger        = bcm2835_i2s_trigger,
        .hw_params      = bcm2835_i2s_hw_params,
        .set_fmt        = bcm2835_i2s_set_dai_fmt,
-       .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio
+       .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio,
 };
 
 static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai)
@@ -750,34 +606,14 @@ static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg)
        };
 }
 
-static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg)
-{
-       switch (reg) {
-       case BCM2835_CLK_PCMCTL_REG:
-               return true;
-       default:
-               return false;
-       };
-}
-
-static const struct regmap_config bcm2835_regmap_config[] = {
-       {
-               .reg_bits = 32,
-               .reg_stride = 4,
-               .val_bits = 32,
-               .max_register = BCM2835_I2S_GRAY_REG,
-               .precious_reg = bcm2835_i2s_precious_reg,
-               .volatile_reg = bcm2835_i2s_volatile_reg,
-               .cache_type = REGCACHE_RBTREE,
-       },
-       {
-               .reg_bits = 32,
-               .reg_stride = 4,
-               .val_bits = 32,
-               .max_register = BCM2835_CLK_PCMDIV_REG,
-               .volatile_reg = bcm2835_clk_volatile_reg,
-               .cache_type = REGCACHE_RBTREE,
-       },
+static const struct regmap_config bcm2835_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = BCM2835_I2S_GRAY_REG,
+       .precious_reg = bcm2835_i2s_precious_reg,
+       .volatile_reg = bcm2835_i2s_volatile_reg,
+       .cache_type = REGCACHE_RBTREE,
 };
 
 static const struct snd_soc_component_driver bcm2835_i2s_component = {
@@ -787,42 +623,50 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = {
 static int bcm2835_i2s_probe(struct platform_device *pdev)
 {
        struct bcm2835_i2s_dev *dev;
-       int i;
        int ret;
-       struct regmap *regmap[2];
-       struct resource *mem[2];
-
-       /* Request both ioareas */
-       for (i = 0; i <= 1; i++) {
-               void __iomem *base;
-
-               mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               base = devm_ioremap_resource(&pdev->dev, mem[i]);
-               if (IS_ERR(base))
-                       return PTR_ERR(base);
-
-               regmap[i] = devm_regmap_init_mmio(&pdev->dev, base,
-                                           &bcm2835_regmap_config[i]);
-               if (IS_ERR(regmap[i]))
-                       return PTR_ERR(regmap[i]);
-       }
+       struct resource *mem;
+       void __iomem *base;
+       const __be32 *addr;
+       dma_addr_t dma_base;
 
        dev = devm_kzalloc(&pdev->dev, sizeof(*dev),
                           GFP_KERNEL);
        if (!dev)
                return -ENOMEM;
 
-       dev->i2s_regmap = regmap[0];
-       dev->clk_regmap = regmap[1];
+       /* get the clock */
+       dev->clk_prepared = false;
+       dev->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dev->clk)) {
+               dev_err(&pdev->dev, "could not get clk: %ld\n",
+                       PTR_ERR(dev->clk));
+               return PTR_ERR(dev->clk);
+       }
+
+       /* Request ioarea */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       dev->i2s_regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                               &bcm2835_regmap_config);
+       if (IS_ERR(dev->i2s_regmap))
+               return PTR_ERR(dev->i2s_regmap);
+
+       /* Set the DMA address - we have to parse DT ourselves */
+       addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
+       if (!addr) {
+               dev_err(&pdev->dev, "could not get DMA-register address\n");
+               return -EINVAL;
+       }
+       dma_base = be32_to_cpup(addr);
 
-       /* Set the DMA address */
        dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
-               (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG
-                                         + BCM2835_VCMMU_SHIFT;
+               dma_base + BCM2835_I2S_FIFO_A_REG;
 
        dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
-               (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG
-                                         + BCM2835_VCMMU_SHIFT;
+               dma_base + BCM2835_I2S_FIFO_A_REG;
 
        /* Set the bus width */
        dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width =
index 50693c867e71d06a2b6ccebf0d2f303c1ef9a0f5..b414a92b677a0da684a695f319e2da0c4c58fd19 100644 (file)
@@ -79,7 +79,9 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_MAX98090 if I2C
        select SND_SOC_MAX98095 if I2C
        select SND_SOC_MAX98357A if GPIOLIB
+       select SND_SOC_MAX9867 if I2C
        select SND_SOC_MAX98925 if I2C
+       select SND_SOC_MAX98926 if I2C
        select SND_SOC_MAX9850 if I2C
        select SND_SOC_MAX9768 if I2C
        select SND_SOC_MAX9877 if I2C
@@ -87,7 +89,8 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_ML26124 if I2C
        select SND_SOC_NAU8825 if I2C
        select SND_SOC_PCM1681 if I2C
-       select SND_SOC_PCM179X if SPI_MASTER
+       select SND_SOC_PCM179X_I2C if I2C
+       select SND_SOC_PCM179X_SPI if SPI_MASTER
        select SND_SOC_PCM3008
        select SND_SOC_PCM3168A_I2C if I2C
        select SND_SOC_PCM3168A_SPI if SPI_MASTER
@@ -490,6 +493,7 @@ config SND_SOC_GTM601
 config SND_SOC_HDAC_HDMI
        tristate
        select SND_HDA_EXT_CORE
+       select SND_PCM_ELD
        select HDMI
 
 config SND_SOC_ICS43432
@@ -516,9 +520,15 @@ config SND_SOC_MAX98095
 config SND_SOC_MAX98357A
        tristate
 
+config SND_SOC_MAX9867
+       tristate
+
 config SND_SOC_MAX98925
        tristate
 
+config SND_SOC_MAX98926
+       tristate
+
 config SND_SOC_MAX9850
        tristate
 
@@ -527,8 +537,23 @@ config SND_SOC_PCM1681
        depends on I2C
 
 config SND_SOC_PCM179X
-       tristate "Texas Instruments PCM179X CODEC"
+       tristate
+
+config SND_SOC_PCM179X_I2C
+       tristate "Texas Instruments PCM179X CODEC (I2C)"
+       depends on I2C
+       select SND_SOC_PCM179X
+       help
+         Enable support for Texas Instruments PCM179x CODEC.
+         Select this if your PCM179x is connected via an I2C bus.
+
+config SND_SOC_PCM179X_SPI
+       tristate "Texas Instruments PCM179X CODEC (SPI)"
        depends on SPI_MASTER
+       select SND_SOC_PCM179X
+       help
+         Enable support for Texas Instruments PCM179x CODEC.
+         Select this if your PCM179x is connected via an SPI bus.
 
 config SND_SOC_PCM3008
        tristate
index d44f7d347183cbe9a0aca29826b9c6477c52d6c4..d10418ccd181576c61fef6f71bad88ee54bb8e95 100644 (file)
@@ -74,13 +74,17 @@ snd-soc-max98088-objs := max98088.o
 snd-soc-max98090-objs := max98090.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max98357a-objs := max98357a.o
+snd-soc-max9867-objs := max9867.o
 snd-soc-max98925-objs := max98925.o
+snd-soc-max98926-objs := max98926.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-nau8825-objs := nau8825.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm179x-codec-objs := pcm179x.o
+snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o
+snd-soc-pcm179x-spi-objs := pcm179x-spi.o
 snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-pcm3168a-objs := pcm3168a.o
 snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o
@@ -278,13 +282,17 @@ obj-$(CONFIG_SND_SOC_MAX98088)    += snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o
 obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX98357A)        += snd-soc-max98357a.o
+obj-$(CONFIG_SND_SOC_MAX9867)  += snd-soc-max9867.o
 obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
+obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
 obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)  += snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)  += snd-soc-ml26124.o
 obj-$(CONFIG_SND_SOC_NAU8825)   += snd-soc-nau8825.o
 obj-$(CONFIG_SND_SOC_PCM1681)  += snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM179X)  += snd-soc-pcm179x-codec.o
+obj-$(CONFIG_SND_SOC_PCM179X_I2C)      += snd-soc-pcm179x-i2c.o
+obj-$(CONFIG_SND_SOC_PCM179X_SPI)      += snd-soc-pcm179x-spi.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o
 obj-$(CONFIG_SND_SOC_PCM3168A_I2C)     += snd-soc-pcm3168a-i2c.o
index affb192238a403b88dc38f3e76e0c54440779ea0..8b1d0c1a783982f77318a6482e5639277abd12a8 100644 (file)
@@ -1130,7 +1130,7 @@ static int sid_status_control_get(struct snd_kcontrol *kcontrol,
        struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 
        mutex_lock(&drvdata->ctrl_lock);
-       ucontrol->value.integer.value[0] = drvdata->sid_status;
+       ucontrol->value.enumerated.item[0] = drvdata->sid_status;
        mutex_unlock(&drvdata->ctrl_lock);
 
        return 0;
@@ -1147,7 +1147,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol,
 
        dev_dbg(codec->dev, "%s: Enter\n", __func__);
 
-       if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) {
+       if (ucontrol->value.enumerated.item[0] != SID_APPLY_FIR) {
                dev_err(codec->dev,
                        "%s: ERROR: This control supports '%s' only!\n",
                        __func__, enum_sid_state[SID_APPLY_FIR]);
@@ -1199,7 +1199,7 @@ static int anc_status_control_get(struct snd_kcontrol *kcontrol,
        struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 
        mutex_lock(&drvdata->ctrl_lock);
-       ucontrol->value.integer.value[0] = drvdata->anc_status;
+       ucontrol->value.enumerated.item[0] = drvdata->anc_status;
        mutex_unlock(&drvdata->ctrl_lock);
 
        return 0;
@@ -1220,7 +1220,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
 
        mutex_lock(&drvdata->ctrl_lock);
 
-       req = ucontrol->value.integer.value[0];
+       req = ucontrol->value.enumerated.item[0];
        if (req >= ARRAY_SIZE(enum_anc_state)) {
                status = -EINVAL;
                goto cleanup;
@@ -2134,7 +2134,6 @@ static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                        "%s: ERROR: Unsupporter master mask 0x%x\n",
                        __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
                return -EINVAL;
-               break;
        }
 
        snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val);
index 348ccb17d3cc9c435e50cd11804e7dfb597906cd..8de010f758cd8d5007cf661a590f6e7c473da385 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
  *
  * Copyright 2014 Analog Devices Inc.
  *  Author: Lars-Peter Clausen <lars@metafoo.de>
@@ -44,9 +44,21 @@ static const struct i2c_device_id adau1761_i2c_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids);
 
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1761_i2c_dt_ids[] = {
+       { .compatible = "adi,adau1361", },
+       { .compatible = "adi,adau1461", },
+       { .compatible = "adi,adau1761", },
+       { .compatible = "adi,adau1961", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, adau1761_i2c_dt_ids);
+#endif
+
 static struct i2c_driver adau1761_i2c_driver = {
        .driver = {
                .name = "adau1761",
+               .of_match_table = of_match_ptr(adau1761_i2c_dt_ids),
        },
        .probe = adau1761_i2c_probe,
        .remove = adau1761_i2c_remove,
index 8bc1fbd25fccccd1c31c66f7a0bcb31eff07af01..d9171245bd9f11a177ce2429c0cbf50ef159af9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
  *
  * Copyright 2014 Analog Devices Inc.
  *  Author: Lars-Peter Clausen <lars@metafoo.de>
@@ -61,9 +61,21 @@ static const struct spi_device_id adau1761_spi_id[] = {
 };
 MODULE_DEVICE_TABLE(spi, adau1761_spi_id);
 
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1761_spi_dt_ids[] = {
+       { .compatible = "adi,adau1361", },
+       { .compatible = "adi,adau1461", },
+       { .compatible = "adi,adau1761", },
+       { .compatible = "adi,adau1961", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, adau1761_spi_dt_ids);
+#endif
+
 static struct spi_driver adau1761_spi_driver = {
        .driver = {
                .name = "adau1761",
+               .of_match_table = of_match_ptr(adau1761_spi_dt_ids),
        },
        .probe = adau1761_spi_probe,
        .remove = adau1761_spi_remove,
index 2f12477e539ebe36f90af0218ee83031b0ac178d..b95d29dbd13dcfe6fb00722bfc980122e7b74286 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
+ * Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
  *
  * Copyright 2011-2013 Analog Devices Inc.
  * Author: Lars-Peter Clausen <lars@metafoo.de>
@@ -456,13 +456,17 @@ static int adau1761_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               regcache_cache_only(adau->regmap, false);
                regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
                        ADAU17X1_CLOCK_CONTROL_SYSCLK_EN,
                        ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
+               if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
+                       regcache_sync(adau->regmap);
                break;
        case SND_SOC_BIAS_OFF:
                regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
                        ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0);
+               regcache_cache_only(adau->regmap, true);
                break;
 
        }
@@ -783,6 +787,10 @@ int adau1761_probe(struct device *dev, struct regmap *regmap,
        if (ret)
                return ret;
 
+       /* Enable cache only mode as we could miss writes before bias level
+        * reaches standby and the core clock is enabled */
+       regcache_cache_only(regmap, true);
+
        return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1);
 }
 EXPORT_SYMBOL_GPL(adau1761_probe);
index 0e32bba92339b17182980c426818c0b58d2c21a7..06cbca84cf02150ab0a83bbf114955ffe6ea62d1 100644 (file)
@@ -42,9 +42,19 @@ static const struct i2c_device_id adau1781_i2c_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
 
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1781_i2c_dt_ids[] = {
+       { .compatible = "adi,adau1381", },
+       { .compatible = "adi,adau1781", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, adau1781_i2c_dt_ids);
+#endif
+
 static struct i2c_driver adau1781_i2c_driver = {
        .driver = {
                .name = "adau1781",
+               .of_match_table = of_match_ptr(adau1781_i2c_dt_ids),
        },
        .probe = adau1781_i2c_probe,
        .remove = adau1781_i2c_remove,
index 33a73ff78de4d2a980146c78b6374f67c0cabb80..3d965a01b99cee318da30a080baebc8a060852cc 100644 (file)
@@ -59,9 +59,19 @@ static const struct spi_device_id adau1781_spi_id[] = {
 };
 MODULE_DEVICE_TABLE(spi, adau1781_spi_id);
 
+#if defined(CONFIG_OF)
+static const struct of_device_id adau1781_spi_dt_ids[] = {
+       { .compatible = "adi,adau1381", },
+       { .compatible = "adi,adau1781", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, adau1781_spi_dt_ids);
+#endif
+
 static struct spi_driver adau1781_spi_driver = {
        .driver = {
                .name = "adau1781",
+               .of_match_table = of_match_ptr(adau1781_spi_dt_ids),
        },
        .probe = adau1781_spi_probe,
        .remove = adau1781_spi_remove,
index fde9068550a6801b6ffbb538fcec13ccacc24f5f..bc1bb56dae63cd1101ca6b9e6823af9d1b01a0ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Driver for ADAU1781/ADAU1781 codec
+ * Driver for ADAU1381/ADAU1781 codec
  *
  * Copyright 2011-2013 Analog Devices Inc.
  * Author: Lars-Peter Clausen <lars@metafoo.de>
index e13583e6ff56aa5d69a163ca7a447acdaa18cbd6..5ae87a084d97e24a6aa243ba6cb1afc45290ac43 100644 (file)
@@ -103,9 +103,9 @@ bool adau17x1_has_dsp(struct adau *adau);
 #define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3)
 #define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN       BIT(0)
 
-#define ADAU17X1_SERIAL_PORT1_BCLK32           (0x0 << 5)
-#define ADAU17X1_SERIAL_PORT1_BCLK48           (0x1 << 5)
-#define ADAU17X1_SERIAL_PORT1_BCLK64           (0x2 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK64           (0x0 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK32           (0x1 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK48           (0x2 << 5)
 #define ADAU17X1_SERIAL_PORT1_BCLK128          (0x3 << 5)
 #define ADAU17X1_SERIAL_PORT1_BCLK256          (0x4 << 5)
 #define ADAU17X1_SERIAL_PORT1_BCLK_MASK                (0x7 << 5)
index 1222282e93c3ebd769605bdc177ccec32cbbe204..c5be1bdc2c9abfbeb61082e118fa2971db1258af 100644 (file)
@@ -20,6 +20,8 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
+#include <linux/of.h>
+
 #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
 #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
 
@@ -75,9 +77,19 @@ static int ads117x_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id ads117x_dt_ids[] = {
+       { .compatible = "ti,ads1174" },
+       { .compatible = "ti,ads1178" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, ads117x_dt_ids);
+#endif
+
 static struct platform_driver ads117x_codec_driver = {
        .driver = {
                        .name = "ads117x-codec",
+                       .of_match_table = of_match_ptr(ads117x_dt_ids),
        },
 
        .probe = ads117x_probe,
index 91785318b2834f325b2ebfb55476ce591b5e377b..92d22a018d68bf13bf57def12d6c2c82e1e9d933 100644 (file)
@@ -1398,29 +1398,6 @@ static const int arizona_48k_bclk_rates[] = {
        24576000,
 };
 
-static const unsigned int arizona_48k_rates[] = {
-       12000,
-       24000,
-       48000,
-       96000,
-       192000,
-       384000,
-       768000,
-       4000,
-       8000,
-       16000,
-       32000,
-       64000,
-       128000,
-       256000,
-       512000,
-};
-
-static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
-       .count  = ARRAY_SIZE(arizona_48k_rates),
-       .list   = arizona_48k_rates,
-};
-
 static const int arizona_44k1_bclk_rates[] = {
        -1,
        44100,
@@ -1443,22 +1420,7 @@ static const int arizona_44k1_bclk_rates[] = {
        22579200,
 };
 
-static const unsigned int arizona_44k1_rates[] = {
-       11025,
-       22050,
-       44100,
-       88200,
-       176400,
-       352800,
-       705600,
-};
-
-static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
-       .count  = ARRAY_SIZE(arizona_44k1_rates),
-       .list   = arizona_44k1_rates,
-};
-
-static int arizona_sr_vals[] = {
+static const unsigned int arizona_sr_vals[] = {
        0,
        12000,
        24000,
@@ -1485,13 +1447,21 @@ static int arizona_sr_vals[] = {
        512000,
 };
 
+#define ARIZONA_48K_RATE_MASK  0x0F003E
+#define ARIZONA_44K1_RATE_MASK 0x003E00
+#define ARIZONA_RATE_MASK      (ARIZONA_48K_RATE_MASK | ARIZONA_44K1_RATE_MASK)
+
+static const struct snd_pcm_hw_constraint_list arizona_constraint = {
+       .count  = ARRAY_SIZE(arizona_sr_vals),
+       .list   = arizona_sr_vals,
+};
+
 static int arizona_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
        struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
-       const struct snd_pcm_hw_constraint_list *constraint;
        unsigned int base_rate;
 
        if (!substream->runtime)
@@ -1509,16 +1479,15 @@ static int arizona_startup(struct snd_pcm_substream *substream,
        }
 
        if (base_rate == 0)
-               return 0;
-
-       if (base_rate % 8000)
-               constraint = &arizona_44k1_constraint;
+               dai_priv->constraint.mask = ARIZONA_RATE_MASK;
+       else if (base_rate % 8000)
+               dai_priv->constraint.mask = ARIZONA_44K1_RATE_MASK;
        else
-               constraint = &arizona_48k_constraint;
+               dai_priv->constraint.mask = ARIZONA_48K_RATE_MASK;
 
        return snd_pcm_hw_constraint_list(substream->runtime, 0,
                                          SNDRV_PCM_HW_PARAM_RATE,
-                                         constraint);
+                                         &dai_priv->constraint);
 }
 
 static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
@@ -1911,6 +1880,7 @@ int arizona_init_dai(struct arizona_priv *priv, int id)
        struct arizona_dai_priv *dai_priv = &priv->dai[id];
 
        dai_priv->clk = ARIZONA_CLK_SYSCLK;
+       dai_priv->constraint = arizona_constraint;
 
        return 0;
 }
@@ -2179,11 +2149,12 @@ static int arizona_calc_fll(struct arizona_fll *fll,
                return -EINVAL;
        }
 
-       arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
+       arizona_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
                        cfg->n, cfg->theta, cfg->lambda);
-       arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
-                       cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
-       arizona_fll_dbg(fll, "GAIN=%d\n", cfg->gain);
+       arizona_fll_dbg(fll, "FRATIO=0x%x(%d) OUTDIV=%d REFCLK_DIV=0x%x(%d)\n",
+                       cfg->fratio, ratio, cfg->outdiv,
+                       cfg->refdiv, 1 << cfg->refdiv);
+       arizona_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
 
        return 0;
 
index 8b6adb5419bb896482139426167752a22aa4df57..1ea8e4ecf8d41bbf9d3a792f4d88cf66383052a4 100644 (file)
@@ -57,7 +57,7 @@
 #define ARIZONA_CLK_98MHZ  5
 #define ARIZONA_CLK_147MHZ 6
 
-#define ARIZONA_MAX_DAI  8
+#define ARIZONA_MAX_DAI  10
 #define ARIZONA_MAX_ADSP 4
 
 #define ARIZONA_DVFS_SR1_RQ    0x001
@@ -68,6 +68,8 @@ struct wm_adsp;
 
 struct arizona_dai_priv {
        int clk;
+
+       struct snd_pcm_hw_constraint_list constraint;
 };
 
 struct arizona_priv {
index b3951524339f90cdf8f90dbc23cbadd46a874af9..35488f14e2378ada271328a97504a9558b746836 100644 (file)
@@ -60,15 +60,15 @@ static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
        switch (value) {
        default:
        case 0:
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
                break;
        /* same value : (L+R)/2 and (R+L)/2 */
        case 1:
        case 2:
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
                break;
        case 3:
-               ucontrol->value.integer.value[0] = 2;
+               ucontrol->value.enumerated.item[0] = 2;
                break;
        }
 
@@ -85,7 +85,7 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        unsigned char val;
 
-       switch (ucontrol->value.integer.value[0]) {
+       switch (ucontrol->value.enumerated.item[0]) {
        default:
        case 0:
                val = CHAN_MIX_NORMAL;
index d562e1b9a5d163bb22e990280b8f2e396e584846..1179101b2b055a639e711049dc389d34e999a011 100644 (file)
@@ -44,6 +44,7 @@ struct cs42xx8_priv {
 
        bool slave_mode;
        unsigned long sysclk;
+       u32 tx_channels;
 };
 
 /* -127.5dB to 0dB with step of 0.5dB */
@@ -257,6 +258,9 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
        u32 ratio = cs42xx8->sysclk / params_rate(params);
        u32 i, fm, val, mask;
 
+       if (tx)
+               cs42xx8->tx_channels = params_channels(params);
+
        for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
                if (cs42xx8_ratios[i].ratio == ratio)
                        break;
@@ -283,9 +287,11 @@ static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec);
+       u8 dac_unmute = cs42xx8->tx_channels ?
+                       ~((0x1 << cs42xx8->tx_channels) - 1) : 0;
 
-       regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE,
-                          CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0);
+       regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE,
+                    mute ? CS42XX8_DACMUTE_ALL : dac_unmute);
 
        return 0;
 }
index dc5ae7f7a1bd77f64e480a0346877358670ffac9..576087bda330ce840bdb4f90777ee7c9f1d580d9 100644 (file)
@@ -57,6 +57,25 @@ static const struct wm_adsp_region *cs47l24_dsp_regions[] = {
        cs47l24_dsp3_regions,
 };
 
+static int cs47l24_adsp_power_ev(struct snd_soc_dapm_widget *w,
+                                struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+       unsigned int v;
+       int ret;
+
+       ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret);
+               return ret;
+       }
+
+       v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+       return wm_adsp2_early_event(w, kcontrol, event, v);
+}
+
 static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0);
@@ -405,8 +424,8 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
                 NULL, 0),
 
-WM_ADSP2("DSP2", 1),
-WM_ADSP2("DSP3", 2),
+WM_ADSP2("DSP2", 1, cs47l24_adsp_power_ev),
+WM_ADSP2("DSP3", 2, cs47l24_adsp_power_ev),
 
 SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
                 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
@@ -779,6 +798,9 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = {
        { "AIF2 Capture", NULL, "SYSCLK" },
        { "AIF3 Capture", NULL, "SYSCLK" },
 
+       { "Voice Control DSP", NULL, "DSP3" },
+       { "Voice Control DSP", NULL, "SYSCLK" },
+
        { "IN1L PGA", NULL, "IN1L" },
        { "IN1R PGA", NULL, "IN1R" },
 
@@ -901,7 +923,7 @@ static int cs47l24_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        }
 }
 
-#define CS47L24_RATES SNDRV_PCM_RATE_8000_192000
+#define CS47L24_RATES SNDRV_PCM_RATE_KNOT
 
 #define CS47L24_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -973,12 +995,68 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
                .symmetric_rates = 1,
                .symmetric_samplebits = 1,
        },
+       {
+               .name = "cs47l24-cpu-voicectrl",
+               .capture = {
+                       .stream_name = "Voice Control CPU",
+                       .channels_min = 1,
+                       .channels_max = 1,
+                       .rates = CS47L24_RATES,
+                       .formats = CS47L24_FORMATS,
+               },
+               .compress_new = snd_soc_new_compress,
+       },
+       {
+               .name = "cs47l24-dsp-voicectrl",
+               .capture = {
+                       .stream_name = "Voice Control DSP",
+                       .channels_min = 1,
+                       .channels_max = 1,
+                       .rates = CS47L24_RATES,
+                       .formats = CS47L24_FORMATS,
+               },
+       },
 };
 
+static int cs47l24_open(struct snd_compr_stream *stream)
+{
+       struct snd_soc_pcm_runtime *rtd = stream->private_data;
+       struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
+       struct arizona *arizona = priv->core.arizona;
+       int n_adsp;
+
+       if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-voicectrl") == 0) {
+               n_adsp = 2;
+       } else {
+               dev_err(arizona->dev,
+                       "No suitable compressed stream for DAI '%s'\n",
+                       rtd->codec_dai->name);
+               return -EINVAL;
+       }
+
+       return wm_adsp_compr_open(&priv->core.adsp[n_adsp], stream);
+}
+
+static irqreturn_t cs47l24_adsp2_irq(int irq, void *data)
+{
+       struct cs47l24_priv *priv = data;
+       struct arizona *arizona = priv->core.arizona;
+       int ret;
+
+       ret = wm_adsp_compr_handle_irq(&priv->core.adsp[2]);
+       if (ret == -ENODEV) {
+               dev_err(arizona->dev, "Spurious compressed data IRQ\n");
+               return IRQ_NONE;
+       }
+
+       return IRQ_HANDLED;
+}
+
 static int cs47l24_codec_probe(struct snd_soc_codec *codec)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
+       struct arizona *arizona = priv->core.arizona;
        int ret;
 
        priv->core.arizona->dapm = dapm;
@@ -987,6 +1065,14 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec)
        arizona_init_gpio(codec);
        arizona_init_mono(codec);
 
+       ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
+                                 "ADSP2 Compressed IRQ", cs47l24_adsp2_irq,
+                                 priv);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
+               return ret;
+       }
+
        ret = wm_adsp2_codec_probe(&priv->core.adsp[1], codec);
        if (ret)
                goto err_adsp2_codec_probe;
@@ -1014,13 +1100,14 @@ err_adsp2_codec_probe:
 static int cs47l24_codec_remove(struct snd_soc_codec *codec)
 {
        struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
-
+       struct arizona *arizona = priv->core.arizona;
 
        wm_adsp2_codec_remove(&priv->core.adsp[1], codec);
        wm_adsp2_codec_remove(&priv->core.adsp[2], codec);
 
        priv->core.arizona->dapm = NULL;
 
+       arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
        return 0;
 }
 
@@ -1057,6 +1144,19 @@ static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = {
        .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes),
 };
 
+static struct snd_compr_ops cs47l24_compr_ops = {
+       .open = cs47l24_open,
+       .free = wm_adsp_compr_free,
+       .set_params = wm_adsp_compr_set_params,
+       .get_caps = wm_adsp_compr_get_caps,
+       .trigger = wm_adsp_compr_trigger,
+       .pointer = wm_adsp_compr_pointer,
+       .copy = wm_adsp_compr_copy,
+};
+
+static struct snd_soc_platform_driver cs47l24_compr_platform = {
+       .compr_ops = &cs47l24_compr_ops,
+};
 static int cs47l24_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
@@ -1120,12 +1220,25 @@ static int cs47l24_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_idle(&pdev->dev);
 
-       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
+       ret = snd_soc_register_platform(&pdev->dev, &cs47l24_compr_platform);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
+               return ret;
+       }
+       ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
                                      cs47l24_dai, ARRAY_SIZE(cs47l24_dai));
+
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
+               snd_soc_unregister_platform(&pdev->dev);
+       }
+
+       return ret;
 }
 
 static int cs47l24_remove(struct platform_device *pdev)
 {
+       snd_soc_unregister_platform(&pdev->dev);
        snd_soc_unregister_codec(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
index 1d5a89c5164b85686f652dc8f5e13af6c1eb49e6..461506a4ca6a2ddb790b1646f27bce2d7abf25ba 100644 (file)
@@ -334,7 +334,7 @@ static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
        unsigned int reg = enum_ctrl->reg;
-       unsigned int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.enumerated.item[0];
        unsigned int bits;
 
        switch (sel) {
@@ -368,13 +368,13 @@ static int da732x_hpf_get(struct snd_kcontrol *kcontrol,
 
        switch (val) {
        case DA732X_HPF_VOICE_EN:
-               ucontrol->value.integer.value[0] = DA732X_HPF_VOICE;
+               ucontrol->value.enumerated.item[0] = DA732X_HPF_VOICE;
                break;
        case DA732X_HPF_MUSIC_EN:
-               ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC;
+               ucontrol->value.enumerated.item[0] = DA732X_HPF_MUSIC;
                break;
        default:
-               ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED;
+               ucontrol->value.enumerated.item[0] = DA732X_HPF_DISABLED;
                break;
        }
 
index 5a1ec0f7a1a6370931e054cfe3ca85223a6b394d..26f9459cb3bc8e6bb60aa2b71ddeaf427cb869ab 100644 (file)
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/hdmi.h>
+#include <drm/drm_edid.h>
 #include <sound/pcm_params.h>
+#include <sound/jack.h>
 #include <sound/soc.h>
 #include <sound/hdaudio_ext.h>
 #include <sound/hda_i915.h>
+#include <sound/pcm_drm_eld.h>
 #include "../../hda/local.h"
+#include "hdac_hdmi.h"
+
+#define NAME_SIZE      32
 
 #define AMP_OUT_MUTE           0xb080
 #define AMP_OUT_UNMUTE         0xb000
 
 #define HDA_MAX_CONNECTIONS     32
 
+#define HDA_MAX_CVTS           3
+
+#define ELD_MAX_SIZE    256
+#define ELD_FIXED_BYTES        20
+
 struct hdac_hdmi_cvt_params {
        unsigned int channels_min;
        unsigned int channels_max;
@@ -45,14 +56,34 @@ struct hdac_hdmi_cvt_params {
 struct hdac_hdmi_cvt {
        struct list_head head;
        hda_nid_t nid;
+       const char *name;
        struct hdac_hdmi_cvt_params params;
 };
 
+struct hdac_hdmi_eld {
+       bool    monitor_present;
+       bool    eld_valid;
+       int     eld_size;
+       char    eld_buffer[ELD_MAX_SIZE];
+};
+
 struct hdac_hdmi_pin {
        struct list_head head;
        hda_nid_t nid;
        int num_mux_nids;
        hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
+       struct hdac_hdmi_eld eld;
+       struct hdac_ext_device *edev;
+       int repoll_count;
+       struct delayed_work work;
+};
+
+struct hdac_hdmi_pcm {
+       struct list_head head;
+       int pcm_id;
+       struct hdac_hdmi_pin *pin;
+       struct hdac_hdmi_cvt *cvt;
+       struct snd_jack *jack;
 };
 
 struct hdac_hdmi_dai_pin_map {
@@ -62,11 +93,13 @@ struct hdac_hdmi_dai_pin_map {
 };
 
 struct hdac_hdmi_priv {
-       struct hdac_hdmi_dai_pin_map dai_map[3];
+       struct hdac_hdmi_dai_pin_map dai_map[HDA_MAX_CVTS];
        struct list_head pin_list;
        struct list_head cvt_list;
+       struct list_head pcm_list;
        int num_pin;
        int num_cvt;
+       struct mutex pin_mutex;
 };
 
 static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
@@ -76,6 +109,119 @@ static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev)
        return to_ehdac_device(hdac);
 }
 
+static unsigned int sad_format(const u8 *sad)
+{
+       return ((sad[0] >> 0x3) & 0x1f);
+}
+
+static unsigned int sad_sample_bits_lpcm(const u8 *sad)
+{
+       return (sad[2] & 7);
+}
+
+static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime,
+                                               void *eld)
+{
+       u64 formats = SNDRV_PCM_FMTBIT_S16;
+       int i;
+       const u8 *sad, *eld_buf = eld;
+
+       sad = drm_eld_sad(eld_buf);
+       if (!sad)
+               goto format_constraint;
+
+       for (i = drm_eld_sad_count(eld_buf); i > 0; i--, sad += 3) {
+               if (sad_format(sad) == 1) { /* AUDIO_CODING_TYPE_LPCM */
+
+                       /*
+                        * the controller support 20 and 24 bits in 32 bit
+                        * container so we set S32
+                        */
+                       if (sad_sample_bits_lpcm(sad) & 0x6)
+                               formats |= SNDRV_PCM_FMTBIT_S32;
+               }
+       }
+
+format_constraint:
+       return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
+                               formats);
+
+}
+
+ /* HDMI ELD routines */
+static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec,
+                               hda_nid_t nid, int byte_index)
+{
+       unsigned int val;
+
+       val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD,
+                                                       byte_index);
+
+       dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n",
+                                       byte_index, val);
+
+       return val;
+}
+
+static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid)
+{
+       return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
+                                                AC_DIPSIZE_ELD_BUF);
+}
+
+/*
+ * This function queries the ELD size and ELD data and fills in the buffer
+ * passed by user
+ */
+static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid,
+                            unsigned char *buf, int *eld_size)
+{
+       int i, size, ret = 0;
+
+       /*
+        * ELD size is initialized to zero in caller function. If no errors and
+        * ELD is valid, actual eld_size is assigned.
+        */
+
+       size = hdac_hdmi_get_eld_size(codec, nid);
+       if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
+               dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size);
+               return -ERANGE;
+       }
+
+       /* set ELD buffer */
+       for (i = 0; i < size; i++) {
+               unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i);
+               /*
+                * Graphics driver might be writing to ELD buffer right now.
+                * Just abort. The caller will repoll after a while.
+                */
+               if (!(val & AC_ELDD_ELD_VALID)) {
+                       dev_err(&codec->dev,
+                               "HDMI: invalid ELD data byte %d\n", i);
+                       ret = -EINVAL;
+                       goto error;
+               }
+               val &= AC_ELDD_ELD_DATA;
+               /*
+                * The first byte cannot be zero. This can happen on some DVI
+                * connections. Some Intel chips may also need some 250ms delay
+                * to return non-zero ELD data, even when the graphics driver
+                * correctly writes ELD content before setting ELD_valid bit.
+                */
+               if (!val && !i) {
+                       dev_err(&codec->dev, "HDMI: 0 ELD data\n");
+                       ret = -EINVAL;
+                       goto error;
+               }
+               buf[i] = val;
+       }
+
+       *eld_size = size;
+error:
+       return ret;
+}
+
 static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac,
                                hda_nid_t cvt_nid, hda_nid_t pin_nid,
                                u32 stream_tag, int format)
@@ -107,27 +253,74 @@ hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid,
                                AC_VERB_SET_HDMI_DIP_INDEX, val);
 }
 
+struct dp_audio_infoframe {
+       u8 type; /* 0x84 */
+       u8 len;  /* 0x1b */
+       u8 ver;  /* 0x11 << 2 */
+
+       u8 CC02_CT47;   /* match with HDMI infoframe from this on */
+       u8 SS01_SF24;
+       u8 CXT04;
+       u8 CA;
+       u8 LFEPBL01_LSV36_DM_INH7;
+};
+
 static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
                                hda_nid_t cvt_nid, hda_nid_t pin_nid)
 {
        uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE];
        struct hdmi_audio_infoframe frame;
-       u8 *dip = (u8 *)&frame;
+       struct dp_audio_infoframe dp_ai;
+       struct hdac_hdmi_priv *hdmi = hdac->private_data;
+       struct hdac_hdmi_pin *pin;
+       u8 *dip;
        int ret;
        int i;
+       const u8 *eld_buf;
+       u8 conn_type;
+       int channels = 2;
 
-       hdmi_audio_infoframe_init(&frame);
+       list_for_each_entry(pin, &hdmi->pin_list, head) {
+               if (pin->nid == pin_nid)
+                       break;
+       }
 
-       /* Default stereo for now */
-       frame.channels = 2;
+       eld_buf = pin->eld.eld_buffer;
+       conn_type = drm_eld_get_conn_type(eld_buf);
 
        /* setup channel count */
        snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0,
-                           AC_VERB_SET_CVT_CHAN_COUNT, frame.channels - 1);
+                           AC_VERB_SET_CVT_CHAN_COUNT, channels - 1);
 
-       ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
-       if (ret < 0)
-               return ret;
+       switch (conn_type) {
+       case DRM_ELD_CONN_TYPE_HDMI:
+               hdmi_audio_infoframe_init(&frame);
+
+               /* Default stereo for now */
+               frame.channels = channels;
+
+               ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       case DRM_ELD_CONN_TYPE_DP:
+               memset(&dp_ai, 0, sizeof(dp_ai));
+               dp_ai.type      = 0x84;
+               dp_ai.len       = 0x1b;
+               dp_ai.ver       = 0x11 << 2;
+               dp_ai.CC02_CT47 = channels - 1;
+               dp_ai.CA        = 0;
+
+               dip = (u8 *)&dp_ai;
+               break;
+
+       default:
+               dev_err(&hdac->hdac.dev, "Invalid connection type: %d\n",
+                                               conn_type);
+               return -EIO;
+       }
 
        /* stop infoframe transmission */
        hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
@@ -137,9 +330,15 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac,
 
        /*  Fill infoframe. Index auto-incremented */
        hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(frame); i++)
-               snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+       if (conn_type == DRM_ELD_CONN_TYPE_HDMI) {
+               for (i = 0; i < sizeof(buffer); i++)
+                       snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
+                               AC_VERB_SET_HDMI_DIP_DATA, buffer[i]);
+       } else {
+               for (i = 0; i < sizeof(dp_ai); i++)
+                       snd_hdac_codec_write(&hdac->hdac, pin_nid, 0,
                                AC_VERB_SET_HDMI_DIP_DATA, dip[i]);
+       }
 
        /* Start infoframe */
        hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0);
@@ -174,11 +373,6 @@ static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream,
        struct hdac_ext_dma_params *dd;
        int ret;
 
-       if (dai->id > 0) {
-               dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
-               return -ENODEV;
-       }
-
        dai_map = &hdmi->dai_map[dai->id];
 
        dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
@@ -198,16 +392,30 @@ static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai)
 {
        struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+       struct hdac_hdmi_priv *hdmi = hdac->private_data;
+       struct hdac_hdmi_dai_pin_map *dai_map;
+       struct hdac_hdmi_pin *pin;
        struct hdac_ext_dma_params *dd;
 
-       if (dai->id > 0) {
-               dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
+       dai_map = &hdmi->dai_map[dai->id];
+       pin = dai_map->pin;
+
+       if (!pin)
+               return -ENODEV;
+
+       if ((!pin->eld.monitor_present) || (!pin->eld.eld_valid)) {
+               dev_err(&hdac->hdac.dev, "device is not configured for this pin: %d\n",
+                                                               pin->nid);
                return -ENODEV;
        }
 
-       dd = kzalloc(sizeof(*dd), GFP_KERNEL);
-       if (!dd)
-               return -ENOMEM;
+       dd = snd_soc_dai_get_dma_data(dai, substream);
+       if (!dd) {
+               dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+               if (!dd)
+                       return -ENOMEM;
+       }
+
        dd->format = snd_hdac_calc_stream_format(params_rate(hparams),
                        params_channels(hparams), params_format(hparams),
                        24, 0);
@@ -227,50 +435,187 @@ static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream,
 
        dai_map = &hdmi->dai_map[dai->id];
 
+       dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
+
+       if (dd) {
+               snd_soc_dai_set_dma_data(dai, substream, NULL);
+               kfree(dd);
+       }
+
+       return 0;
+}
+
+static void hdac_hdmi_enable_cvt(struct hdac_ext_device *edev,
+               struct hdac_hdmi_dai_pin_map *dai_map)
+{
+       /* Enable transmission */
        snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
-                               AC_VERB_SET_CHANNEL_STREAMID, 0);
+                       AC_VERB_SET_DIGI_CONVERT_1, 1);
+
+       /* Category Code (CC) to zero */
        snd_hdac_codec_write(&edev->hdac, dai_map->cvt->nid, 0,
-                               AC_VERB_SET_STREAM_FORMAT, 0);
+                       AC_VERB_SET_DIGI_CONVERT_2, 0);
+}
 
-       dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream);
-       snd_soc_dai_set_dma_data(dai, substream, NULL);
+static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac,
+               struct hdac_hdmi_dai_pin_map *dai_map)
+{
+       int mux_idx;
+       struct hdac_hdmi_pin *pin = dai_map->pin;
+
+       for (mux_idx = 0; mux_idx < pin->num_mux_nids; mux_idx++) {
+               if (pin->mux_nids[mux_idx] == dai_map->cvt->nid) {
+                       snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
+                                       AC_VERB_SET_CONNECT_SEL, mux_idx);
+                       break;
+               }
+       }
+
+       if (mux_idx == pin->num_mux_nids)
+               return -EIO;
+
+       /* Enable out path for this pin widget */
+       snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
+                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 
-       kfree(dd);
+       hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0);
+
+       snd_hdac_codec_write(&hdac->hdac, pin->nid, 0,
+                       AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
 
        return 0;
 }
 
+static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac,
+                                       struct hdac_hdmi_pin *pin)
+{
+       if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
+               dev_warn(&hdac->hdac.dev,
+                       "HDMI: pin %d wcaps %#x does not support connection list\n",
+                       pin->nid, get_wcaps(&hdac->hdac, pin->nid));
+               return -EINVAL;
+       }
+
+       pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
+                       pin->mux_nids, HDA_MAX_CONNECTIONS);
+       if (pin->num_mux_nids == 0)
+               dev_warn(&hdac->hdac.dev, "No connections found for pin: %d\n",
+                                                               pin->nid);
+
+       dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin: %d\n",
+                       pin->num_mux_nids, pin->nid);
+
+       return pin->num_mux_nids;
+}
+
+/*
+ * Query pcm list and return pin widget to which stream is routed.
+ *
+ * Also query connection list of the pin, to validate the cvt to pin map.
+ *
+ * Same stream rendering to multiple pins simultaneously can be done
+ * possibly, but not supported for now in driver. So return the first pin
+ * connected.
+ */
+static struct hdac_hdmi_pin *hdac_hdmi_get_pin_from_cvt(
+                       struct hdac_ext_device *edev,
+                       struct hdac_hdmi_priv *hdmi,
+                       struct hdac_hdmi_cvt *cvt)
+{
+       struct hdac_hdmi_pcm *pcm;
+       struct hdac_hdmi_pin *pin = NULL;
+       int ret, i;
+
+       list_for_each_entry(pcm, &hdmi->pcm_list, head) {
+               if (pcm->cvt == cvt) {
+                       pin = pcm->pin;
+                       break;
+               }
+       }
+
+       if (pin) {
+               ret = hdac_hdmi_query_pin_connlist(edev, pin);
+               if (ret < 0)
+                       return NULL;
+
+               for (i = 0; i < pin->num_mux_nids; i++) {
+                       if (pin->mux_nids[i] == cvt->nid)
+                               return pin;
+               }
+       }
+
+       return NULL;
+}
+
+/*
+ * This tries to get a valid pin and set the HW constraints based on the
+ * ELD. Even if a valid pin is not found return success so that device open
+ * doesn't fail.
+ */
 static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream,
                        struct snd_soc_dai *dai)
 {
        struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
        struct hdac_hdmi_priv *hdmi = hdac->private_data;
        struct hdac_hdmi_dai_pin_map *dai_map;
-       int val;
-
-       if (dai->id > 0) {
-               dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n");
-               return -ENODEV;
-       }
+       struct hdac_hdmi_cvt *cvt;
+       struct hdac_hdmi_pin *pin;
+       int ret;
 
        dai_map = &hdmi->dai_map[dai->id];
 
-       val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin->nid, 0,
-                                       AC_VERB_GET_PIN_SENSE, 0);
-       dev_info(&hdac->hdac.dev, "Val for AC_VERB_GET_PIN_SENSE: %x\n", val);
+       cvt = dai_map->cvt;
+       pin = hdac_hdmi_get_pin_from_cvt(hdac, hdmi, cvt);
 
-       if ((!(val & AC_PINSENSE_PRESENCE)) || (!(val & AC_PINSENSE_ELDV))) {
-               dev_err(&hdac->hdac.dev, "Monitor presence invalid with val: %x\n", val);
-               return -ENODEV;
+       /*
+        * To make PA and other userland happy.
+        * userland scans devices so returning error does not help.
+        */
+       if (!pin)
+               return 0;
+
+       if ((!pin->eld.monitor_present) ||
+                       (!pin->eld.eld_valid)) {
+
+               dev_warn(&hdac->hdac.dev,
+                       "Failed: montior present? %d ELD valid?: %d for pin: %d\n",
+                       pin->eld.monitor_present, pin->eld.eld_valid, pin->nid);
+
+               return 0;
        }
 
-       hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0);
+       dai_map->pin = pin;
 
-       snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
-                       AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+       hdac_hdmi_enable_cvt(hdac, dai_map);
+       ret = hdac_hdmi_enable_pin(hdac, dai_map);
+       if (ret < 0)
+               return ret;
 
-       snd_pcm_hw_constraint_step(substream->runtime, 0,
-                                  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+       ret = hdac_hdmi_eld_limit_formats(substream->runtime,
+                               pin->eld.eld_buffer);
+       if (ret < 0)
+               return ret;
+
+       return snd_pcm_hw_constraint_eld(substream->runtime,
+                               pin->eld.eld_buffer);
+}
+
+static int hdac_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+               struct snd_soc_dai *dai)
+{
+       struct hdac_hdmi_dai_pin_map *dai_map;
+       struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai);
+       struct hdac_hdmi_priv *hdmi = hdac->private_data;
+       int ret;
+
+       dai_map = &hdmi->dai_map[dai->id];
+       if (cmd == SNDRV_PCM_TRIGGER_RESUME) {
+               ret = hdac_hdmi_enable_pin(hdac, dai_map);
+               if (ret < 0)
+                       return ret;
+
+               return hdac_hdmi_playback_prepare(substream, dai);
+       }
 
        return 0;
 }
@@ -284,10 +629,19 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream,
 
        dai_map = &hdmi->dai_map[dai->id];
 
-       hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
+       if (dai_map->pin) {
+               snd_hdac_codec_write(&hdac->hdac, dai_map->cvt->nid, 0,
+                               AC_VERB_SET_CHANNEL_STREAMID, 0);
+               snd_hdac_codec_write(&hdac->hdac, dai_map->cvt->nid, 0,
+                               AC_VERB_SET_STREAM_FORMAT, 0);
+
+               hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3);
 
-       snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
+               snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0,
                        AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+               dai_map->pin = NULL;
+       }
 }
 
 static int
@@ -310,85 +664,326 @@ hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
        return err;
 }
 
-static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w,
-                               enum snd_soc_dapm_type id,
-                               const char *wname, const char *stream)
+static int hdac_hdmi_fill_widget_info(struct device *dev,
+                               struct snd_soc_dapm_widget *w,
+                               enum snd_soc_dapm_type id, void *priv,
+                               const char *wname, const char *stream,
+                               struct snd_kcontrol_new *wc, int numkc)
 {
        w->id = id;
-       w->name = wname;
+       w->name = devm_kstrdup(dev, wname, GFP_KERNEL);
+       if (!w->name)
+               return -ENOMEM;
+
        w->sname = stream;
        w->reg = SND_SOC_NOPM;
        w->shift = 0;
-       w->kcontrol_news = NULL;
-       w->num_kcontrols = 0;
-       w->priv = NULL;
+       w->kcontrol_news = wc;
+       w->num_kcontrols = numkc;
+       w->priv = priv;
+
+       return 0;
 }
 
 static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
-               const char *sink, const char *control, const char *src)
+               const char *sink, const char *control, const char *src,
+               int (*handler)(struct snd_soc_dapm_widget *src,
+                       struct snd_soc_dapm_widget *sink))
 {
        route->sink = sink;
        route->source = src;
        route->control = control;
-       route->connected = NULL;
+       route->connected = handler;
 }
 
-static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm,
-                                       struct hdac_hdmi_dai_pin_map *dai_map)
+static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev,
+                                       struct hdac_hdmi_pin *pin)
 {
-       struct snd_soc_dapm_route route[1];
-       struct snd_soc_dapm_widget widgets[2] = { {0} };
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_pcm *pcm = NULL;
 
-       memset(&route, 0, sizeof(route));
+       list_for_each_entry(pcm, &hdmi->pcm_list, head) {
+               if (pcm->pin == pin)
+                       return pcm;
+       }
 
-       hdac_hdmi_fill_widget_info(&widgets[0], snd_soc_dapm_output,
-                       "hif1 Output", NULL);
-       hdac_hdmi_fill_widget_info(&widgets[1], snd_soc_dapm_aif_in,
-                       "Coverter 1", "hif1");
+       return NULL;
+}
 
-       hdac_hdmi_fill_route(&route[0], "hif1 Output", NULL, "Coverter 1");
+/*
+ * Based on user selection, map the PINs with the PCMs.
+ */
+static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       int ret;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+       struct snd_soc_dapm_context *dapm = w->dapm;
+       struct hdac_hdmi_pin *pin = w->priv;
+       struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_pcm *pcm = NULL;
+       const char *cvt_name =  e->texts[ucontrol->value.enumerated.item[0]];
 
-       snd_soc_dapm_new_controls(dapm, widgets, ARRAY_SIZE(widgets));
-       snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route));
+       ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&hdmi->pin_mutex);
+       list_for_each_entry(pcm, &hdmi->pcm_list, head) {
+               if (pcm->pin == pin)
+                       pcm->pin = NULL;
+
+               /*
+                * Jack status is not reported during device probe as the
+                * PCMs are not registered by then. So report it here.
+                */
+               if (!strcmp(cvt_name, pcm->cvt->name) && !pcm->pin) {
+                       pcm->pin = pin;
+                       if (pin->eld.monitor_present && pin->eld.eld_valid) {
+                               dev_dbg(&edev->hdac.dev,
+                                       "jack report for pcm=%d\n",
+                                       pcm->pcm_id);
+
+                               snd_jack_report(pcm->jack, SND_JACK_AVOUT);
+                       }
+                       mutex_unlock(&hdmi->pin_mutex);
+                       return ret;
+               }
+       }
+       mutex_unlock(&hdmi->pin_mutex);
+
+       return ret;
 }
 
-static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
+/*
+ * Ideally the Mux inputs should be based on the num_muxs enumerated, but
+ * the display driver seem to be programming the connection list for the pin
+ * widget runtime.
+ *
+ * So programming all the possible inputs for the mux, the user has to take
+ * care of selecting the right one and leaving all other inputs selected to
+ * "NONE"
+ */
+static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev,
+                               struct hdac_hdmi_pin *pin,
+                               struct snd_soc_dapm_widget *widget,
+                               const char *widget_name)
+{
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct snd_kcontrol_new *kc;
+       struct hdac_hdmi_cvt *cvt;
+       struct soc_enum *se;
+       char kc_name[NAME_SIZE];
+       char mux_items[NAME_SIZE];
+       /* To hold inputs to the Pin mux */
+       char *items[HDA_MAX_CONNECTIONS];
+       int i = 0;
+       int num_items = hdmi->num_cvt + 1;
+
+       kc = devm_kzalloc(&edev->hdac.dev, sizeof(*kc), GFP_KERNEL);
+       if (!kc)
+               return -ENOMEM;
+
+       se = devm_kzalloc(&edev->hdac.dev, sizeof(*se), GFP_KERNEL);
+       if (!se)
+               return -ENOMEM;
+
+       sprintf(kc_name, "Pin %d Input", pin->nid);
+       kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL);
+       if (!kc->name)
+               return -ENOMEM;
+
+       kc->private_value = (long)se;
+       kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       kc->access = 0;
+       kc->info = snd_soc_info_enum_double;
+       kc->put = hdac_hdmi_set_pin_mux;
+       kc->get = snd_soc_dapm_get_enum_double;
+
+       se->reg = SND_SOC_NOPM;
+
+       /* enum texts: ["NONE", "cvt #", "cvt #", ...] */
+       se->items = num_items;
+       se->mask = roundup_pow_of_two(se->items) - 1;
+
+       sprintf(mux_items, "NONE");
+       items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL);
+       if (!items[i])
+               return -ENOMEM;
+
+       list_for_each_entry(cvt, &hdmi->cvt_list, head) {
+               i++;
+               sprintf(mux_items, "cvt %d", cvt->nid);
+               items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL);
+               if (!items[i])
+                       return -ENOMEM;
+       }
+
+       se->texts = devm_kmemdup(&edev->hdac.dev, items,
+                       (num_items  * sizeof(char *)), GFP_KERNEL);
+       if (!se->texts)
+               return -ENOMEM;
+
+       return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget,
+                       snd_soc_dapm_mux, pin, widget_name, NULL, kc, 1);
+}
+
+/* Add cvt <- input <- mux route map */
+static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev,
+                       struct snd_soc_dapm_widget *widgets,
+                       struct snd_soc_dapm_route *route, int rindex)
+{
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       const struct snd_kcontrol_new *kc;
+       struct soc_enum *se;
+       int mux_index = hdmi->num_cvt + hdmi->num_pin;
+       int i, j;
+
+       for (i = 0; i < hdmi->num_pin; i++) {
+               kc = widgets[mux_index].kcontrol_news;
+               se = (struct soc_enum *)kc->private_value;
+               for (j = 0; j < hdmi->num_cvt; j++) {
+                       hdac_hdmi_fill_route(&route[rindex],
+                                       widgets[mux_index].name,
+                                       se->texts[j + 1],
+                                       widgets[j].name, NULL);
+
+                       rindex++;
+               }
+
+               mux_index++;
+       }
+}
+
+/*
+ * Widgets are added in the below sequence
+ *     Converter widgets for num converters enumerated
+ *     Pin widgets for num pins enumerated
+ *     Pin mux widgets to represent connenction list of pin widget
+ *
+ * Total widgets elements = num_cvt + num_pin + num_pin;
+ *
+ * Routes are added as below:
+ *     pin mux -> pin (based on num_pins)
+ *     cvt -> "Input sel control" -> pin_mux
+ *
+ * Total route elements:
+ *     num_pins + (pin_muxes * num_cvt)
+ */
+static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
 {
+       struct snd_soc_dapm_widget *widgets;
+       struct snd_soc_dapm_route *route;
+       struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev);
        struct hdac_hdmi_priv *hdmi = edev->private_data;
-       struct hdac_hdmi_dai_pin_map *dai_map = &hdmi->dai_map[0];
+       struct snd_soc_dai_driver *dai_drv = dapm->component->dai_drv;
+       char widget_name[NAME_SIZE];
        struct hdac_hdmi_cvt *cvt;
        struct hdac_hdmi_pin *pin;
+       int ret, i = 0, num_routes = 0;
 
        if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list))
                return -EINVAL;
 
-       /*
-        * Currently on board only 1 pin and 1 converter is enabled for
-        * simplification, more will be added eventually
-        * So using fixed map for dai_id:pin:cvt
-        */
-       cvt = list_first_entry(&hdmi->cvt_list, struct hdac_hdmi_cvt, head);
-       pin = list_first_entry(&hdmi->pin_list, struct hdac_hdmi_pin, head);
+       widgets = devm_kzalloc(dapm->dev,
+               (sizeof(*widgets) * ((2 * hdmi->num_pin) + hdmi->num_cvt)),
+               GFP_KERNEL);
 
-       dai_map->dai_id = 0;
-       dai_map->pin = pin;
+       if (!widgets)
+               return -ENOMEM;
 
-       dai_map->cvt = cvt;
+       /* DAPM widgets to represent each converter widget */
+       list_for_each_entry(cvt, &hdmi->cvt_list, head) {
+               sprintf(widget_name, "Converter %d", cvt->nid);
+               ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
+                       snd_soc_dapm_aif_in, &cvt->nid,
+                       widget_name, dai_drv[i].playback.stream_name, NULL, 0);
+               if (ret < 0)
+                       return ret;
+               i++;
+       }
 
-       /* Enable out path for this pin widget */
-       snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
-                       AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       list_for_each_entry(pin, &hdmi->pin_list, head) {
+               sprintf(widget_name, "hif%d Output", pin->nid);
+               ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
+                               snd_soc_dapm_output, &pin->nid,
+                               widget_name, NULL, NULL, 0);
+               if (ret < 0)
+                       return ret;
+               i++;
+       }
 
-       /* Enable transmission */
-       snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
-                       AC_VERB_SET_DIGI_CONVERT_1, 1);
+       /* DAPM widgets to represent the connection list to pin widget */
+       list_for_each_entry(pin, &hdmi->pin_list, head) {
+               sprintf(widget_name, "Pin %d Mux", pin->nid);
+               ret = hdac_hdmi_create_pin_muxs(edev, pin, &widgets[i],
+                                                       widget_name);
+               if (ret < 0)
+                       return ret;
+               i++;
 
-       /* Category Code (CC) to zero */
-       snd_hdac_codec_write(&edev->hdac, cvt->nid, 0,
-                       AC_VERB_SET_DIGI_CONVERT_2, 0);
+               /* For cvt to pin_mux mapping */
+               num_routes += hdmi->num_cvt;
+
+               /* For pin_mux to pin mapping */
+               num_routes++;
+       }
 
-       snd_hdac_codec_write(&edev->hdac, pin->nid, 0,
-                       AC_VERB_SET_CONNECT_SEL, 0);
+       route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes),
+                                                       GFP_KERNEL);
+       if (!route)
+               return -ENOMEM;
+
+       i = 0;
+       /* Add pin <- NULL <- mux route map */
+       list_for_each_entry(pin, &hdmi->pin_list, head) {
+               int sink_index = i + hdmi->num_cvt;
+               int src_index = sink_index + hdmi->num_pin;
+
+               hdac_hdmi_fill_route(&route[i],
+                               widgets[sink_index].name, NULL,
+                               widgets[src_index].name, NULL);
+               i++;
+
+       }
+
+       hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i);
+
+       snd_soc_dapm_new_controls(dapm, widgets,
+               ((2 * hdmi->num_pin) + hdmi->num_cvt));
+
+       snd_soc_dapm_add_routes(dapm, route, num_routes);
+       snd_soc_dapm_new_widgets(dapm->card);
+
+       return 0;
+
+}
+
+static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev)
+{
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_dai_pin_map *dai_map;
+       struct hdac_hdmi_cvt *cvt;
+       int dai_id = 0;
+
+       if (list_empty(&hdmi->cvt_list))
+               return -EINVAL;
+
+       list_for_each_entry(cvt, &hdmi->cvt_list, head) {
+               dai_map = &hdmi->dai_map[dai_id];
+               dai_map->dai_id = dai_id;
+               dai_map->cvt = cvt;
+
+               dai_id++;
+
+               if (dai_id == HDA_MAX_CVTS) {
+                       dev_warn(&edev->hdac.dev,
+                               "Max dais supported: %d\n", dai_id);
+                       break;
+               }
+       }
 
        return 0;
 }
@@ -397,12 +992,15 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
 {
        struct hdac_hdmi_priv *hdmi = edev->private_data;
        struct hdac_hdmi_cvt *cvt;
+       char name[NAME_SIZE];
 
        cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
        if (!cvt)
                return -ENOMEM;
 
        cvt->nid = nid;
+       sprintf(name, "cvt %d", cvt->nid);
+       cvt->name = kstrdup(name, GFP_KERNEL);
 
        list_add_tail(&cvt->head, &hdmi->cvt_list);
        hdmi->num_cvt++;
@@ -410,6 +1008,106 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid)
        return hdac_hdmi_query_cvt_params(&edev->hdac, cvt);
 }
 
+static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll)
+{
+       struct hdac_ext_device *edev = pin->edev;
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_pcm *pcm;
+       int val;
+
+       pin->repoll_count = repoll;
+
+       pm_runtime_get_sync(&edev->hdac.dev);
+       val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0,
+                                       AC_VERB_GET_PIN_SENSE, 0);
+
+       dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n",
+                                               val, pin->nid);
+
+
+       mutex_lock(&hdmi->pin_mutex);
+       pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE);
+       pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV);
+
+       pcm = hdac_hdmi_get_pcm(edev, pin);
+
+       if (!pin->eld.monitor_present || !pin->eld.eld_valid) {
+
+               dev_dbg(&edev->hdac.dev, "%s: disconnect for pin %d\n",
+                                               __func__, pin->nid);
+
+               /*
+                * PCMs are not registered during device probe, so don't
+                * report jack here. It will be done in usermode mux
+                * control select.
+                */
+               if (pcm) {
+                       dev_dbg(&edev->hdac.dev,
+                               "jack report for pcm=%d\n", pcm->pcm_id);
+
+                       snd_jack_report(pcm->jack, 0);
+               }
+
+               mutex_unlock(&hdmi->pin_mutex);
+               goto put_hdac_device;
+       }
+
+       if (pin->eld.monitor_present && pin->eld.eld_valid) {
+               /* TODO: use i915 component for reading ELD later */
+               if (hdac_hdmi_get_eld(&edev->hdac, pin->nid,
+                               pin->eld.eld_buffer,
+                               &pin->eld.eld_size) == 0) {
+
+                       if (pcm) {
+                               dev_dbg(&edev->hdac.dev,
+                                       "jack report for pcm=%d\n",
+                                       pcm->pcm_id);
+
+                               snd_jack_report(pcm->jack, SND_JACK_AVOUT);
+                       }
+
+                       print_hex_dump_bytes("ELD: ", DUMP_PREFIX_OFFSET,
+                                       pin->eld.eld_buffer, pin->eld.eld_size);
+               } else {
+                       pin->eld.monitor_present = false;
+                       pin->eld.eld_valid = false;
+
+                       if (pcm) {
+                               dev_dbg(&edev->hdac.dev,
+                                       "jack report for pcm=%d\n",
+                                       pcm->pcm_id);
+
+                               snd_jack_report(pcm->jack, 0);
+                       }
+               }
+       }
+
+       mutex_unlock(&hdmi->pin_mutex);
+
+       /*
+        * Sometimes the pin_sense may present invalid monitor
+        * present and eld_valid. If ELD data is not valid, loop few
+        * more times to get correct pin sense and valid ELD.
+        */
+       if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll)
+               schedule_delayed_work(&pin->work, msecs_to_jiffies(300));
+
+put_hdac_device:
+       pm_runtime_put_sync(&edev->hdac.dev);
+}
+
+static void hdac_hdmi_repoll_eld(struct work_struct *work)
+{
+       struct hdac_hdmi_pin *pin =
+               container_of(to_delayed_work(work), struct hdac_hdmi_pin, work);
+
+       /* picked from legacy HDA driver */
+       if (pin->repoll_count++ > 6)
+               pin->repoll_count = 0;
+
+       hdac_hdmi_present_sense(pin, pin->repoll_count);
+}
+
 static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
 {
        struct hdac_hdmi_priv *hdmi = edev->private_data;
@@ -424,6 +1122,120 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
        list_add_tail(&pin->head, &hdmi->pin_list);
        hdmi->num_pin++;
 
+       pin->edev = edev;
+       INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld);
+
+       return 0;
+}
+
+#define INTEL_VENDOR_NID 0x08
+#define INTEL_GET_VENDOR_VERB 0xf81
+#define INTEL_SET_VENDOR_VERB 0x781
+#define INTEL_EN_DP12                  0x02 /* enable DP 1.2 features */
+#define INTEL_EN_ALL_PIN_CVTS  0x01 /* enable 2nd & 3rd pins and convertors */
+
+static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac)
+{
+       unsigned int vendor_param;
+
+       vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
+                               INTEL_GET_VENDOR_VERB, 0);
+       if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
+               return;
+
+       vendor_param |= INTEL_EN_ALL_PIN_CVTS;
+       vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
+                               INTEL_SET_VENDOR_VERB, vendor_param);
+       if (vendor_param == -1)
+               return;
+}
+
+static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
+{
+       unsigned int vendor_param;
+
+       vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
+                               INTEL_GET_VENDOR_VERB, 0);
+       if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
+               return;
+
+       /* enable DP1.2 mode */
+       vendor_param |= INTEL_EN_DP12;
+       vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0,
+                               INTEL_SET_VENDOR_VERB, vendor_param);
+       if (vendor_param == -1)
+               return;
+
+}
+
+static struct snd_soc_dai_ops hdmi_dai_ops = {
+       .startup = hdac_hdmi_pcm_open,
+       .shutdown = hdac_hdmi_pcm_close,
+       .hw_params = hdac_hdmi_set_hw_params,
+       .prepare = hdac_hdmi_playback_prepare,
+       .trigger = hdac_hdmi_trigger,
+       .hw_free = hdac_hdmi_playback_cleanup,
+};
+
+/*
+ * Each converter can support a stream independently. So a dai is created
+ * based on the number of converter queried.
+ */
+static int hdac_hdmi_create_dais(struct hdac_device *hdac,
+               struct snd_soc_dai_driver **dais,
+               struct hdac_hdmi_priv *hdmi, int num_dais)
+{
+       struct snd_soc_dai_driver *hdmi_dais;
+       struct hdac_hdmi_cvt *cvt;
+       char name[NAME_SIZE], dai_name[NAME_SIZE];
+       int i = 0;
+       u32 rates, bps;
+       unsigned int rate_max = 384000, rate_min = 8000;
+       u64 formats;
+       int ret;
+
+       hdmi_dais = devm_kzalloc(&hdac->dev,
+                       (sizeof(*hdmi_dais) * num_dais),
+                       GFP_KERNEL);
+       if (!hdmi_dais)
+               return -ENOMEM;
+
+       list_for_each_entry(cvt, &hdmi->cvt_list, head) {
+               ret = snd_hdac_query_supported_pcm(hdac, cvt->nid,
+                                       &rates, &formats, &bps);
+               if (ret)
+                       return ret;
+
+               sprintf(dai_name, "intel-hdmi-hifi%d", i+1);
+               hdmi_dais[i].name = devm_kstrdup(&hdac->dev,
+                                       dai_name, GFP_KERNEL);
+
+               if (!hdmi_dais[i].name)
+                       return -ENOMEM;
+
+               snprintf(name, sizeof(name), "hifi%d", i+1);
+               hdmi_dais[i].playback.stream_name =
+                               devm_kstrdup(&hdac->dev, name, GFP_KERNEL);
+               if (!hdmi_dais[i].playback.stream_name)
+                       return -ENOMEM;
+
+               /*
+                * Set caps based on capability queried from the converter.
+                * It will be constrained runtime based on ELD queried.
+                */
+               hdmi_dais[i].playback.formats = formats;
+               hdmi_dais[i].playback.rates = rates;
+               hdmi_dais[i].playback.rate_max = rate_max;
+               hdmi_dais[i].playback.rate_min = rate_min;
+               hdmi_dais[i].playback.channels_min = 2;
+               hdmi_dais[i].playback.channels_max = 2;
+               hdmi_dais[i].ops = &hdmi_dai_ops;
+
+               i++;
+       }
+
+       *dais = hdmi_dais;
+
        return 0;
 }
 
@@ -431,7 +1243,8 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid)
  * Parse all nodes and store the cvt/pin nids in array
  * Add one time initialization for pin and cvt widgets
  */
-static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
+static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
+               struct snd_soc_dai_driver **dais, int *num_dais)
 {
        hda_nid_t nid;
        int i, num_nodes;
@@ -439,6 +1252,9 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
        struct hdac_hdmi_priv *hdmi = edev->private_data;
        int ret;
 
+       hdac_hdmi_skl_enable_all_pins(hdac);
+       hdac_hdmi_skl_enable_dp12(hdac);
+
        num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
        if (!nid || num_nodes <= 0) {
                dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
@@ -479,19 +1295,107 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
        if (!hdmi->num_pin || !hdmi->num_cvt)
                return -EIO;
 
+       ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt);
+       if (ret) {
+               dev_err(&hdac->dev, "Failed to create dais with err: %d\n",
+                                                       ret);
+               return ret;
+       }
+
+       *num_dais = hdmi->num_cvt;
+
        return hdac_hdmi_init_dai_map(edev);
 }
 
+static void hdac_hdmi_eld_notify_cb(void *aptr, int port)
+{
+       struct hdac_ext_device *edev = aptr;
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_pin *pin;
+       struct snd_soc_codec *codec = edev->scodec;
+
+       /* Don't know how this mapping is derived */
+       hda_nid_t pin_nid = port + 0x04;
+
+       dev_dbg(&edev->hdac.dev, "%s: for pin: %d\n", __func__, pin_nid);
+
+       /*
+        * skip notification during system suspend (but not in runtime PM);
+        * the state will be updated at resume. Also since the ELD and
+        * connection states are updated in anyway at the end of the resume,
+        * we can skip it when received during PM process.
+        */
+       if (snd_power_get_state(codec->component.card->snd_card) !=
+                       SNDRV_CTL_POWER_D0)
+               return;
+
+       if (atomic_read(&edev->hdac.in_pm))
+               return;
+
+       list_for_each_entry(pin, &hdmi->pin_list, head) {
+               if (pin->nid == pin_nid)
+                       hdac_hdmi_present_sense(pin, 1);
+       }
+}
+
+static struct i915_audio_component_audio_ops aops = {
+       .pin_eld_notify = hdac_hdmi_eld_notify_cb,
+};
+
+int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device)
+{
+       char jack_name[NAME_SIZE];
+       struct snd_soc_codec *codec = dai->codec;
+       struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(&codec->component);
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_pcm *pcm;
+
+       /*
+        * this is a new PCM device, create new pcm and
+        * add to the pcm list
+        */
+       pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+       if (!pcm)
+               return -ENOMEM;
+       pcm->pcm_id = device;
+       pcm->cvt = hdmi->dai_map[dai->id].cvt;
+
+       list_add_tail(&pcm->head, &hdmi->pcm_list);
+
+       sprintf(jack_name, "HDMI/DP, pcm=%d Jack", device);
+
+       return snd_jack_new(dapm->card->snd_card, jack_name,
+               SND_JACK_AVOUT, &pcm->jack, true, false);
+}
+EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init);
+
 static int hdmi_codec_probe(struct snd_soc_codec *codec)
 {
        struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
        struct hdac_hdmi_priv *hdmi = edev->private_data;
        struct snd_soc_dapm_context *dapm =
                snd_soc_component_get_dapm(&codec->component);
+       struct hdac_hdmi_pin *pin;
+       int ret;
 
        edev->scodec = codec;
 
-       create_fill_widget_route_map(dapm, &hdmi->dai_map[0]);
+       ret = create_fill_widget_route_map(dapm);
+       if (ret < 0)
+               return ret;
+
+       aops.audio_ptr = edev;
+       ret = snd_hdac_i915_register_notifier(&aops);
+       if (ret < 0) {
+               dev_err(&edev->hdac.dev, "notifier register failed: err: %d\n",
+                               ret);
+               return ret;
+       }
+
+       list_for_each_entry(pin, &hdmi->pin_list, head)
+               hdac_hdmi_present_sense(pin, 1);
 
        /* Imp: Store the card pointer in hda_codec */
        edev->card = dapm->card->snd_card;
@@ -515,44 +1419,73 @@ static int hdmi_codec_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int hdmi_codec_resume(struct snd_soc_codec *codec)
+{
+       struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
+       struct hdac_hdmi_priv *hdmi = edev->private_data;
+       struct hdac_hdmi_pin *pin;
+       struct hdac_device *hdac = &edev->hdac;
+       struct hdac_bus *bus = hdac->bus;
+       int err;
+       unsigned long timeout;
+
+       hdac_hdmi_skl_enable_all_pins(&edev->hdac);
+       hdac_hdmi_skl_enable_dp12(&edev->hdac);
+
+       /* Power up afg */
+       if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) {
+
+               snd_hdac_codec_write(hdac, hdac->afg, 0,
+                       AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+               /* Wait till power state is set to D0 */
+               timeout = jiffies + msecs_to_jiffies(1000);
+               while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)
+                               && time_before(jiffies, timeout)) {
+                       msleep(50);
+               }
+       }
+
+       /*
+        * As the ELD notify callback request is not entertained while the
+        * device is in suspend state. Need to manually check detection of
+        * all pins here.
+        */
+       list_for_each_entry(pin, &hdmi->pin_list, head)
+               hdac_hdmi_present_sense(pin, 1);
+
+       /*
+        * Codec power is turned ON during controller resume.
+        * Turn it OFF here
+        */
+       err = snd_hdac_display_power(bus, false);
+       if (err < 0) {
+               dev_err(bus->dev,
+                       "Cannot turn OFF display power on i915, err: %d\n",
+                       err);
+               return err;
+       }
+
+       return 0;
+}
+#else
+#define hdmi_codec_resume NULL
+#endif
+
 static struct snd_soc_codec_driver hdmi_hda_codec = {
        .probe          = hdmi_codec_probe,
        .remove         = hdmi_codec_remove,
+       .resume         = hdmi_codec_resume,
        .idle_bias_off  = true,
 };
 
-static struct snd_soc_dai_ops hdmi_dai_ops = {
-       .startup = hdac_hdmi_pcm_open,
-       .shutdown = hdac_hdmi_pcm_close,
-       .hw_params = hdac_hdmi_set_hw_params,
-       .prepare = hdac_hdmi_playback_prepare,
-       .hw_free = hdac_hdmi_playback_cleanup,
-};
-
-static struct snd_soc_dai_driver hdmi_dais[] = {
-       {       .name = "intel-hdmi-hif1",
-               .playback = {
-                       .stream_name = "hif1",
-                       .channels_min = 2,
-                       .channels_max = 2,
-                       .rates = SNDRV_PCM_RATE_32000 |
-                               SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                               SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                               SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
-                       .formats = SNDRV_PCM_FMTBIT_S16_LE |
-                               SNDRV_PCM_FMTBIT_S20_3LE |
-                               SNDRV_PCM_FMTBIT_S24_LE |
-                               SNDRV_PCM_FMTBIT_S32_LE,
-
-               },
-               .ops = &hdmi_dai_ops,
-       },
-};
-
 static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
 {
        struct hdac_device *codec = &edev->hdac;
        struct hdac_hdmi_priv *hdmi_priv;
+       struct snd_soc_dai_driver *hdmi_dais = NULL;
+       int num_dais = 0;
        int ret = 0;
 
        hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
@@ -565,14 +1498,31 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
 
        INIT_LIST_HEAD(&hdmi_priv->pin_list);
        INIT_LIST_HEAD(&hdmi_priv->cvt_list);
+       INIT_LIST_HEAD(&hdmi_priv->pcm_list);
+       mutex_init(&hdmi_priv->pin_mutex);
 
-       ret = hdac_hdmi_parse_and_map_nid(edev);
-       if (ret < 0)
+       /*
+        * Turned off in the runtime_suspend during the first explicit
+        * pm_runtime_suspend call.
+        */
+       ret = snd_hdac_display_power(edev->hdac.bus, true);
+       if (ret < 0) {
+               dev_err(&edev->hdac.dev,
+                       "Cannot turn on display power on i915 err: %d\n",
+                       ret);
                return ret;
+       }
+
+       ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais);
+       if (ret < 0) {
+               dev_err(&codec->dev,
+                       "Failed in parse and map nid with err: %d\n", ret);
+               return ret;
+       }
 
        /* ASoC specific initialization */
        return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
-                       hdmi_dais, ARRAY_SIZE(hdmi_dais));
+                       hdmi_dais, num_dais);
 }
 
 static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
@@ -580,11 +1530,20 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
        struct hdac_hdmi_priv *hdmi = edev->private_data;
        struct hdac_hdmi_pin *pin, *pin_next;
        struct hdac_hdmi_cvt *cvt, *cvt_next;
+       struct hdac_hdmi_pcm *pcm, *pcm_next;
 
        snd_soc_unregister_codec(&edev->hdac.dev);
 
+       list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) {
+               pcm->cvt = NULL;
+               pcm->pin = NULL;
+               list_del(&pcm->head);
+               kfree(pcm);
+       }
+
        list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
                list_del(&cvt->head);
+               kfree(cvt->name);
                kfree(cvt);
        }
 
@@ -602,6 +1561,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
        struct hdac_ext_device *edev = to_hda_ext_device(dev);
        struct hdac_device *hdac = &edev->hdac;
        struct hdac_bus *bus = hdac->bus;
+       unsigned long timeout;
        int err;
 
        dev_dbg(dev, "Enter: %s\n", __func__);
@@ -611,10 +1571,19 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
                return 0;
 
        /* Power down afg */
-       if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3))
+       if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)) {
                snd_hdac_codec_write(hdac, hdac->afg, 0,
                        AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
 
+               /* Wait till power state is set to D3 */
+               timeout = jiffies + msecs_to_jiffies(1000);
+               while (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)
+                               && time_before(jiffies, timeout)) {
+
+                       msleep(50);
+               }
+       }
+
        err = snd_hdac_display_power(bus, false);
        if (err < 0) {
                dev_err(bus->dev, "Cannot turn on display power on i915\n");
@@ -643,6 +1612,9 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
                return err;
        }
 
+       hdac_hdmi_skl_enable_all_pins(&edev->hdac);
+       hdac_hdmi_skl_enable_dp12(&edev->hdac);
+
        /* Power up afg */
        if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0))
                snd_hdac_codec_write(hdac, hdac->afg, 0,
@@ -661,6 +1633,7 @@ static const struct dev_pm_ops hdac_hdmi_pm = {
 
 static const struct hda_device_id hdmi_list[] = {
        HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
+       HDA_CODEC_EXT_ENTRY(0x8086280a, 0x100000, "Broxton HDMI", 0),
        {}
 };
 
diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h
new file mode 100644 (file)
index 0000000..8dfd1e0
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __HDAC_HDMI_H__
+#define __HDAC_HDMI_H__
+
+int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm);
+
+#endif /* __HDAC_HDMI_H__ */
index 20dcc496d39c9d8ac01e4d49004f92823fdd37a6..fc22804cabc5942acca6921c034fa98f234041dc 100644 (file)
@@ -1496,7 +1496,7 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct max98088_pdata *pdata = max98088->pdata;
        int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
-       int sel = ucontrol->value.integer.value[0];
+       int sel = ucontrol->value.enumerated.item[0];
 
        if (channel < 0)
               return channel;
index 1fedac50355e954790a15b84ed6aab49b2bb98e3..3577003f39cf8feaba0d97bb313e277b3b763ce7 100644 (file)
@@ -1499,7 +1499,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct max98095_pdata *pdata = max98095->pdata;
        int channel = max98095_get_eq_channel(kcontrol->id.name);
        struct max98095_cdata *cdata;
-       unsigned int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.enumerated.item[0];
        struct max98095_eq_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
@@ -1653,7 +1653,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
        struct max98095_pdata *pdata = max98095->pdata;
        int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
        struct max98095_cdata *cdata;
-       unsigned int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.enumerated.item[0];
        struct max98095_biquad_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c
new file mode 100755 (executable)
index 0000000..2a22fdd
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * max9867.c -- max9867 ALSA SoC Audio driver
+ *
+ * Copyright 2013-15 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "max9867.h"
+
+static const char *const max9867_spmode[] = {
+       "Stereo Diff", "Mono Diff",
+       "Stereo Cap", "Mono Cap",
+       "Stereo Single", "Mono Single",
+       "Stereo Single Fast", "Mono Single Fast"
+};
+static const char *const max9867_sidetone_text[] = {
+       "None", "Left", "Right", "LeftRight", "LeftRightDiv2",
+};
+static const char *const max9867_filter_text[] = {"IIR", "FIR"};
+
+static SOC_ENUM_SINGLE_DECL(max9867_filter, MAX9867_CODECFLTR, 7,
+       max9867_filter_text);
+static SOC_ENUM_SINGLE_DECL(max9867_spkmode, MAX9867_MODECONFIG, 0,
+       max9867_spmode);
+static SOC_ENUM_SINGLE_DECL(max9867_sidetone, MAX9867_DACGAIN, 6,
+       max9867_sidetone_text);
+static DECLARE_TLV_DB_SCALE(max9860_capture_tlv, -600, 200, 0);
+static DECLARE_TLV_DB_SCALE(max9860_mic_tlv, 2000, 100, 1);
+static DECLARE_TLV_DB_SCALE(max9860_adc_left_tlv, -1200, 100, 1);
+static DECLARE_TLV_DB_SCALE(max9860_adc_right_tlv, -1200, 100, 1);
+static const unsigned int max98088_micboost_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+       2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+};
+
+static const struct snd_kcontrol_new max9867_snd_controls[] = {
+       SOC_DOUBLE_R("Master Playback Volume", MAX9867_LEFTVOL,
+                               MAX9867_RIGHTVOL, 0, 63, 1),
+       SOC_DOUBLE_R_TLV("Capture Volume", MAX9867_LEFTMICGAIN,
+                       MAX9867_RIGHTMICGAIN,
+                       0, 15, 1, max9860_capture_tlv),
+       SOC_DOUBLE_R_TLV("Mic Volume", MAX9867_LEFTMICGAIN,
+                       MAX9867_RIGHTMICGAIN, 0, 31, 1, max9860_mic_tlv),
+       SOC_DOUBLE_R_TLV("Mic Boost Volume", MAX9867_LEFTMICGAIN,
+                       MAX9867_RIGHTMICGAIN, 5, 3, 0, max98088_micboost_tlv),
+       SOC_ENUM("Digital Sidetone Src", max9867_sidetone),
+       SOC_SINGLE("Sidetone Volume", MAX9867_DACGAIN, 0, 31, 1),
+       SOC_SINGLE("DAC Volume", MAX9867_DACLEVEL, 4, 3, 0),
+       SOC_SINGLE("DAC Attenuation", MAX9867_DACLEVEL, 0, 15, 1),
+       SOC_SINGLE_TLV("ADC Left Volume", MAX9867_ADCLEVEL,
+                       4, 15, 1, max9860_adc_left_tlv),
+       SOC_SINGLE_TLV("ADC Right Volume", MAX9867_ADCLEVEL,
+                       0, 15, 1, max9860_adc_right_tlv),
+       SOC_ENUM("Speaker Mode", max9867_spkmode),
+       SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0),
+       SOC_SINGLE("ZCD Switch", MAX9867_MODECONFIG, 5, 1, 0),
+       SOC_ENUM("DSP Filter", max9867_filter),
+};
+
+static const char *const max9867_mux[] = {"None", "Mic", "Line", "Mic_Line"};
+
+static SOC_ENUM_SINGLE_DECL(max9867_mux_enum,
+       MAX9867_INPUTCONFIG, MAX9867_INPUT_SHIFT,
+       max9867_mux);
+
+static const struct snd_kcontrol_new max9867_dapm_mux_controls =
+       SOC_DAPM_ENUM("Route", max9867_mux_enum);
+
+static const struct snd_kcontrol_new max9867_left_dapm_control =
+       SOC_DAPM_SINGLE("Switch", MAX9867_PWRMAN, 6, 1, 0);
+static const struct snd_kcontrol_new max9867_right_dapm_control =
+       SOC_DAPM_SINGLE("Switch", MAX9867_PWRMAN, 5, 1, 0);
+static const struct snd_kcontrol_new max9867_line_dapm_control =
+       SOC_DAPM_SINGLE("Switch", MAX9867_LEFTLINELVL, 6, 1, 1);
+
+static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = {
+       SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_DAC("Left DAC", NULL, MAX9867_PWRMAN, 3, 0),
+       SND_SOC_DAPM_DAC("Right DAC", NULL, MAX9867_PWRMAN, 2, 0),
+       SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("HPOUT"),
+
+       SND_SOC_DAPM_AIF_IN("DAI_IN", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture", MAX9867_PWRMAN, 1, 0),
+       SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture", MAX9867_PWRMAN, 0, 0),
+       SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
+               &max9867_dapm_mux_controls),
+
+       SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_SWITCH("Left Line", MAX9867_LEFTLINELVL, 6, 1,
+               &max9867_left_dapm_control),
+       SND_SOC_DAPM_SWITCH("Right Line", MAX9867_RIGTHLINELVL, 6, 1,
+               &max9867_right_dapm_control),
+       SND_SOC_DAPM_SWITCH("Line Mixer", SND_SOC_NOPM, 0, 0,
+               &max9867_line_dapm_control),
+       SND_SOC_DAPM_INPUT("LINE_IN"),
+};
+
+static const struct snd_soc_dapm_route max9867_audio_map[] = {
+       {"Left DAC", NULL, "DAI_OUT"},
+       {"Right DAC", NULL, "DAI_OUT"},
+       {"Output Mixer", NULL, "Left DAC"},
+       {"Output Mixer", NULL, "Right DAC"},
+       {"HPOUT", NULL, "Output Mixer"},
+
+       {"Left ADC", NULL, "DAI_IN"},
+       {"Right ADC", NULL, "DAI_IN"},
+       {"Input Mixer", NULL, "Left ADC"},
+       {"Input Mixer", NULL, "Right ADC"},
+       {"Input Mux", "Line", "Input Mixer"},
+       {"Input Mux", "Mic", "Input Mixer"},
+       {"Input Mux", "Mic_Line", "Input Mixer"},
+       {"Right Line", "Switch", "Input Mux"},
+       {"Left Line", "Switch", "Input Mux"},
+       {"LINE_IN", NULL, "Left Line"},
+       {"LINE_IN", NULL, "Right Line"},
+};
+
+enum rates {
+       pcm_rate_8, pcm_rate_16, pcm_rate_24,
+       pcm_rate_32, pcm_rate_44,
+       pcm_rate_48, max_pcm_rate,
+};
+
+struct ni_div_rates {
+       u32 mclk;
+       u16 ni[max_pcm_rate];
+} ni_div[] = {
+       {11289600, {0x116A, 0x22D4, 0x343F, 0x45A9, 0x6000, 0x687D} },
+       {12000000, {0x1062, 0x20C5, 0x3127, 0x4189, 0x5A51, 0x624E} },
+       {12288000, {0x1000, 0x2000, 0x3000, 0x4000, 0x5833, 0x6000} },
+       {13000000, {0x0F20, 0x1E3F, 0x2D5F, 0x3C7F, 0x535F, 0x5ABE} },
+       {19200000, {0x0A3D, 0x147B, 0x1EB8, 0x28F6, 0x3873, 0x3D71} },
+       {24000000, {0x1062, 0x20C5, 0x1893, 0x4189, 0x5A51, 0x624E} },
+       {26000000, {0x0F20, 0x1E3F, 0x16AF, 0x3C7F, 0x535F, 0x5ABE} },
+       {27000000, {0x0E90, 0x1D21, 0x15D8, 0x3A41, 0x5048, 0x5762} },
+};
+
+static inline int get_ni_value(int mclk, int rate)
+{
+       int i, ret = 0;
+
+       /* find the closest rate index*/
+       for (i = 0; i < ARRAY_SIZE(ni_div); i++) {
+               if (ni_div[i].mclk >= mclk)
+                       break;
+       }
+       if (i == ARRAY_SIZE(ni_div))
+               return -EINVAL;
+
+       switch (rate) {
+       case 8000:
+               return ni_div[i].ni[pcm_rate_8];
+       case 16000:
+               return ni_div[i].ni[pcm_rate_16];
+       case 32000:
+               return ni_div[i].ni[pcm_rate_32];
+       case 44100:
+               return ni_div[i].ni[pcm_rate_44];
+       case 48000:
+               return ni_div[i].ni[pcm_rate_48];
+       default:
+               pr_err("%s wrong rate %d\n", __func__, rate);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int max9867_dai_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
+       unsigned int ni_h, ni_l;
+       int value;
+
+       value = get_ni_value(max9867->sysclk, params_rate(params));
+       if (value < 0)
+               return value;
+
+       ni_h = (0xFF00 & value) >> 8;
+       ni_l = 0x00FF & value;
+       /* set up the ni value */
+       regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
+               MAX9867_NI_HIGH_MASK, ni_h);
+       regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
+               MAX9867_NI_LOW_MASK, ni_l);
+       if (!max9867->master) {
+               /*
+                * digital pll locks on to any externally supplied LRCLK signal
+                * and also enable rapid lock mode.
+                */
+               regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
+                       MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK);
+               regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
+                       MAX9867_PLL, MAX9867_PLL);
+       } else {
+               unsigned long int bclk_rate, pclk_bclk_ratio;
+               int bclk_value;
+
+               bclk_rate = params_rate(params) * 2 * params_width(params);
+               pclk_bclk_ratio = max9867->pclk/bclk_rate;
+               switch (params_width(params)) {
+               case 8:
+               case 16:
+                       switch (pclk_bclk_ratio) {
+                       case 2:
+                               bclk_value = MAX9867_IFC1B_PCLK_2;
+                               break;
+                       case 4:
+                               bclk_value = MAX9867_IFC1B_PCLK_4;
+                               break;
+                       case 8:
+                               bclk_value = MAX9867_IFC1B_PCLK_8;
+                               break;
+                       case 16:
+                               bclk_value = MAX9867_IFC1B_PCLK_16;
+                               break;
+                       default:
+                               dev_err(codec->dev,
+                                       "unsupported sampling rate\n");
+                               return -EINVAL;
+                       }
+                       break;
+               case 24:
+                       bclk_value = MAX9867_IFC1B_24BIT;
+                       break;
+               case 32:
+                       bclk_value = MAX9867_IFC1B_32BIT;
+                       break;
+               default:
+                       dev_err(codec->dev, "unsupported sampling rate\n");
+                       return -EINVAL;
+               }
+               regmap_update_bits(max9867->regmap, MAX9867_IFC1B,
+                       MAX9867_IFC1B_BCLK_MASK, bclk_value);
+       }
+       return 0;
+}
+
+static int max9867_prepare(struct snd_pcm_substream *substream,
+                        struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
+
+       regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
+               MAX9867_SHTDOWN_MASK, MAX9867_SHTDOWN_MASK);
+       return 0;
+}
+
+static int max9867_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
+
+       if (mute)
+               regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL,
+                       MAX9867_DAC_MUTE_MASK, MAX9867_DAC_MUTE_MASK);
+       else
+               regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL,
+                       MAX9867_DAC_MUTE_MASK, 0);
+       return 0;
+}
+
+static int max9867_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
+       int value = 0;
+
+       /* Set the prescaler based on the master clock frequency*/
+       if (freq >= 10000000 && freq <= 20000000) {
+               value |= MAX9867_PSCLK_10_20;
+               max9867->pclk =  freq;
+       } else if (freq >= 20000000 && freq <= 40000000) {
+               value |= MAX9867_PSCLK_20_40;
+               max9867->pclk =  freq/2;
+       } else if (freq >= 40000000 && freq <= 60000000) {
+               value |= MAX9867_PSCLK_40_60;
+               max9867->pclk =  freq/4;
+       } else {
+               pr_err("bad clock frequency %d", freq);
+               return -EINVAL;
+       }
+       value = value << MAX9867_PSCLK_SHIFT;
+       max9867->sysclk = freq;
+       /* exact integer mode is not supported */
+       value &= ~MAX9867_FREQ_MASK;
+       regmap_update_bits(max9867->regmap, MAX9867_SYSCLK,
+                       MAX9867_PSCLK_MASK, value);
+       return 0;
+}
+
+static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
+       u8 iface1A = 0, iface1B = 0;
+       int ret;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               max9867->master = 1;
+               iface1A |= MAX9867_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               max9867->master = 0;
+               iface1A &= ~MAX9867_MASTER;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* for i2s compatible mode */
+       iface1A |= MAX9867_I2S_DLY;
+       /* SDOUT goes to hiz state after all data is transferred */
+       iface1A |= MAX9867_SDOUT_HIZ;
+
+       /* Clock inversion bits, BCI and WCI */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               iface1A |= MAX9867_WCI_MODE | MAX9867_BCI_MODE;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface1A |= MAX9867_BCI_MODE;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               iface1A |= MAX9867_WCI_MODE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A);
+       ret = regmap_write(max9867->regmap, MAX9867_IFC1B, iface1B);
+       return 0;
+}
+
+static struct snd_soc_dai_ops max9867_dai_ops = {
+       .set_fmt = max9867_dai_set_fmt,
+       .set_sysclk     = max9867_set_dai_sysclk,
+       .prepare        = max9867_prepare,
+       .digital_mute   = max9867_mute,
+       .hw_params = max9867_dai_hw_params,
+};
+
+#define MAX9867_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+       SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+#define MAX9867_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+
+static struct snd_soc_dai_driver max9867_dai[] = {
+       {
+       .name = "max9867-aif1",
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = MAX9867_RATES,
+               .formats = MAX9867_FORMATS,
+       },
+       .capture = {
+               .stream_name = "HiFi Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = MAX9867_RATES,
+               .formats = MAX9867_FORMATS,
+       },
+       .ops = &max9867_dai_ops,
+       }
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int max9867_suspend(struct device *dev)
+{
+       struct max9867_priv *max9867 = dev_get_drvdata(dev);
+
+       /* Drop down to power saving mode when system is suspended */
+       regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
+               MAX9867_SHTDOWN_MASK, ~MAX9867_SHTDOWN_MASK);
+       return 0;
+}
+
+static int max9867_resume(struct device *dev)
+{
+       struct max9867_priv *max9867 = dev_get_drvdata(dev);
+
+       regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
+               MAX9867_SHTDOWN_MASK, MAX9867_SHTDOWN_MASK);
+       return 0;
+}
+#endif
+
+static int max9867_probe(struct snd_soc_codec *codec)
+{
+       struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "max98090_probe\n");
+       max9867->codec = codec;
+       return 0;
+}
+
+static struct snd_soc_codec_driver max9867_codec = {
+       .probe = max9867_probe,
+       .controls = max9867_snd_controls,
+       .num_controls = ARRAY_SIZE(max9867_snd_controls),
+       .dapm_routes = max9867_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(max9867_audio_map),
+       .dapm_widgets = max9867_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(max9867_dapm_widgets),
+};
+
+static bool max9867_volatile_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX9867_STATUS:
+       case MAX9867_JACKSTATUS:
+       case MAX9867_AUXHIGH:
+       case MAX9867_AUXLOW:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct reg_default max9867_reg[] = {
+       { 0x04, 0x00 },
+       { 0x05, 0x00 },
+       { 0x06, 0x00 },
+       { 0x07, 0x00 },
+       { 0x08, 0x00 },
+       { 0x09, 0x00 },
+       { 0x0A, 0x00 },
+       { 0x0B, 0x00 },
+       { 0x0C, 0x00 },
+       { 0x0D, 0x00 },
+       { 0x0E, 0x00 },
+       { 0x0F, 0x00 },
+       { 0x10, 0x00 },
+       { 0x11, 0x00 },
+       { 0x12, 0x00 },
+       { 0x13, 0x00 },
+       { 0x14, 0x00 },
+       { 0x15, 0x00 },
+       { 0x16, 0x00 },
+       { 0x17, 0x00 },
+};
+
+static const struct regmap_config max9867_regmap = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .max_register   = MAX9867_REVISION,
+       .reg_defaults   = max9867_reg,
+       .num_reg_defaults = ARRAY_SIZE(max9867_reg),
+       .volatile_reg   = max9867_volatile_register,
+       .cache_type     = REGCACHE_RBTREE,
+};
+
+static int max9867_i2c_probe(struct i2c_client *i2c,
+               const struct i2c_device_id *id)
+{
+       struct max9867_priv *max9867;
+       int ret = 0, reg;
+
+       max9867 = devm_kzalloc(&i2c->dev,
+                       sizeof(*max9867), GFP_KERNEL);
+       if (!max9867)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, max9867);
+       max9867->regmap = devm_regmap_init_i2c(i2c, &max9867_regmap);
+       if (IS_ERR(max9867->regmap)) {
+               ret = PTR_ERR(max9867->regmap);
+               dev_err(&i2c->dev,
+                               "Failed to allocate regmap: %d\n", ret);
+               return ret;
+       }
+       ret = regmap_read(max9867->regmap,
+                       MAX9867_REVISION, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read: %d\n", ret);
+               return ret;
+       }
+       dev_info(&i2c->dev, "device revision: %x\n", reg);
+       ret = snd_soc_register_codec(&i2c->dev, &max9867_codec,
+                       max9867_dai, ARRAY_SIZE(max9867_dai));
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int max9867_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       return 0;
+}
+
+static const struct i2c_device_id max9867_i2c_id[] = {
+       { "max9867", 0 },
+       { }
+};
+
+static const struct of_device_id max9867_of_match[] = {
+       { .compatible = "maxim,max9867", },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, max9867_i2c_id);
+
+static const struct dev_pm_ops max9867_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(max9867_suspend, max9867_resume)
+};
+
+static struct i2c_driver max9867_i2c_driver = {
+       .driver = {
+               .name = "max9867",
+               .of_match_table = of_match_ptr(max9867_of_match),
+               .pm = &max9867_pm_ops,
+       },
+       .probe  = max9867_i2c_probe,
+       .remove = max9867_i2c_remove,
+       .id_table = max9867_i2c_id,
+};
+
+module_i2c_driver(max9867_i2c_driver);
+
+MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC MAX9867 driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max9867.h b/sound/soc/codecs/max9867.h
new file mode 100755 (executable)
index 0000000..65590b4
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * max9867.h -- MAX9867 ALSA SoC Audio driver
+ *
+ * Copyright 2013-2015 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX9867_H
+#define _MAX9867_H
+
+/* MAX9867 register space */
+
+#define MAX9867_STATUS        0x00
+#define MAX9867_JACKSTATUS   0x01
+#define MAX9867_AUXHIGH      0x02
+#define MAX9867_AUXLOW       0x03
+#define MAX9867_INTEN        0x04
+#define MAX9867_SYSCLK       0x05
+#define MAX9867_FREQ_MASK    0xF
+#define MAX9867_PSCLK_SHIFT  0x4
+#define MAX9867_PSCLK_WIDTH  0x2
+#define MAX9867_PSCLK_MASK   (0x03<<MAX9867_PSCLK_SHIFT)
+#define MAX9867_PSCLK_10_20  0x1
+#define MAX9867_PSCLK_20_40  0x2
+#define MAX9867_PSCLK_40_60  0x3
+#define MAX9867_AUDIOCLKHIGH 0x06
+#define MAX9867_NI_HIGH_WIDTH 0x7
+#define MAX9867_NI_HIGH_MASK 0x7F
+#define MAX9867_NI_LOW_MASK 0x7F
+#define MAX9867_NI_LOW_SHIFT 0x1
+#define MAX9867_PLL     (1<<7)
+#define MAX9867_AUDIOCLKLOW  0x07
+#define MAX9867_RAPID_LOCK   0x01
+#define MAX9867_IFC1A        0x08
+#define MAX9867_MASTER       (1<<7)
+#define MAX9867_I2S_DLY      (1<<4)
+#define MAX9867_SDOUT_HIZ    (1<<3)
+#define MAX9867_TDM_MODE     (1<<2)
+#define MAX9867_WCI_MODE     (1<<6)
+#define MAX9867_BCI_MODE     (1<<5)
+#define MAX9867_IFC1B        0x09
+#define MAX9867_IFC1B_BCLK_MASK 7
+#define MAX9867_IFC1B_32BIT  0x01
+#define MAX9867_IFC1B_24BIT  0x02
+#define MAX9867_IFC1B_PCLK_2 4
+#define MAX9867_IFC1B_PCLK_4 5
+#define MAX9867_IFC1B_PCLK_8 6
+#define MAX9867_IFC1B_PCLK_16 7
+#define MAX9867_CODECFLTR    0x0a
+#define MAX9867_DACGAIN      0x0b
+#define MAX9867_DACLEVEL     0x0c
+#define MAX9867_DAC_MUTE_SHIFT 0x6
+#define MAX9867_DAC_MUTE_WIDTH 0x1
+#define MAX9867_DAC_MUTE_MASK (0x1<<MAX9867_DAC_MUTE_SHIFT)
+#define MAX9867_ADCLEVEL     0x0d
+#define MAX9867_LEFTLINELVL  0x0e
+#define MAX9867_RIGTHLINELVL 0x0f
+#define MAX9867_LEFTVOL      0x10
+#define MAX9867_RIGHTVOL     0x11
+#define MAX9867_LEFTMICGAIN  0x12
+#define MAX9867_RIGHTMICGAIN 0x13
+#define MAX9867_INPUTCONFIG  0x14
+#define MAX9867_INPUT_SHIFT  0x6
+#define MAX9867_MICCONFIG    0x15
+#define MAX9867_MODECONFIG   0x16
+#define MAX9867_PWRMAN       0x17
+#define MAX9867_SHTDOWN_MASK (1<<7)
+#define MAX9867_REVISION     0xff
+
+#define MAX9867_CACHEREGNUM 10
+
+/* codec private data */
+struct max9867_priv {
+       struct regmap *regmap;
+       struct snd_soc_codec *codec;
+       unsigned int sysclk;
+       unsigned int pclk;
+       unsigned int master;
+};
+#endif
diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c
new file mode 100644 (file)
index 0000000..8d14ada
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * max98926.c -- ALSA SoC MAX98926 driver
+ * Copyright 2013-15 Maxim Integrated Products
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "max98926.h"
+
+static const char * const max98926_boost_voltage_txt[] = {
+       "8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V",
+       "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V"
+};
+
+static const char * const max98926_boost_current_txt[] = {
+       "0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0",
+       "2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4"
+};
+
+static const char *const max98926_dai_txt[] = {
+       "Left", "Right", "LeftRight", "LeftRightDiv2",
+};
+
+static const char *const max98926_pdm_ch_text[] = {
+       "Current", "Voltage",
+};
+
+static const char *const max98926_hpf_cutoff_txt[] = {
+       "Disable", "DC Block", "100Hz",
+       "200Hz", "400Hz", "800Hz",
+};
+
+static const struct reg_default max98926_reg[] = {
+       { 0x0B, 0x00 }, /* IRQ Enable0 */
+       { 0x0C, 0x00 }, /* IRQ Enable1 */
+       { 0x0D, 0x00 }, /* IRQ Enable2 */
+       { 0x0E, 0x00 }, /* IRQ Clear0 */
+       { 0x0F, 0x00 }, /* IRQ Clear1 */
+       { 0x10, 0x00 }, /* IRQ Clear2 */
+       { 0x11, 0xC0 }, /* Map0 */
+       { 0x12, 0x00 }, /* Map1 */
+       { 0x13, 0x00 }, /* Map2 */
+       { 0x14, 0xF0 }, /* Map3 */
+       { 0x15, 0x00 }, /* Map4 */
+       { 0x16, 0xAB }, /* Map5 */
+       { 0x17, 0x89 }, /* Map6 */
+       { 0x18, 0x00 }, /* Map7 */
+       { 0x19, 0x00 }, /* Map8 */
+       { 0x1A, 0x04 }, /* DAI Clock Mode 1 */
+       { 0x1B, 0x00 }, /* DAI Clock Mode 2 */
+       { 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */
+       { 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */
+       { 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */
+       { 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */
+       { 0x20, 0x50 }, /* Format */
+       { 0x21, 0x00 }, /* TDM Slot Select */
+       { 0x22, 0x00 }, /* DOUT Configuration VMON */
+       { 0x23, 0x00 }, /* DOUT Configuration IMON */
+       { 0x24, 0x00 }, /* DOUT Configuration VBAT */
+       { 0x25, 0x00 }, /* DOUT Configuration VBST */
+       { 0x26, 0x00 }, /* DOUT Configuration FLAG */
+       { 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */
+       { 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */
+       { 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */
+       { 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */
+       { 0x2B, 0x02 }, /* DOUT Drive Strength */
+       { 0x2C, 0x90 }, /* Filters */
+       { 0x2D, 0x00 }, /* Gain */
+       { 0x2E, 0x02 }, /* Gain Ramping */
+       { 0x2F, 0x00 }, /* Speaker Amplifier */
+       { 0x30, 0x0A }, /* Threshold */
+       { 0x31, 0x00 }, /* ALC Attack */
+       { 0x32, 0x80 }, /* ALC Atten and Release */
+       { 0x33, 0x00 }, /* ALC Infinite Hold Release */
+       { 0x34, 0x92 }, /* ALC Configuration */
+       { 0x35, 0x01 }, /* Boost Converter */
+       { 0x36, 0x00 }, /* Block Enable */
+       { 0x37, 0x00 }, /* Configuration */
+       { 0x38, 0x00 }, /* Global Enable */
+       { 0x3A, 0x00 }, /* Boost Limiter */
+};
+
+static const struct soc_enum max98926_voltage_enum[] = {
+       SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, 0,
+               ARRAY_SIZE(max98926_pdm_ch_text),
+               max98926_pdm_ch_text),
+};
+
+static const struct snd_kcontrol_new max98926_voltage_control =
+       SOC_DAPM_ENUM("Route", max98926_voltage_enum);
+
+static const struct soc_enum max98926_current_enum[] = {
+       SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS,
+               MAX98926_PDM_SOURCE_1_SHIFT,
+               ARRAY_SIZE(max98926_pdm_ch_text),
+               max98926_pdm_ch_text),
+};
+
+static const struct snd_kcontrol_new max98926_current_control =
+       SOC_DAPM_ENUM("Route", max98926_current_enum);
+
+static const struct snd_kcontrol_new max98926_mixer_controls[] = {
+       SOC_DAPM_SINGLE("PCM Single Switch", MAX98926_SPK_AMP,
+               MAX98926_INSELECT_MODE_SHIFT, 0, 0),
+       SOC_DAPM_SINGLE("PDM Single Switch", MAX98926_SPK_AMP,
+               MAX98926_INSELECT_MODE_SHIFT, 1, 0),
+};
+
+static const struct snd_kcontrol_new max98926_dai_controls[] = {
+       SOC_DAPM_SINGLE("Left", MAX98926_GAIN,
+               MAX98926_DAC_IN_SEL_SHIFT, 0, 0),
+       SOC_DAPM_SINGLE("Right", MAX98926_GAIN,
+               MAX98926_DAC_IN_SEL_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("LeftRight", MAX98926_GAIN,
+               MAX98926_DAC_IN_SEL_SHIFT, 2, 0),
+       SOC_DAPM_SINGLE("(Left+Right)/2 Switch", MAX98926_GAIN,
+               MAX98926_DAC_IN_SEL_SHIFT, 3, 0),
+};
+
+static const struct snd_soc_dapm_widget max98926_dapm_widgets[] = {
+       SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0,
+               SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_DAC("Amp Enable", NULL, MAX98926_BLOCK_ENABLE,
+               MAX98926_SPK_EN_SHIFT, 0),
+       SND_SOC_DAPM_SUPPLY("Global Enable", MAX98926_GLOBAL_ENABLE,
+               MAX98926_EN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("VI Enable", MAX98926_BLOCK_ENABLE,
+               MAX98926_ADC_IMON_EN_WIDTH |
+               MAX98926_ADC_VMON_EN_SHIFT,
+               0, NULL, 0),
+       SND_SOC_DAPM_PGA("BST Enable", MAX98926_BLOCK_ENABLE,
+               MAX98926_BST_EN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("BE_OUT"),
+       SND_SOC_DAPM_MIXER("PCM Sel", MAX98926_SPK_AMP,
+               MAX98926_INSELECT_MODE_SHIFT, 0,
+               &max98926_mixer_controls[0],
+               ARRAY_SIZE(max98926_mixer_controls)),
+       SND_SOC_DAPM_MIXER("DAI Sel",
+               MAX98926_GAIN, MAX98926_DAC_IN_SEL_SHIFT, 0,
+               &max98926_dai_controls[0],
+               ARRAY_SIZE(max98926_dai_controls)),
+       SND_SOC_DAPM_MUX("PDM CH1 Source",
+               MAX98926_DAI_CLK_DIV_N_LSBS,
+               MAX98926_PDM_CURRENT_SHIFT,
+               0, &max98926_current_control),
+       SND_SOC_DAPM_MUX("PDM CH0 Source",
+               MAX98926_DAI_CLK_DIV_N_LSBS,
+               MAX98926_PDM_VOLTAGE_SHIFT,
+               0, &max98926_voltage_control),
+};
+
+static const struct snd_soc_dapm_route max98926_audio_map[] = {
+       {"VI Enable", NULL, "DAI_OUT"},
+       {"DAI Sel", "Left", "VI Enable"},
+       {"DAI Sel", "Right", "VI Enable"},
+       {"DAI Sel", "LeftRight", "VI Enable"},
+       {"DAI Sel", "LeftRightDiv2", "VI Enable"},
+       {"PCM Sel", "PCM", "DAI Sel"},
+
+       {"PDM CH1 Source", "Current", "DAI_OUT"},
+       {"PDM CH1 Source", "Voltage", "DAI_OUT"},
+       {"PDM CH0 Source", "Current", "DAI_OUT"},
+       {"PDM CH0 Source", "Voltage", "DAI_OUT"},
+       {"PCM Sel", "Analog", "PDM CH1 Source"},
+       {"PCM Sel", "Analog", "PDM CH0 Source"},
+       {"Amp Enable", NULL, "PCM Sel"},
+
+       {"BST Enable", NULL, "Amp Enable"},
+       {"BE_OUT", NULL, "BST Enable"},
+};
+
+static bool max98926_volatile_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX98926_VBAT_DATA:
+       case MAX98926_VBST_DATA:
+       case MAX98926_LIVE_STATUS0:
+       case MAX98926_LIVE_STATUS1:
+       case MAX98926_LIVE_STATUS2:
+       case MAX98926_STATE0:
+       case MAX98926_STATE1:
+       case MAX98926_STATE2:
+       case MAX98926_FLAG0:
+       case MAX98926_FLAG1:
+       case MAX98926_FLAG2:
+       case MAX98926_VERSION:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool max98926_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX98926_IRQ_CLEAR0:
+       case MAX98926_IRQ_CLEAR1:
+       case MAX98926_IRQ_CLEAR2:
+       case MAX98926_ALC_HOLD_RLS:
+               return false;
+       default:
+               return true;
+       }
+};
+
+DECLARE_TLV_DB_SCALE(max98926_spk_tlv, -600, 100, 0);
+DECLARE_TLV_DB_RANGE(max98926_current_tlv,
+       0, 11, TLV_DB_SCALE_ITEM(20, 20, 0),
+       12, 15, TLV_DB_SCALE_ITEM(320, 40, 0),
+);
+
+static SOC_ENUM_SINGLE_DECL(max98926_dac_hpf_cutoff,
+               MAX98926_FILTERS, MAX98926_DAC_HPF_SHIFT,
+               max98926_hpf_cutoff_txt);
+
+static SOC_ENUM_SINGLE_DECL(max98926_boost_voltage,
+               MAX98926_CONFIGURATION, MAX98926_BST_VOUT_SHIFT,
+               max98926_boost_voltage_txt);
+
+static const struct snd_kcontrol_new max98926_snd_controls[] = {
+       SOC_SINGLE_TLV("Speaker Volume", MAX98926_GAIN,
+               MAX98926_SPK_GAIN_SHIFT,
+               (1<<MAX98926_SPK_GAIN_WIDTH)-1, 0,
+               max98926_spk_tlv),
+       SOC_SINGLE("Ramp Switch", MAX98926_GAIN_RAMPING,
+               MAX98926_SPK_RMP_EN_SHIFT, 1, 0),
+       SOC_SINGLE("ZCD Switch", MAX98926_GAIN_RAMPING,
+               MAX98926_SPK_ZCD_EN_SHIFT, 1, 0),
+       SOC_SINGLE("ALC Switch", MAX98926_THRESHOLD,
+               MAX98926_ALC_EN_SHIFT, 1, 0),
+       SOC_SINGLE("ALC Threshold", MAX98926_THRESHOLD,
+               MAX98926_ALC_TH_SHIFT,
+               (1<<MAX98926_ALC_TH_WIDTH)-1, 0),
+       SOC_ENUM("Boost Output Voltage", max98926_boost_voltage),
+       SOC_SINGLE_TLV("Boost Current Limit", MAX98926_BOOST_LIMITER,
+               MAX98926_BST_ILIM_SHIFT,
+               (1<<MAX98926_BST_ILIM_SHIFT)-1, 0,
+               max98926_current_tlv),
+       SOC_ENUM("DAC HPF Cutoff", max98926_dac_hpf_cutoff),
+       SOC_DOUBLE("PDM Channel One", MAX98926_DAI_CLK_DIV_N_LSBS,
+               MAX98926_PDM_CHANNEL_1_SHIFT,
+               MAX98926_PDM_CHANNEL_1_HIZ, 1, 0),
+       SOC_DOUBLE("PDM Channel Zero", MAX98926_DAI_CLK_DIV_N_LSBS,
+               MAX98926_PDM_CHANNEL_0_SHIFT,
+               MAX98926_PDM_CHANNEL_0_HIZ, 1, 0),
+};
+
+static const struct {
+       int rate;
+       int  sr;
+} rate_table[] = {
+       {
+               .rate = 8000,
+               .sr = 0,
+       },
+       {
+               .rate = 11025,
+               .sr = 1,
+       },
+       {
+               .rate = 12000,
+               .sr = 2,
+       },
+       {
+               .rate = 16000,
+               .sr = 3,
+       },
+       {
+               .rate = 22050,
+               .sr = 4,
+       },
+       {
+               .rate = 24000,
+               .sr = 5,
+       },
+       {
+               .rate = 32000,
+               .sr = 6,
+       },
+       {
+               .rate = 44100,
+               .sr = 7,
+       },
+       {
+               .rate = 48000,
+               .sr = 8,
+       },
+};
+
+static void max98926_set_sense_data(struct max98926_priv *max98926)
+{
+       regmap_update_bits(max98926->regmap,
+               MAX98926_DOUT_CFG_VMON,
+               MAX98926_DAI_VMON_EN_MASK,
+               MAX98926_DAI_VMON_EN_MASK);
+       regmap_update_bits(max98926->regmap,
+               MAX98926_DOUT_CFG_IMON,
+               MAX98926_DAI_IMON_EN_MASK,
+               MAX98926_DAI_IMON_EN_MASK);
+
+       if (!max98926->interleave_mode) {
+               /* set VMON slots */
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_DOUT_CFG_VMON,
+                       MAX98926_DAI_VMON_SLOT_MASK,
+                       max98926->v_slot);
+               /* set IMON slots */
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_DOUT_CFG_IMON,
+                       MAX98926_DAI_IMON_SLOT_MASK,
+                       max98926->i_slot);
+       } else {
+               /* enable interleave mode */
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_FORMAT,
+                       MAX98926_DAI_INTERLEAVE_MASK,
+                       MAX98926_DAI_INTERLEAVE_MASK);
+               /* set interleave slots */
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_DOUT_CFG_VBAT,
+                       MAX98926_DAI_INTERLEAVE_SLOT_MASK,
+                       max98926->v_slot);
+       }
+}
+
+static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec);
+       unsigned int invert = 0;
+
+       dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               max98926_set_sense_data(max98926);
+               break;
+       default:
+               dev_err(codec->dev, "DAI clock mode unsupported");
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               invert = MAX98926_DAI_WCI_MASK;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               invert = MAX98926_DAI_BCI_MASK;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK;
+               break;
+       default:
+               dev_err(codec->dev, "DAI invert mode unsupported");
+               return -EINVAL;
+       }
+
+       regmap_write(max98926->regmap,
+                       MAX98926_FORMAT, MAX98926_DAI_DLY_MASK);
+       regmap_update_bits(max98926->regmap, MAX98926_FORMAT,
+                       MAX98926_DAI_BCI_MASK, invert);
+       return 0;
+}
+
+static int max98926_dai_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params,
+               struct snd_soc_dai *dai)
+{
+       int dai_sr = -EINVAL;
+       int rate = params_rate(params), i;
+       struct snd_soc_codec *codec = dai->codec;
+       struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec);
+       int blr_clk_ratio;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_FORMAT,
+                       MAX98926_DAI_CHANSZ_MASK,
+                       MAX98926_DAI_CHANSZ_16);
+               max98926->ch_size = 16;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_FORMAT,
+                       MAX98926_DAI_CHANSZ_MASK,
+                       MAX98926_DAI_CHANSZ_24);
+               max98926->ch_size = 24;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_FORMAT,
+                       MAX98926_DAI_CHANSZ_MASK,
+                       MAX98926_DAI_CHANSZ_32);
+               max98926->ch_size = 32;
+               break;
+       default:
+               dev_dbg(codec->dev, "format unsupported %d",
+                       params_format(params));
+               return -EINVAL;
+       }
+
+       /* BCLK/LRCLK ratio calculation */
+       blr_clk_ratio = params_channels(params) * max98926->ch_size;
+
+       switch (blr_clk_ratio) {
+       case 32:
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_DAI_CLK_MODE2,
+                       MAX98926_DAI_BSEL_MASK,
+                       MAX98926_DAI_BSEL_32);
+               break;
+       case 48:
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_DAI_CLK_MODE2,
+                       MAX98926_DAI_BSEL_MASK,
+                       MAX98926_DAI_BSEL_48);
+               break;
+       case 64:
+               regmap_update_bits(max98926->regmap,
+                       MAX98926_DAI_CLK_MODE2,
+                       MAX98926_DAI_BSEL_MASK,
+                       MAX98926_DAI_BSEL_64);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* find the closest rate */
+       for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+               if (rate_table[i].rate >= rate) {
+                       dai_sr = rate_table[i].sr;
+                       break;
+               }
+       }
+       if (dai_sr < 0)
+               return -EINVAL;
+
+       /* set DAI_SR to correct LRCLK frequency */
+       regmap_update_bits(max98926->regmap,
+               MAX98926_DAI_CLK_MODE2,
+               MAX98926_DAI_SR_MASK, dai_sr << MAX98926_DAI_SR_SHIFT);
+       return 0;
+}
+
+#define MAX98926_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+               SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops max98926_dai_ops = {
+       .set_fmt = max98926_dai_set_fmt,
+       .hw_params = max98926_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver max98926_dai[] = {
+{
+       .name = "max98926-aif1",
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = MAX98926_FORMATS,
+       },
+       .capture = {
+               .stream_name = "HiFi Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = MAX98926_FORMATS,
+       },
+       .ops = &max98926_dai_ops,
+}
+};
+
+static int max98926_probe(struct snd_soc_codec *codec)
+{
+       struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec);
+
+       max98926->codec = codec;
+       codec->control_data = max98926->regmap;
+       /* Hi-Z all the slots */
+       regmap_write(max98926->regmap, MAX98926_DOUT_HIZ_CFG4, 0xF0);
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98926 = {
+       .probe  = max98926_probe,
+       .controls = max98926_snd_controls,
+       .num_controls = ARRAY_SIZE(max98926_snd_controls),
+       .dapm_routes = max98926_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(max98926_audio_map),
+       .dapm_widgets = max98926_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets),
+};
+
+static const struct regmap_config max98926_regmap = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .max_register   = MAX98926_VERSION,
+       .reg_defaults   = max98926_reg,
+       .num_reg_defaults = ARRAY_SIZE(max98926_reg),
+       .volatile_reg   = max98926_volatile_register,
+       .readable_reg   = max98926_readable_register,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int max98926_i2c_probe(struct i2c_client *i2c,
+               const struct i2c_device_id *id)
+{
+       int ret, reg;
+       u32 value;
+       struct max98926_priv *max98926;
+
+       max98926 = devm_kzalloc(&i2c->dev,
+                       sizeof(*max98926), GFP_KERNEL);
+       if (!max98926)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, max98926);
+       max98926->regmap = devm_regmap_init_i2c(i2c, &max98926_regmap);
+       if (IS_ERR(max98926->regmap)) {
+               ret = PTR_ERR(max98926->regmap);
+               dev_err(&i2c->dev,
+                               "Failed to allocate regmap: %d\n", ret);
+               goto err_out;
+       }
+       if (of_property_read_bool(i2c->dev.of_node, "interleave-mode"))
+               max98926->interleave_mode = true;
+
+       if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
+               if (value > MAX98926_DAI_VMON_SLOT_1E_1F) {
+                       dev_err(&i2c->dev, "vmon slot number is wrong:\n");
+                       return -EINVAL;
+               }
+               max98926->v_slot = value;
+       }
+       if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) {
+               if (value > MAX98926_DAI_IMON_SLOT_1E_1F) {
+                       dev_err(&i2c->dev, "imon slot number is wrong:\n");
+                       return -EINVAL;
+               }
+               max98926->i_slot = value;
+       }
+       ret = regmap_read(max98926->regmap,
+                       MAX98926_VERSION, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read: %x\n", reg);
+               return ret;
+       }
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98926,
+                       max98926_dai, ARRAY_SIZE(max98926_dai));
+       if (ret < 0)
+               dev_err(&i2c->dev,
+                               "Failed to register codec: %d\n", ret);
+       dev_info(&i2c->dev, "device version: %x\n", reg);
+err_out:
+       return ret;
+}
+
+static int max98926_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       return 0;
+}
+
+static const struct i2c_device_id max98926_i2c_id[] = {
+       { "max98926", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max98926_i2c_id);
+
+static const struct of_device_id max98926_of_match[] = {
+       { .compatible = "maxim,max98926", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, max98926_of_match);
+
+static struct i2c_driver max98926_i2c_driver = {
+       .driver = {
+               .name = "max98926",
+               .of_match_table = of_match_ptr(max98926_of_match),
+               .pm = NULL,
+       },
+       .probe  = max98926_i2c_probe,
+       .remove = max98926_i2c_remove,
+       .id_table = max98926_i2c_id,
+};
+
+module_i2c_driver(max98926_i2c_driver)
+MODULE_DESCRIPTION("ALSA SoC MAX98926 driver");
+MODULE_AUTHOR("Anish kumar <anish.kumar@maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98926.h b/sound/soc/codecs/max98926.h
new file mode 100644 (file)
index 0000000..9d7ab6d
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ * max98926.h -- MAX98926 ALSA SoC Audio driver
+ * Copyright 2013-2015 Maxim Integrated Products
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX98926_H
+#define _MAX98926_H
+
+#define MAX98926_CHIP_VERSION   0x40
+#define MAX98926_CHIP_VERSION1  0x50
+
+#define MAX98926_VBAT_DATA          0x00
+#define MAX98926_VBST_DATA          0x01
+#define MAX98926_LIVE_STATUS0       0x02
+#define MAX98926_LIVE_STATUS1       0x03
+#define MAX98926_LIVE_STATUS2       0x04
+#define MAX98926_STATE0         0x05
+#define MAX98926_STATE1         0x06
+#define MAX98926_STATE2         0x07
+#define MAX98926_FLAG0          0x08
+#define MAX98926_FLAG1          0x09
+#define MAX98926_FLAG2          0x0A
+#define MAX98926_IRQ_ENABLE0        0x0B
+#define MAX98926_IRQ_ENABLE1        0x0C
+#define MAX98926_IRQ_ENABLE2        0x0D
+#define MAX98926_IRQ_CLEAR0     0x0E
+#define MAX98926_IRQ_CLEAR1     0x0F
+#define MAX98926_IRQ_CLEAR2     0x10
+#define MAX98926_MAP0           0x11
+#define MAX98926_MAP1           0x12
+#define MAX98926_MAP2           0x13
+#define MAX98926_MAP3           0x14
+#define MAX98926_MAP4           0x15
+#define MAX98926_MAP5           0x16
+#define MAX98926_MAP6           0x17
+#define MAX98926_MAP7           0x18
+#define MAX98926_MAP8           0x19
+#define MAX98926_DAI_CLK_MODE1      0x1A
+#define MAX98926_DAI_CLK_MODE2      0x1B
+#define MAX98926_DAI_CLK_DIV_M_MSBS 0x1C
+#define MAX98926_DAI_CLK_DIV_M_LSBS 0x1D
+#define MAX98926_DAI_CLK_DIV_N_MSBS 0x1E
+#define MAX98926_DAI_CLK_DIV_N_LSBS 0x1F
+#define MAX98926_FORMAT         0x20
+#define MAX98926_TDM_SLOT_SELECT        0x21
+#define MAX98926_DOUT_CFG_VMON      0x22
+#define MAX98926_DOUT_CFG_IMON      0x23
+#define MAX98926_DOUT_CFG_VBAT      0x24
+#define MAX98926_DOUT_CFG_VBST      0x25
+#define MAX98926_DOUT_CFG_FLAG      0x26
+#define MAX98926_DOUT_HIZ_CFG1      0x27
+#define MAX98926_DOUT_HIZ_CFG2      0x28
+#define MAX98926_DOUT_HIZ_CFG3      0x29
+#define MAX98926_DOUT_HIZ_CFG4      0x2A
+#define MAX98926_DOUT_DRV_STRENGTH      0x2B
+#define MAX98926_FILTERS            0x2C
+#define MAX98926_GAIN           0x2D
+#define MAX98926_GAIN_RAMPING       0x2E
+#define MAX98926_SPK_AMP            0x2F
+#define MAX98926_THRESHOLD          0x30
+#define MAX98926_ALC_ATTACK     0x31
+#define MAX98926_ALC_ATTEN_RLS      0x32
+#define MAX98926_ALC_HOLD_RLS       0x33
+#define MAX98926_ALC_CONFIGURATION      0x34
+#define MAX98926_BOOST_CONVERTER        0x35
+#define MAX98926_BLOCK_ENABLE       0x36
+#define MAX98926_CONFIGURATION      0x37
+#define MAX98926_GLOBAL_ENABLE      0x38
+#define MAX98926_BOOST_LIMITER      0x3A
+#define MAX98926_VERSION            0xFF
+
+#define MAX98926_REG_CNT               (MAX98926_R03A_BOOST_LIMITER+1)
+
+#define MAX98926_PDM_CURRENT_MASK (1<<7)
+#define MAX98926_PDM_CURRENT_SHIFT 7
+#define MAX98926_PDM_VOLTAGE_MASK (1<<3)
+#define MAX98926_PDM_VOLTAGE_SHIFT 3
+#define MAX98926_PDM_CHANNEL_0_MASK (1<<2)
+#define MAX98926_PDM_CHANNEL_0_SHIFT 2
+#define MAX98926_PDM_CHANNEL_1_MASK (1<<6)
+#define MAX98926_PDM_CHANNEL_1_SHIFT 6
+#define MAX98926_PDM_CHANNEL_1_HIZ 5
+#define MAX98926_PDM_CHANNEL_0_HIZ 1
+#define MAX98926_PDM_SOURCE_0_SHIFT 0
+#define MAX98926_PDM_SOURCE_0_MASK (1<<0)
+#define MAX98926_PDM_SOURCE_1_MASK (1<<4)
+#define MAX98926_PDM_SOURCE_1_SHIFT 4
+
+/* MAX98926 Register Bit Fields */
+
+/* MAX98926_R002_LIVE_STATUS0 */
+#define MAX98926_THERMWARN_STATUS_MASK          (1<<3)
+#define MAX98926_THERMWARN_STATUS_SHIFT         3
+#define MAX98926_THERMWARN_STATUS_WIDTH         1
+#define MAX98926_THERMSHDN_STATUS_MASK          (1<<1)
+#define MAX98926_THERMSHDN_STATUS_SHIFT         1
+#define MAX98926_THERMSHDN_STATUS_WIDTH         1
+
+/* MAX98926_R003_LIVE_STATUS1 */
+#define MAX98926_SPKCURNT_STATUS_MASK               (1<<5)
+#define MAX98926_SPKCURNT_STATUS_SHIFT          5
+#define MAX98926_SPKCURNT_STATUS_WIDTH          1
+#define MAX98926_WATCHFAIL_STATUS_MASK          (1<<4)
+#define MAX98926_WATCHFAIL_STATUS_SHIFT         4
+#define MAX98926_WATCHFAIL_STATUS_WIDTH         1
+#define MAX98926_ALCINFH_STATUS_MASK                (1<<3)
+#define MAX98926_ALCINFH_STATUS_SHIFT               3
+#define MAX98926_ALCINFH_STATUS_WIDTH               1
+#define MAX98926_ALCACT_STATUS_MASK             (1<<2)
+#define MAX98926_ALCACT_STATUS_SHIFT                2
+#define MAX98926_ALCACT_STATUS_WIDTH                1
+#define MAX98926_ALCMUT_STATUS_MASK             (1<<1)
+#define MAX98926_ALCMUT_STATUS_SHIFT                1
+#define MAX98926_ALCMUT_STATUS_WIDTH                1
+#define MAX98926_ACLP_STATUS_MASK                   (1<<0)
+#define MAX98926_ACLP_STATUS_SHIFT              0
+#define MAX98926_ACLP_STATUS_WIDTH              1
+
+/* MAX98926_R004_LIVE_STATUS2 */
+#define MAX98926_SLOTOVRN_STATUS_MASK               (1<<6)
+#define MAX98926_SLOTOVRN_STATUS_SHIFT          6
+#define MAX98926_SLOTOVRN_STATUS_WIDTH          1
+#define MAX98926_INVALSLOT_STATUS_MASK          (1<<5)
+#define MAX98926_INVALSLOT_STATUS_SHIFT         5
+#define MAX98926_INVALSLOT_STATUS_WIDTH         1
+#define MAX98926_SLOTCNFLT_STATUS_MASK          (1<<4)
+#define MAX98926_SLOTCNFLT_STATUS_SHIFT         4
+#define MAX98926_SLOTCNFLT_STATUS_WIDTH         1
+#define MAX98926_VBSTOVFL_STATUS_MASK               (1<<3)
+#define MAX98926_VBSTOVFL_STATUS_SHIFT          3
+#define MAX98926_VBSTOVFL_STATUS_WIDTH          1
+#define MAX98926_VBATOVFL_STATUS_MASK               (1<<2)
+#define MAX98926_VBATOVFL_STATUS_SHIFT          2
+#define MAX98926_VBATOVFL_STATUS_WIDTH          1
+#define MAX98926_IMONOVFL_STATUS_MASK               (1<<1)
+#define MAX98926_IMONOVFL_STATUS_SHIFT          1
+#define MAX98926_IMONOVFL_STATUS_WIDTH          1
+#define MAX98926_VMONOVFL_STATUS_MASK               (1<<0)
+#define MAX98926_VMONOVFL_STATUS_SHIFT          0
+#define MAX98926_VMONOVFL_STATUS_WIDTH          1
+
+/* MAX98926_R005_STATE0 */
+#define MAX98926_THERMWARN_END_STATE_MASK           (1<<3)
+#define MAX98926_THERMWARN_END_STATE_SHIFT      3
+#define MAX98926_THERMWARN_END_STATE_WIDTH      1
+#define MAX98926_THERMWARN_BGN_STATE_MASK           (1<<2)
+#define MAX98926_THERMWARN_BGN_STATE_SHIFT      1
+#define MAX98926_THERMWARN_BGN_STATE_WIDTH      1
+#define MAX98926_THERMSHDN_END_STATE_MASK           (1<<1)
+#define MAX98926_THERMSHDN_END_STATE_SHIFT      1
+#define MAX98926_THERMSHDN_END_STATE_WIDTH      1
+#define MAX98926_THERMSHDN_BGN_STATE_MASK           (1<<0)
+#define MAX98926_THERMSHDN_BGN_STATE_SHIFT      0
+#define MAX98926_THERMSHDN_BGN_STATE_WIDTH      1
+
+/* MAX98926_R006_STATE1 */
+#define MAX98926_SPRCURNT_STATE_MASK                (1<<5)
+#define MAX98926_SPRCURNT_STATE_SHIFT               5
+#define MAX98926_SPRCURNT_STATE_WIDTH               1
+#define MAX98926_WATCHFAIL_STATE_MASK               (1<<4)
+#define MAX98926_WATCHFAIL_STATE_SHIFT          4
+#define MAX98926_WATCHFAIL_STATE_WIDTH          1
+#define MAX98926_ALCINFH_STATE_MASK             (1<<3)
+#define MAX98926_ALCINFH_STATE_SHIFT                3
+#define MAX98926_ALCINFH_STATE_WIDTH                1
+#define MAX98926_ALCACT_STATE_MASK              (1<<2)
+#define MAX98926_ALCACT_STATE_SHIFT             2
+#define MAX98926_ALCACT_STATE_WIDTH             1
+#define MAX98926_ALCMUT_STATE_MASK              (1<<1)
+#define MAX98926_ALCMUT_STATE_SHIFT             1
+#define MAX98926_ALCMUT_STATE_WIDTH             1
+#define MAX98926_ALCP_STATE_MASK                    (1<<0)
+#define MAX98926_ALCP_STATE_SHIFT                   0
+#define MAX98926_ALCP_STATE_WIDTH                   1
+
+/* MAX98926_R007_STATE2 */
+#define MAX98926_SLOTOVRN_STATE_MASK                (1<<6)
+#define MAX98926_SLOTOVRN_STATE_SHIFT               6
+#define MAX98926_SLOTOVRN_STATE_WIDTH               1
+#define MAX98926_INVALSLOT_STATE_MASK               (1<<5)
+#define MAX98926_INVALSLOT_STATE_SHIFT          5
+#define MAX98926_INVALSLOT_STATE_WIDTH          1
+#define MAX98926_SLOTCNFLT_STATE_MASK               (1<<4)
+#define MAX98926_SLOTCNFLT_STATE_SHIFT          4
+#define MAX98926_SLOTCNFLT_STATE_WIDTH          1
+#define MAX98926_VBSTOVFL_STATE_MASK                (1<<3)
+#define MAX98926_VBSTOVFL_STATE_SHIFT               3
+#define MAX98926_VBSTOVFL_STATE_WIDTH               1
+#define MAX98926_VBATOVFL_STATE_MASK                (1<<2)
+#define MAX98926_VBATOVFL_STATE_SHIFT               2
+#define MAX98926_VBATOVFL_STATE_WIDTH               1
+#define MAX98926_IMONOVFL_STATE_MASK                (1<<1)
+#define MAX98926_IMONOVFL_STATE_SHIFT               1
+#define MAX98926_IMONOVFL_STATE_WIDTH               1
+#define MAX98926_VMONOVFL_STATE_MASK                (1<<0)
+#define MAX98926_VMONOVFL_STATE_SHIFT               0
+#define MAX98926_VMONOVFL_STATE_WIDTH               1
+
+/* MAX98926_R008_FLAG0 */
+#define MAX98926_THERMWARN_END_FLAG_MASK            (1<<3)
+#define MAX98926_THERMWARN_END_FLAG_SHIFT           3
+#define MAX98926_THERMWARN_END_FLAG_WIDTH           1
+#define MAX98926_THERMWARN_BGN_FLAG_MASK            (1<<2)
+#define MAX98926_THERMWARN_BGN_FLAG_SHIFT           2
+#define MAX98926_THERMWARN_BGN_FLAG_WIDTH           1
+#define MAX98926_THERMSHDN_END_FLAG_MASK            (1<<1)
+#define MAX98926_THERMSHDN_END_FLAG_SHIFT           1
+#define MAX98926_THERMSHDN_END_FLAG_WIDTH           1
+#define MAX98926_THERMSHDN_BGN_FLAG_MASK            (1<<0)
+#define MAX98926_THERMSHDN_BGN_FLAG_SHIFT           0
+#define MAX98926_THERMSHDN_BGN_FLAG_WIDTH           1
+
+/* MAX98926_R009_FLAG1 */
+#define MAX98926_SPKCURNT_FLAG_MASK             (1<<5)
+#define MAX98926_SPKCURNT_FLAG_SHIFT                5
+#define MAX98926_SPKCURNT_FLAG_WIDTH                1
+#define MAX98926_WATCHFAIL_FLAG_MASK                (1<<4)
+#define MAX98926_WATCHFAIL_FLAG_SHIFT               4
+#define MAX98926_WATCHFAIL_FLAG_WIDTH               1
+#define MAX98926_ALCINFH_FLAG_MASK              (1<<3)
+#define MAX98926_ALCINFH_FLAG_SHIFT             3
+#define MAX98926_ALCINFH_FLAG_WIDTH             1
+#define MAX98926_ALCACT_FLAG_MASK                   (1<<2)
+#define MAX98926_ALCACT_FLAG_SHIFT              2
+#define MAX98926_ALCACT_FLAG_WIDTH              1
+#define MAX98926_ALCMUT_FLAG_MASK                   (1<<1)
+#define MAX98926_ALCMUT_FLAG_SHIFT              1
+#define MAX98926_ALCMUT_FLAG_WIDTH              1
+#define MAX98926_ALCP_FLAG_MASK                 (1<<0)
+#define MAX98926_ALCP_FLAG_SHIFT                    0
+#define MAX98926_ALCP_FLAG_WIDTH                    1
+
+/* MAX98926_R00A_FLAG2 */
+#define MAX98926_SLOTOVRN_FLAG_MASK             (1<<6)
+#define MAX98926_SLOTOVRN_FLAG_SHIFT                6
+#define MAX98926_SLOTOVRN_FLAG_WIDTH                1
+#define MAX98926_INVALSLOT_FLAG_MASK                (1<<5)
+#define MAX98926_INVALSLOT_FLAG_SHIFT               5
+#define MAX98926_INVALSLOT_FLAG_WIDTH               1
+#define MAX98926_SLOTCNFLT_FLAG_MASK                (1<<4)
+#define MAX98926_SLOTCNFLT_FLAG_SHIFT               4
+#define MAX98926_SLOTCNFLT_FLAG_WIDTH               1
+#define MAX98926_VBSTOVFL_FLAG_MASK             (1<<3)
+#define MAX98926_VBSTOVFL_FLAG_SHIFT                3
+#define MAX98926_VBSTOVFL_FLAG_WIDTH                1
+#define MAX98926_VBATOVFL_FLAG_MASK             (1<<2)
+#define MAX98926_VBATOVFL_FLAG_SHIFT                2
+#define MAX98926_VBATOVFL_FLAG_WIDTH                1
+#define MAX98926_IMONOVFL_FLAG_MASK             (1<<1)
+#define MAX98926_IMONOVFL_FLAG_SHIFT                1
+#define MAX98926_IMONOVFL_FLAG_WIDTH                1
+#define MAX98926_VMONOVFL_FLAG_MASK             (1<<0)
+#define MAX98926_VMONOVFL_FLAG_SHIFT                0
+#define MAX98926_VMONOVFL_FLAG_WIDTH                1
+
+/* MAX98926_R00B_IRQ_ENABLE0 */
+#define MAX98926_THERMWARN_END_EN_MASK          (1<<3)
+#define MAX98926_THERMWARN_END_EN_SHIFT         3
+#define MAX98926_THERMWARN_END_EN_WIDTH         1
+#define MAX98926_THERMWARN_BGN_EN_MASK          (1<<2)
+#define MAX98926_THERMWARN_BGN_EN_SHIFT         2
+#define MAX98926_THERMWARN_BGN_EN_WIDTH         1
+#define MAX98926_THERMSHDN_END_EN_MASK          (1<<1)
+#define MAX98926_THERMSHDN_END_EN_SHIFT         1
+#define MAX98926_THERMSHDN_END_EN_WIDTH         1
+#define MAX98926_THERMSHDN_BGN_EN_MASK          (1<<0)
+#define MAX98926_THERMSHDN_BGN_EN_SHIFT         0
+#define MAX98926_THERMSHDN_BGN_EN_WIDTH         1
+
+/* MAX98926_R00C_IRQ_ENABLE1 */
+#define MAX98926_SPKCURNT_EN_MASK       (1<<5)
+#define MAX98926_SPKCURNT_EN_SHIFT  5
+#define MAX98926_SPKCURNT_EN_WIDTH  1
+#define MAX98926_WATCHFAIL_EN_MASK  (1<<4)
+#define MAX98926_WATCHFAIL_EN_SHIFT 4
+#define MAX98926_WATCHFAIL_EN_WIDTH 1
+#define MAX98926_ALCINFH_EN_MASK        (1<<3)
+#define MAX98926_ALCINFH_EN_SHIFT       3
+#define MAX98926_ALCINFH_EN_WIDTH       1
+#define MAX98926_ALCACT_EN_MASK     (1<<2)
+#define MAX98926_ALCACT_EN_SHIFT        2
+#define MAX98926_ALCACT_EN_WIDTH        1
+#define MAX98926_ALCMUT_EN_MASK     (1<<1)
+#define MAX98926_ALCMUT_EN_SHIFT        1
+#define MAX98926_ALCMUT_EN_WIDTH        1
+#define MAX98926_ALCP_EN_MASK           (1<<0)
+#define MAX98926_ALCP_EN_SHIFT      0
+#define MAX98926_ALCP_EN_WIDTH      1
+
+/* MAX98926_R00D_IRQ_ENABLE2 */
+#define MAX98926_SLOTOVRN_EN_MASK       (1<<6)
+#define MAX98926_SLOTOVRN_EN_SHIFT  6
+#define MAX98926_SLOTOVRN_EN_WIDTH  1
+#define MAX98926_INVALSLOT_EN_MASK  (1<<5)
+#define MAX98926_INVALSLOT_EN_SHIFT 5
+#define MAX98926_INVALSLOT_EN_WIDTH 1
+#define MAX98926_SLOTCNFLT_EN_MASK  (1<<4)
+#define MAX98926_SLOTCNFLT_EN_SHIFT 4
+#define MAX98926_SLOTCNFLT_EN_WIDTH 1
+#define MAX98926_VBSTOVFL_EN_MASK       (1<<3)
+#define MAX98926_VBSTOVFL_EN_SHIFT  3
+#define MAX98926_VBSTOVFL_EN_WIDTH  1
+#define MAX98926_VBATOVFL_EN_MASK       (1<<2)
+#define MAX98926_VBATOVFL_EN_SHIFT  2
+#define MAX98926_VBATOVFL_EN_WIDTH  1
+#define MAX98926_IMONOVFL_EN_MASK       (1<<1)
+#define MAX98926_IMONOVFL_EN_SHIFT  1
+#define MAX98926_IMONOVFL_EN_WIDTH  1
+#define MAX98926_VMONOVFL_EN_MASK       (1<<0)
+#define MAX98926_VMONOVFL_EN_SHIFT  0
+#define MAX98926_VMONOVFL_EN_WIDTH  1
+
+/* MAX98926_R00E_IRQ_CLEAR0 */
+#define MAX98926_THERMWARN_END_CLR_MASK         (1<<3)
+#define MAX98926_THERMWARN_END_CLR_SHIFT            3
+#define MAX98926_THERMWARN_END_CLR_WIDTH            1
+#define MAX98926_THERMWARN_BGN_CLR_MASK         (1<<2)
+#define MAX98926_THERMWARN_BGN_CLR_SHIFT            2
+#define MAX98926_THERMWARN_BGN_CLR_WIDTH            1
+#define MAX98926_THERMSHDN_END_CLR_MASK         (1<<1)
+#define MAX98926_THERMSHDN_END_CLR_SHIFT            1
+#define MAX98926_THERMSHDN_END_CLR_WIDTH            1
+#define MAX98926_THERMSHDN_BGN_CLR_MASK         (1<<0)
+#define MAX98926_THERMSHDN_BGN_CLR_SHIFT            0
+#define MAX98926_THERMSHDN_BGN_CLR_WIDTH            1
+
+/* MAX98926_R00F_IRQ_CLEAR1 */
+#define MAX98926_SPKCURNT_CLR_MASK      (1<<5)
+#define MAX98926_SPKCURNT_CLR_SHIFT     5
+#define MAX98926_SPKCURNT_CLR_WIDTH     1
+#define MAX98926_WATCHFAIL_CLR_MASK     (1<<4)
+#define MAX98926_WATCHFAIL_CLR_SHIFT        4
+#define MAX98926_WATCHFAIL_CLR_WIDTH        1
+#define MAX98926_ALCINFH_CLR_MASK           (1<<3)
+#define MAX98926_ALCINFH_CLR_SHIFT      3
+#define MAX98926_ALCINFH_CLR_WIDTH      1
+#define MAX98926_ALCACT_CLR_MASK            (1<<2)
+#define MAX98926_ALCACT_CLR_SHIFT           2
+#define MAX98926_ALCACT_CLR_WIDTH           1
+#define MAX98926_ALCMUT_CLR_MASK            (1<<1)
+#define MAX98926_ALCMUT_CLR_SHIFT           1
+#define MAX98926_ALCMUT_CLR_WIDTH           1
+#define MAX98926_ALCP_CLR_MASK          (1<<0)
+#define MAX98926_ALCP_CLR_SHIFT         0
+#define MAX98926_ALCP_CLR_WIDTH         1
+
+/* MAX98926_R010_IRQ_CLEAR2 */
+#define MAX98926_SLOTOVRN_CLR_MASK      (1<<6)
+#define MAX98926_SLOTOVRN_CLR_SHIFT     6
+#define MAX98926_SLOTOVRN_CLR_WIDTH     1
+#define MAX98926_INVALSLOT_CLR_MASK     (1<<5)
+#define MAX98926_INVALSLOT_CLR_SHIFT        5
+#define MAX98926_INVALSLOT_CLR_WIDTH        1
+#define MAX98926_SLOTCNFLT_CLR_MASK     (1<<4)
+#define MAX98926_SLOTCNFLT_CLR_SHIFT        4
+#define MAX98926_SLOTCNFLT_CLR_WIDTH        1
+#define MAX98926_VBSTOVFL_CLR_MASK      (1<<3)
+#define MAX98926_VBSTOVFL_CLR_SHIFT     3
+#define MAX98926_VBSTOVFL_CLR_WIDTH     1
+#define MAX98926_VBATOVFL_CLR_MASK      (1<<2)
+#define MAX98926_VBATOVFL_CLR_SHIFT     2
+#define MAX98926_VBATOVFL_CLR_WIDTH     1
+#define MAX98926_IMONOVFL_CLR_MASK      (1<<1)
+#define MAX98926_IMONOVFL_CLR_SHIFT     1
+#define MAX98926_IMONOVFL_CLR_WIDTH     1
+#define MAX98926_VMONOVFL_CLR_MASK          (1<<0)
+#define MAX98926_VMONOVFL_CLR_SHIFT         0
+#define MAX98926_VMONOVFL_CLR_WIDTH         1
+
+/* MAX98926_R011_MAP0 */
+#define MAX98926_ER_THERMWARN_EN_MASK               (1<<7)
+#define MAX98926_ER_THERMWARN_EN_SHIFT          7
+#define MAX98926_ER_THERMWARN_EN_WIDTH          1
+#define MAX98926_ER_THERMWARN_MAP_MASK          (0x07<<4)
+#define MAX98926_ER_THERMWARN_MAP_SHIFT         4
+#define MAX98926_ER_THERMWARN_MAP_WIDTH         3
+
+/* MAX98926_R012_MAP1 */
+#define MAX98926_ER_ALCMUT_EN_MASK      (1<<7)
+#define MAX98926_ER_ALCMUT_EN_SHIFT     7
+#define MAX98926_ER_ALCMUT_EN_WIDTH     1
+#define MAX98926_ER_ALCMUT_MAP_MASK     (0x07<<4)
+#define MAX98926_ER_ALCMUT_MAP_SHIFT        4
+#define MAX98926_ER_ALCMUT_MAP_WIDTH        3
+#define MAX98926_ER_ALCP_EN_MASK            (1<<3)
+#define MAX98926_ER_ALCP_EN_SHIFT           3
+#define MAX98926_ER_ALCP_EN_WIDTH           1
+#define MAX98926_ER_ALCP_MAP_MASK           (0x07<<0)
+#define MAX98926_ER_ALCP_MAP_SHIFT      0
+#define MAX98926_ER_ALCP_MAP_WIDTH      3
+
+/* MAX98926_R013_MAP2 */
+#define MAX98926_ER_ALCINFH_EN_MASK     (1<<7)
+#define MAX98926_ER_ALCINFH_EN_SHIFT        7
+#define MAX98926_ER_ALCINFH_EN_WIDTH        1
+#define MAX98926_ER_ALCINFH_MAP_MASK        (0x07<<4)
+#define MAX98926_ER_ALCINFH_MAP_SHIFT       4
+#define MAX98926_ER_ALCINFH_MAP_WIDTH       3
+#define MAX98926_ER_ALCACT_EN_MASK      (1<<3)
+#define MAX98926_ER_ALCACT_EN_SHIFT     3
+#define MAX98926_ER_ALCACT_EN_WIDTH     1
+#define MAX98926_ER_ALCACT_MAP_MASK     (0x07<<0)
+#define MAX98926_ER_ALCACT_MAP_SHIFT        0
+#define MAX98926_ER_ALCACT_MAP_WIDTH        3
+
+/* MAX98926_R014_MAP3 */
+#define MAX98926_ER_SPKCURNT_EN_MASK            (1<<7)
+#define MAX98926_ER_SPKCURNT_EN_SHIFT           7
+#define MAX98926_ER_SPKCURNT_EN_WIDTH           1
+#define MAX98926_ER_SPKCURNT_MAP_MASK           (0x07<<4)
+#define MAX98926_ER_SPKCURNT_MAP_SHIFT          4
+#define MAX98926_ER_SPKCURNT_MAP_WIDTH          3
+
+/* MAX98926_R015_MAP4 */
+/* RESERVED */
+
+/* MAX98926_R016_MAP5 */
+#define MAX98926_ER_IMONOVFL_EN_MASK            (1<<7)
+#define MAX98926_ER_IMONOVFL_EN_SHIFT           7
+#define MAX98926_ER_IMONOVFL_EN_WIDTH           1
+#define MAX98926_ER_IMONOVFL_MAP_MASK           (0x07<<4)
+#define MAX98926_ER_IMONOVFL_MAP_SHIFT          4
+#define MAX98926_ER_IMONOVFL_MAP_WIDTH          3
+#define MAX98926_ER_VMONOVFL_EN_MASK            (1<<3)
+#define MAX98926_ER_VMONOVFL_EN_SHIFT           3
+#define MAX98926_ER_VMONOVFL_EN_WIDTH           1
+#define MAX98926_ER_VMONOVFL_MAP_MASK           (0x07<<0)
+#define MAX98926_ER_VMONOVFL_MAP_SHIFT          0
+#define MAX98926_ER_VMONOVFL_MAP_WIDTH          3
+
+/* MAX98926_R017_MAP6 */
+#define MAX98926_ER_VBSTOVFL_EN_MASK            (1<<7)
+#define MAX98926_ER_VBSTOVFL_EN_SHIFT           7
+#define MAX98926_ER_VBSTOVFL_EN_WIDTH           1
+#define MAX98926_ER_VBSTOVFL_MAP_MASK           (0x07<<4)
+#define MAX98926_ER_VBSTOVFL_MAP_SHIFT          4
+#define MAX98926_ER_VBSTOVFL_MAP_WIDTH          3
+#define MAX98926_ER_VBATOVFL_EN_MASK            (1<<3)
+#define MAX98926_ER_VBATOVFL_EN_SHIFT           3
+#define MAX98926_ER_VBATOVFL_EN_WIDTH           1
+#define MAX98926_ER_VBATOVFL_MAP_MASK           (0x07<<0)
+#define MAX98926_ER_VBATOVFL_MAP_SHIFT          0
+#define MAX98926_ER_VBATOVFL_MAP_WIDTH          3
+
+/* MAX98926_R018_MAP7 */
+#define MAX98926_ER_INVALSLOT_EN_MASK               (1<<7)
+#define MAX98926_ER_INVALSLOT_EN_SHIFT          7
+#define MAX98926_ER_INVALSLOT_EN_WIDTH          1
+#define MAX98926_ER_INVALSLOT_MAP_MASK          (0x07<<4)
+#define MAX98926_ER_INVALSLOT_MAP_SHIFT         4
+#define MAX98926_ER_INVALSLOT_MAP_WIDTH         3
+#define MAX98926_ER_SLOTCNFLT_EN_MASK               (1<<3)
+#define MAX98926_ER_SLOTCNFLT_EN_SHIFT          3
+#define MAX98926_ER_SLOTCNFLT_EN_WIDTH          1
+#define MAX98926_ER_SLOTCNFLT_MAP_MASK          (0x07<<0)
+#define MAX98926_ER_SLOTCNFLT_MAP_SHIFT         0
+#define MAX98926_ER_SLOTCNFLT_MAP_WIDTH         3
+
+/* MAX98926_R019_MAP8 */
+#define MAX98926_ER_SLOTOVRN_EN_MASK    (1<<3)
+#define MAX98926_ER_SLOTOVRN_EN_SHIFT   3
+#define MAX98926_ER_SLOTOVRN_EN_WIDTH   1
+#define MAX98926_ER_SLOTOVRN_MAP_MASK   (0x07<<0)
+#define MAX98926_ER_SLOTOVRN_MAP_SHIFT  0
+#define MAX98926_ER_SLOTOVRN_MAP_WIDTH  3
+
+/* MAX98926_R01A_DAI_CLK_MODE1 */
+#define MAX98926_DAI_CLK_SOURCE_MASK    (1<<6)
+#define MAX98926_DAI_CLK_SOURCE_SHIFT   6
+#define MAX98926_DAI_CLK_SOURCE_WIDTH   1
+#define MAX98926_MDLL_MULT_MASK     (0x0F<<0)
+#define MAX98926_MDLL_MULT_SHIFT        0
+#define MAX98926_MDLL_MULT_WIDTH        4
+
+#define MAX98926_MDLL_MULT_MCLKx8       6
+#define MAX98926_MDLL_MULT_MCLKx16  8
+
+/* MAX98926_R01B_DAI_CLK_MODE2 */
+#define MAX98926_DAI_SR_MASK            (0x0F<<4)
+#define MAX98926_DAI_SR_SHIFT           4
+#define MAX98926_DAI_SR_WIDTH           4
+#define MAX98926_DAI_MAS_MASK           (1<<3)
+#define MAX98926_DAI_MAS_SHIFT          3
+#define MAX98926_DAI_MAS_WIDTH          1
+#define MAX98926_DAI_BSEL_MASK          (0x07<<0)
+#define MAX98926_DAI_BSEL_SHIFT         0
+#define MAX98926_DAI_BSEL_WIDTH         3
+
+#define MAX98926_DAI_BSEL_32 (0 << MAX98926_DAI_BSEL_SHIFT)
+#define MAX98926_DAI_BSEL_48 (1 << MAX98926_DAI_BSEL_SHIFT)
+#define MAX98926_DAI_BSEL_64 (2 << MAX98926_DAI_BSEL_SHIFT)
+#define MAX98926_DAI_BSEL_256 (6 << MAX98926_DAI_BSEL_SHIFT)
+
+/* MAX98926_R01C_DAI_CLK_DIV_M_MSBS */
+#define MAX98926_DAI_M_MSBS_MASK        (0xFF<<0)
+#define MAX98926_DAI_M_MSBS_SHIFT       0
+#define MAX98926_DAI_M_MSBS_WIDTH       8
+
+/* MAX98926_R01D_DAI_CLK_DIV_M_LSBS */
+#define MAX98926_DAI_M_LSBS_MASK        (0xFF<<0)
+#define MAX98926_DAI_M_LSBS_SHIFT       0
+#define MAX98926_DAI_M_LSBS_WIDTH       8
+
+/* MAX98926_R01E_DAI_CLK_DIV_N_MSBS */
+#define MAX98926_DAI_N_MSBS_MASK        (0x7F<<0)
+#define MAX98926_DAI_N_MSBS_SHIFT       0
+#define MAX98926_DAI_N_MSBS_WIDTH       7
+
+/* MAX98926_R01F_DAI_CLK_DIV_N_LSBS */
+#define MAX98926_DAI_N_LSBS_MASK        (0xFF<<0)
+#define MAX98926_DAI_N_LSBS_SHIFT       0
+#define MAX98926_DAI_N_LSBS_WIDTH       8
+
+/* MAX98926_R020_FORMAT */
+#define MAX98926_DAI_CHANSZ_MASK    (0x03<<6)
+#define MAX98926_DAI_CHANSZ_SHIFT   6
+#define MAX98926_DAI_CHANSZ_WIDTH   2
+#define MAX98926_DAI_INTERLEAVE_MASK        (1<<5)
+#define MAX98926_DAI_INTERLEAVE_SHIFT       5
+#define MAX98926_DAI_INTERLEAVE_WIDTH       1
+#define MAX98926_DAI_EXTBCLK_HIZ_MASK       (1<<4)
+#define MAX98926_DAI_EXTBCLK_HIZ_SHIFT      4
+#define MAX98926_DAI_EXTBCLK_HIZ_WIDTH      1
+#define MAX98926_DAI_WCI_MASK           (1<<3)
+#define MAX98926_DAI_WCI_SHIFT      3
+#define MAX98926_DAI_WCI_WIDTH      1
+#define MAX98926_DAI_BCI_MASK           (1<<2)
+#define MAX98926_DAI_BCI_SHIFT      2
+#define MAX98926_DAI_BCI_WIDTH      1
+#define MAX98926_DAI_DLY_MASK           (1<<1)
+#define MAX98926_DAI_DLY_SHIFT      1
+#define MAX98926_DAI_DLY_WIDTH      1
+#define MAX98926_DAI_TDM_MASK           (1<<0)
+#define MAX98926_DAI_TDM_SHIFT      0
+#define MAX98926_DAI_TDM_WIDTH      1
+
+#define MAX98926_DAI_CHANSZ_16 (1 << MAX98926_DAI_CHANSZ_SHIFT)
+#define MAX98926_DAI_CHANSZ_24 (2 << MAX98926_DAI_CHANSZ_SHIFT)
+#define MAX98926_DAI_CHANSZ_32 (3 << MAX98926_DAI_CHANSZ_SHIFT)
+
+/* MAX98926_R021_TDM_SLOT_SELECT */
+#define MAX98926_DAI_DO_EN_MASK     (1<<7)
+#define MAX98926_DAI_DO_EN_SHIFT        7
+#define MAX98926_DAI_DO_EN_WIDTH        1
+#define MAX98926_DAI_DIN_EN_MASK        (1<<6)
+#define MAX98926_DAI_DIN_EN_SHIFT       6
+#define MAX98926_DAI_DIN_EN_WIDTH       1
+#define MAX98926_DAI_INR_SOURCE_MASK    (0x07<<3)
+#define MAX98926_DAI_INR_SOURCE_SHIFT   3
+#define MAX98926_DAI_INR_SOURCE_WIDTH   3
+#define MAX98926_DAI_INL_SOURCE_MASK    (0x07<<0)
+#define MAX98926_DAI_INL_SOURCE_SHIFT   0
+#define MAX98926_DAI_INL_SOURCE_WIDTH   3
+
+/* MAX98926_R022_DOUT_CFG_VMON */
+#define MAX98926_DAI_VMON_EN_MASK       (1<<5)
+#define MAX98926_DAI_VMON_EN_SHIFT  5
+#define MAX98926_DAI_VMON_EN_WIDTH  1
+#define MAX98926_DAI_VMON_SLOT_MASK (0x1F<<0)
+#define MAX98926_DAI_VMON_SLOT_SHIFT    0
+#define MAX98926_DAI_VMON_SLOT_WIDTH    5
+
+#define MAX98926_DAI_VMON_SLOT_00_01 (0 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_01_02 (1 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_02_03 (2 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_03_04 (3 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_04_05 (4 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_05_06 (5 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_06_07 (6 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_07_08 (7 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_08_09 (8 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_09_0A (9 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_0A_0B (10 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_0B_0C (11 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_0C_0D (12 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_0D_0E (13 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_0E_0F (14 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_0F_10 (15 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_10_11 (16 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_11_12 (17 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_12_13 (18 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_13_14 (19 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_14_15 (20 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_15_16 (21 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_16_17 (22 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_17_18 (23 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_18_19 (24 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_19_1A (25 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_1A_1B (26 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_1B_1C (27 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_1C_1D (28 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_1D_1E (29 << MAX98926_DAI_VMON_SLOT_SHIFT)
+#define MAX98926_DAI_VMON_SLOT_1E_1F (30 << MAX98926_DAI_VMON_SLOT_SHIFT)
+
+/* MAX98926_R023_DOUT_CFG_IMON */
+#define MAX98926_DAI_IMON_EN_MASK       (1<<5)
+#define MAX98926_DAI_IMON_EN_SHIFT  5
+#define MAX98926_DAI_IMON_EN_WIDTH  1
+#define MAX98926_DAI_IMON_SLOT_MASK (0x1F<<0)
+#define MAX98926_DAI_IMON_SLOT_SHIFT    0
+#define MAX98926_DAI_IMON_SLOT_WIDTH    5
+
+#define MAX98926_DAI_IMON_SLOT_00_01 (0 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_01_02 (1 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_02_03 (2 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_03_04 (3 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_04_05 (4 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_05_06 (5 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_06_07 (6 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_07_08 (7 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_08_09 (8 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_09_0A (9 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_0A_0B (10 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_0B_0C (11 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_0C_0D (12 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_0D_0E (13 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_0E_0F (14 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_0F_10 (15 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_10_11 (16 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_11_12 (17 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_12_13 (18 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_13_14 (19 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_14_15 (20 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_15_16 (21 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_16_17 (22 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_17_18 (23 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_18_19 (24 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_19_1A (25 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_1A_1B (26 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_1B_1C (27 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_1C_1D (28 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_1D_1E (29 << MAX98926_DAI_IMON_SLOT_SHIFT)
+#define MAX98926_DAI_IMON_SLOT_1E_1F (30 << MAX98926_DAI_IMON_SLOT_SHIFT)
+
+/* MAX98926_R024_DOUT_CFG_VBAT */
+#define MAX98926_DAI_INTERLEAVE_SLOT_MASK       (0x1F<<0)
+#define MAX98926_DAI_INTERLEAVE_SLOT_SHIFT      0
+#define MAX98926_DAI_INTERLEAVE_SLOT_WIDTH      5
+
+/* MAX98926_R025_DOUT_CFG_VBST */
+#define MAX98926_DAI_VBST_EN_MASK               (1<<5)
+#define MAX98926_DAI_VBST_EN_SHIFT          5
+#define MAX98926_DAI_VBST_EN_WIDTH          1
+#define MAX98926_DAI_VBST_SLOT_MASK         (0x1F<<0)
+#define MAX98926_DAI_VBST_SLOT_SHIFT            0
+#define MAX98926_DAI_VBST_SLOT_WIDTH            5
+
+/* MAX98926_R026_DOUT_CFG_FLAG */
+#define MAX98926_DAI_FLAG_EN_MASK               (1<<5)
+#define MAX98926_DAI_FLAG_EN_SHIFT          5
+#define MAX98926_DAI_FLAG_EN_WIDTH          1
+#define MAX98926_DAI_FLAG_SLOT_MASK         (0x1F<<0)
+#define MAX98926_DAI_FLAG_SLOT_SHIFT            0
+#define MAX98926_DAI_FLAG_SLOT_WIDTH            5
+
+/* MAX98926_R027_DOUT_HIZ_CFG1 */
+#define MAX98926_DAI_SLOT_HIZ_CFG1_MASK         (0xFF<<0)
+#define MAX98926_DAI_SLOT_HIZ_CFG1_SHIFT            0
+#define MAX98926_DAI_SLOT_HIZ_CFG1_WIDTH            8
+
+/* MAX98926_R028_DOUT_HIZ_CFG2 */
+#define MAX98926_DAI_SLOT_HIZ_CFG2_MASK         (0xFF<<0)
+#define MAX98926_DAI_SLOT_HIZ_CFG2_SHIFT            0
+#define MAX98926_DAI_SLOT_HIZ_CFG2_WIDTH            8
+
+/* MAX98926_R029_DOUT_HIZ_CFG3 */
+#define MAX98926_DAI_SLOT_HIZ_CFG3_MASK         (0xFF<<0)
+#define MAX98926_DAI_SLOT_HIZ_CFG3_SHIFT            0
+#define MAX98926_DAI_SLOT_HIZ_CFG3_WIDTH            8
+
+/* MAX98926_R02A_DOUT_HIZ_CFG4 */
+#define MAX98926_DAI_SLOT_HIZ_CFG4_MASK         (0xFF<<0)
+#define MAX98926_DAI_SLOT_HIZ_CFG4_SHIFT            0
+#define MAX98926_DAI_SLOT_HIZ_CFG4_WIDTH            8
+
+/* MAX98926_R02B_DOUT_DRV_STRENGTH */
+#define MAX98926_DAI_OUT_DRIVE_MASK             (0x03<<0)
+#define MAX98926_DAI_OUT_DRIVE_SHIFT                0
+#define MAX98926_DAI_OUT_DRIVE_WIDTH                2
+
+/* MAX98926_R02C_FILTERS */
+#define MAX98926_ADC_DITHER_EN_MASK             (1<<7)
+#define MAX98926_ADC_DITHER_EN_SHIFT                7
+#define MAX98926_ADC_DITHER_EN_WIDTH                1
+#define MAX98926_IV_DCB_EN_MASK                 (1<<6)
+#define MAX98926_IV_DCB_EN_SHIFT                    6
+#define MAX98926_IV_DCB_EN_WIDTH                    1
+#define MAX98926_DAC_DITHER_EN_MASK             (1<<4)
+#define MAX98926_DAC_DITHER_EN_SHIFT                4
+#define MAX98926_DAC_DITHER_EN_WIDTH                1
+#define MAX98926_DAC_FILTER_MODE_MASK               (1<<3)
+#define MAX98926_DAC_FILTER_MODE_SHIFT          3
+#define MAX98926_DAC_FILTER_MODE_WIDTH          1
+#define MAX98926_DAC_HPF_MASK               (0x07<<0)
+#define MAX98926_DAC_HPF_SHIFT                  0
+#define MAX98926_DAC_HPF_WIDTH                  3
+#define MAX98926_DAC_HPF_DISABLE        (0 << MAX98926_DAC_HPF_SHIFT)
+#define MAX98926_DAC_HPF_DC_BLOCK       (1 << MAX98926_DAC_HPF_SHIFT)
+#define MAX98926_DAC_HPF_EN_100     (2 << MAX98926_DAC_HPF_SHIFT)
+#define MAX98926_DAC_HPF_EN_200     (3 << MAX98926_DAC_HPF_SHIFT)
+#define MAX98926_DAC_HPF_EN_400     (4 << MAX98926_DAC_HPF_SHIFT)
+#define MAX98926_DAC_HPF_EN_800     (5 << MAX98926_DAC_HPF_SHIFT)
+
+/* MAX98926_R02D_GAIN */
+#define MAX98926_DAC_IN_SEL_MASK    (0x03<<5)
+#define MAX98926_DAC_IN_SEL_SHIFT   5
+#define MAX98926_DAC_IN_SEL_WIDTH   2
+#define MAX98926_SPK_GAIN_MASK      (0x1F<<0)
+#define MAX98926_SPK_GAIN_SHIFT     0
+#define MAX98926_SPK_GAIN_WIDTH     5
+
+#define MAX98926_DAC_IN_SEL_LEFT_DAI (0 << MAX98926_DAC_IN_SEL_SHIFT)
+#define MAX98926_DAC_IN_SEL_RIGHT_DAI (1 << MAX98926_DAC_IN_SEL_SHIFT)
+#define MAX98926_DAC_IN_SEL_SUMMED_DAI (2 << MAX98926_DAC_IN_SEL_SHIFT)
+#define MAX98926_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << MAX98926_DAC_IN_SEL_SHIFT)
+
+/* MAX98926_R02E_GAIN_RAMPING */
+#define MAX98926_SPK_RMP_EN_MASK        (1<<1)
+#define MAX98926_SPK_RMP_EN_SHIFT       1
+#define MAX98926_SPK_RMP_EN_WIDTH       1
+#define MAX98926_SPK_ZCD_EN_MASK        (1<<0)
+#define MAX98926_SPK_ZCD_EN_SHIFT       0
+#define MAX98926_SPK_ZCD_EN_WIDTH       1
+
+/* MAX98926_R02F_SPK_AMP */
+#define MAX98926_SPK_MODE_MASK      (1<<0)
+#define MAX98926_SPK_MODE_SHIFT     0
+#define MAX98926_SPK_MODE_WIDTH     1
+#define MAX98926_INSELECT_MODE_MASK (1<<1)
+#define MAX98926_INSELECT_MODE_SHIFT    1
+#define MAX98926_INSELECT_MODE_WIDTH    1
+
+/* MAX98926_R030_THRESHOLD */
+#define MAX98926_ALC_EN_MASK            (1<<5)
+#define MAX98926_ALC_EN_SHIFT           5
+#define MAX98926_ALC_EN_WIDTH           1
+#define MAX98926_ALC_TH_MASK            (0x1F<<0)
+#define MAX98926_ALC_TH_SHIFT           0
+#define MAX98926_ALC_TH_WIDTH           5
+
+/* MAX98926_R031_ALC_ATTACK */
+#define MAX98926_ALC_ATK_STEP_MASK  (0x0F<<4)
+#define MAX98926_ALC_ATK_STEP_SHIFT 4
+#define MAX98926_ALC_ATK_STEP_WIDTH 4
+#define MAX98926_ALC_ATK_RATE_MASK  (0x7<<0)
+#define MAX98926_ALC_ATK_RATE_SHIFT 0
+#define MAX98926_ALC_ATK_RATE_WIDTH 3
+
+/* MAX98926_R032_ALC_ATTEN_RLS */
+#define MAX98926_ALC_MAX_ATTEN_MASK (0x0F<<4)
+#define MAX98926_ALC_MAX_ATTEN_SHIFT    4
+#define MAX98926_ALC_MAX_ATTEN_WIDTH    4
+#define MAX98926_ALC_RLS_RATE_MASK  (0x7<<0)
+#define MAX98926_ALC_RLS_RATE_SHIFT 0
+#define MAX98926_ALC_RLS_RATE_WIDTH 3
+
+/* MAX98926_R033_ALC_HOLD_RLS */
+#define MAX98926_ALC_RLS_TGR_MASK       (1<<0)
+#define MAX98926_ALC_RLS_TGR_SHIFT  0
+#define MAX98926_ALC_RLS_TGR_WIDTH  1
+
+/* MAX98926_R034_ALC_CONFIGURATION */
+#define MAX98926_ALC_MUTE_EN_MASK       (1<<7)
+#define MAX98926_ALC_MUTE_EN_SHIFT  7
+#define MAX98926_ALC_MUTE_EN_WIDTH  1
+#define MAX98926_ALC_MUTE_DLY_MASK  (0x07<<4)
+#define MAX98926_ALC_MUTE_DLY_SHIFT 4
+#define MAX98926_ALC_MUTE_DLY_WIDTH 3
+#define MAX98926_ALC_RLS_DBT_MASK       (0x07<<0)
+#define MAX98926_ALC_RLS_DBT_SHIFT  0
+#define MAX98926_ALC_RLS_DBT_WIDTH  3
+
+/* MAX98926_R035_BOOST_CONVERTER */
+#define MAX98926_BST_SYNC_MASK      (1<<7)
+#define MAX98926_BST_SYNC_SHIFT     7
+#define MAX98926_BST_SYNC_WIDTH     1
+#define MAX98926_BST_PHASE_MASK     (0x03<<4)
+#define MAX98926_BST_PHASE_SHIFT        4
+#define MAX98926_BST_PHASE_WIDTH        2
+#define MAX98926_BST_SKIP_MODE_MASK (0x03<<0)
+#define MAX98926_BST_SKIP_MODE_SHIFT    0
+#define MAX98926_BST_SKIP_MODE_WIDTH    2
+
+/* MAX98926_R036_BLOCK_ENABLE */
+#define MAX98926_BST_EN_MASK            (1<<7)
+#define MAX98926_BST_EN_SHIFT           7
+#define MAX98926_BST_EN_WIDTH           1
+#define MAX98926_WATCH_EN_MASK      (1<<6)
+#define MAX98926_WATCH_EN_SHIFT     6
+#define MAX98926_WATCH_EN_WIDTH     1
+#define MAX98926_CLKMON_EN_MASK     (1<<5)
+#define MAX98926_CLKMON_EN_SHIFT        5
+#define MAX98926_CLKMON_EN_WIDTH        1
+#define MAX98926_SPK_EN_MASK            (1<<4)
+#define MAX98926_SPK_EN_SHIFT           4
+#define MAX98926_SPK_EN_WIDTH           1
+#define MAX98926_ADC_VBST_EN_MASK       (1<<3)
+#define MAX98926_ADC_VBST_EN_SHIFT  3
+#define MAX98926_ADC_VBST_EN_WIDTH  1
+#define MAX98926_ADC_VBAT_EN_MASK       (1<<2)
+#define MAX98926_ADC_VBAT_EN_SHIFT  2
+#define MAX98926_ADC_VBAT_EN_WIDTH  1
+#define MAX98926_ADC_IMON_EN_MASK       (1<<1)
+#define MAX98926_ADC_IMON_EN_SHIFT  1
+#define MAX98926_ADC_IMON_EN_WIDTH  1
+#define MAX98926_ADC_VMON_EN_MASK       (1<<0)
+#define MAX98926_ADC_VMON_EN_SHIFT  0
+#define MAX98926_ADC_VMON_EN_WIDTH  1
+
+/* MAX98926_R037_CONFIGURATION */
+#define MAX98926_BST_VOUT_MASK      (0x0F<<4)
+#define MAX98926_BST_VOUT_SHIFT     4
+#define MAX98926_BST_VOUT_WIDTH     4
+#define MAX98926_THERMWARN_LEVEL_MASK   (0x03<<2)
+#define MAX98926_THERMWARN_LEVEL_SHIFT          2
+#define MAX98926_THERMWARN_LEVEL_WIDTH          2
+#define MAX98926_WATCH_TIME_MASK            (0x03<<0)
+#define MAX98926_WATCH_TIME_SHIFT           0
+#define MAX98926_WATCH_TIME_WIDTH           2
+
+/* MAX98926_R038_GLOBAL_ENABLE */
+#define MAX98926_EN_MASK            (1<<7)
+#define MAX98926_EN_SHIFT           7
+#define MAX98926_EN_WIDTH           1
+
+/* MAX98926_R03A_BOOST_LIMITER */
+#define MAX98926_BST_ILIM_MASK  (0xF<<4)
+#define MAX98926_BST_ILIM_SHIFT 4
+#define MAX98926_BST_ILIM_WIDTH 4
+
+/* MAX98926_R0FF_VERSION */
+#define MAX98926_REV_ID_MASK    (0xFF<<0)
+#define MAX98926_REV_ID_SHIFT   0
+#define MAX98926_REV_ID_WIDTH   8
+
+struct max98926_priv {
+       struct regmap *regmap;
+       struct snd_soc_codec *codec;
+       unsigned int sysclk;
+       unsigned int v_slot;
+       unsigned int i_slot;
+       unsigned int ch_size;
+       unsigned int interleave_mode;
+};
+#endif
index c1b87c5800b1d0980cf541e96a4d22ae76e9b32c..1c8729984c2b6332502a0f90df457b1df59f22f0 100644 (file)
@@ -84,6 +84,7 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = {
 
 static const struct reg_default nau8825_reg_defaults[] = {
        { NAU8825_REG_ENA_CTRL, 0x00ff },
+       { NAU8825_REG_IIC_ADDR_SET, 0x0 },
        { NAU8825_REG_CLK_DIVIDER, 0x0050 },
        { NAU8825_REG_FLL1, 0x0 },
        { NAU8825_REG_FLL2, 0x3126 },
@@ -158,8 +159,7 @@ static const struct reg_default nau8825_reg_defaults[] = {
 static bool nau8825_readable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
-       case NAU8825_REG_ENA_CTRL:
-       case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV:
+       case NAU8825_REG_ENA_CTRL ... NAU8825_REG_FLL_VCO_RSV:
        case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL:
        case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL:
        case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL:
@@ -184,8 +184,7 @@ static bool nau8825_readable_reg(struct device *dev, unsigned int reg)
 static bool nau8825_writeable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
-       case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL:
-       case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV:
+       case NAU8825_REG_RESET ... NAU8825_REG_FLL_VCO_RSV:
        case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL:
        case NAU8825_REG_INTERRUPT_MASK:
        case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL:
@@ -227,10 +226,42 @@ static bool nau8825_volatile_reg(struct device *dev, unsigned int reg)
 static int nau8825_pump_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
+
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                /* Prevent startup click by letting charge pump to ramp up */
                msleep(10);
+               regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP,
+                       NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW);
+               break;
+       case SND_SOC_DAPM_PRE_PMD:
+               regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP,
+                       NAU8825_JAMNODCLOW, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int nau8825_output_dac_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               /* Disables the TESTDAC to let DAC signal pass through. */
+               regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
+                       NAU8825_BIAS_TESTDAC_EN, 0);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
+                       NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN);
                break;
        default:
                return -EINVAL;
@@ -316,10 +347,10 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
        SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL,
                NAU8825_SAR_ADC_EN_SFT, 0),
 
-       SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0),
-       SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0),
-       SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("ADACL Clock", 3, NAU8825_REG_RDAC, 8, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("ADACR Clock", 3, NAU8825_REG_RDAC, 9, 0, NULL, 0),
 
        SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL,
                NAU8825_ENABLE_DACR_SFT, 0),
@@ -330,29 +361,48 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux),
        SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux),
 
-       SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL,
-               0),
+       SND_SOC_DAPM_PGA_S("HP amp L", 0,
+               NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("HP amp R", 0,
+               NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0),
 
-       SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0,
-               nau8825_pump_event, SND_SOC_DAPM_POST_PMU),
+       SND_SOC_DAPM_PGA_S("Charge Pump", 1, NAU8825_REG_CHARGE_PUMP, 5, 0,
+               nau8825_pump_event, SND_SOC_DAPM_POST_PMU |
+               SND_SOC_DAPM_PRE_PMD),
 
-       SND_SOC_DAPM_PGA("Output Driver R Stage 1",
+       SND_SOC_DAPM_PGA_S("Output Driver R Stage 1", 4,
                NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("Output Driver L Stage 1",
+       SND_SOC_DAPM_PGA_S("Output Driver L Stage 1", 4,
                NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("Output Driver R Stage 2",
+       SND_SOC_DAPM_PGA_S("Output Driver R Stage 2", 5,
                NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("Output Driver L Stage 2",
+       SND_SOC_DAPM_PGA_S("Output Driver L Stage 2", 5,
                NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0),
-       SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1,
+       SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 6,
                NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0),
-       SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1,
+       SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 6,
                NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0),
 
-       SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0),
-       SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0),
+       SND_SOC_DAPM_PGA_S("Output DACL", 7,
+               NAU8825_REG_CHARGE_PUMP, 8, 1, nau8825_output_dac_event,
+               SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_PGA_S("Output DACR", 7,
+               NAU8825_REG_CHARGE_PUMP, 9, 1, nau8825_output_dac_event,
+               SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+       /* HPOL/R are ungrounded by disabling 16 Ohm pull-downs on playback */
+       SND_SOC_DAPM_PGA_S("HPOL Pulldown", 8,
+               NAU8825_REG_HSD_CTRL, 0, 1, NULL, 0),
+       SND_SOC_DAPM_PGA_S("HPOR Pulldown", 8,
+               NAU8825_REG_HSD_CTRL, 1, 1, NULL, 0),
+
+       /* High current HPOL/R boost driver */
+       SND_SOC_DAPM_PGA_S("HP Boost Driver", 9,
+               NAU8825_REG_BOOST, 9, 1, NULL, 0),
+
+       /* Class G operation control*/
+       SND_SOC_DAPM_PGA_S("Class G", 10,
+               NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, 0),
 
        SND_SOC_DAPM_OUTPUT("HPOL"),
        SND_SOC_DAPM_OUTPUT("HPOR"),
@@ -375,24 +425,27 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
        {"DACR Mux", "DACR", "DDACR"},
        {"HP amp L", NULL, "DACL Mux"},
        {"HP amp R", NULL, "DACR Mux"},
-       {"HP amp L", NULL, "HP amp power"},
-       {"HP amp R", NULL, "HP amp power"},
-       {"ADACL", NULL, "HP amp L"},
-       {"ADACR", NULL, "HP amp R"},
-       {"ADACL", NULL, "ADACL Clock"},
-       {"ADACR", NULL, "ADACR Clock"},
-       {"Output Driver L Stage 1", NULL, "ADACL"},
-       {"Output Driver R Stage 1", NULL, "ADACR"},
+       {"Charge Pump", NULL, "HP amp L"},
+       {"Charge Pump", NULL, "HP amp R"},
+       {"ADACL", NULL, "Charge Pump"},
+       {"ADACR", NULL, "Charge Pump"},
+       {"ADACL Clock", NULL, "ADACL"},
+       {"ADACR Clock", NULL, "ADACR"},
+       {"Output Driver L Stage 1", NULL, "ADACL Clock"},
+       {"Output Driver R Stage 1", NULL, "ADACR Clock"},
        {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"},
        {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"},
        {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"},
        {"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"},
        {"Output DACL", NULL, "Output Driver L Stage 3"},
        {"Output DACR", NULL, "Output Driver R Stage 3"},
-       {"HPOL", NULL, "Output DACL"},
-       {"HPOR", NULL, "Output DACR"},
-       {"HPOL", NULL, "Charge Pump"},
-       {"HPOR", NULL, "Charge Pump"},
+       {"HPOL Pulldown", NULL, "Output DACL"},
+       {"HPOR Pulldown", NULL, "Output DACR"},
+       {"HP Boost Driver", NULL, "HPOL Pulldown"},
+       {"HP Boost Driver", NULL, "HPOR Pulldown"},
+       {"Class G", NULL, "HP Boost Driver"},
+       {"HPOL", NULL, "Class G"},
+       {"HPOR", NULL, "Class G"},
 };
 
 static int nau8825_hw_params(struct snd_pcm_substream *substream,
@@ -659,11 +712,10 @@ static int nau8825_jack_insert(struct nau8825 *nau8825)
                break;
        }
 
-       if (type & SND_JACK_HEADPHONE) {
-               /* Unground HPL/R */
-               regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0x3, 0);
-       }
-
+       /* Leaving HPOL/R grounded after jack insert by default. They will be
+        * ungrounded as part of the widget power up sequence at the beginning
+        * of playback to reduce pop.
+        */
        return type;
 }
 
@@ -768,6 +820,8 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
 {
        struct regmap *regmap = nau8825->regmap;
 
+       /* Latch IIC LSB value */
+       regmap_write(regmap, NAU8825_REG_IIC_ADDR_SET, 0x0001);
        /* Enable Bias/Vmid */
        regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
                NAU8825_BIAS_VMID, NAU8825_BIAS_VMID);
@@ -780,10 +834,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
                nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT);
        /* Disable Boost Driver, Automatic Short circuit protection enable */
        regmap_update_bits(regmap, NAU8825_REG_BOOST,
-               NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS |
-               NAU8825_SHORT_SHUTDOWN_EN,
-               NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS |
-               NAU8825_SHORT_SHUTDOWN_EN);
+               NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS |
+               NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN,
+               NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS |
+               NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN);
 
        regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL,
                NAU8825_JKDET_OUTPUT_EN,
@@ -822,6 +876,35 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
                NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128);
        regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1,
                NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128);
+       /* Disable DACR/L power */
+       regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP,
+               NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL,
+               NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL);
+       /* Enable TESTDAC. This sets the analog DAC inputs to a '0' input
+        * signal to avoid any glitches due to power up transients in both
+        * the analog and digital DAC circuit.
+        */
+       regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ,
+               NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN);
+       /* CICCLP off */
+       regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1,
+               NAU8825_DAC_CLIP_OFF, NAU8825_DAC_CLIP_OFF);
+
+       /* Class AB bias current to 2x, DAC Capacitor enable MSB/LSB */
+       regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_2,
+               NAU8825_HP_NON_CLASSG_CURRENT_2xADJ |
+               NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB,
+               NAU8825_HP_NON_CLASSG_CURRENT_2xADJ |
+               NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB);
+       /* Class G timer 64ms */
+       regmap_update_bits(regmap, NAU8825_REG_CLASSG_CTRL,
+               NAU8825_CLASSG_TIMER_MASK,
+               0x20 << NAU8825_CLASSG_TIMER_SFT);
+       /* DAC clock delay 2ns, VREF */
+       regmap_update_bits(regmap, NAU8825_REG_RDAC,
+               NAU8825_RDAC_CLK_DELAY_MASK | NAU8825_RDAC_VREF_MASK,
+               (0x2 << NAU8825_RDAC_CLK_DELAY_SFT) |
+               (0x3 << NAU8825_RDAC_VREF_SFT));
 }
 
 static const struct regmap_config nau8825_regmap_config = {
index dff8edb83bfdfeb034a230ddbfce02952617eace..8ceb5f38547846e89239e2023fac8bed20c4359e 100644 (file)
@@ -14,6 +14,7 @@
 
 #define NAU8825_REG_RESET              0x00
 #define NAU8825_REG_ENA_CTRL           0x01
+#define NAU8825_REG_IIC_ADDR_SET               0x02
 #define NAU8825_REG_CLK_DIVIDER                0x03
 #define NAU8825_REG_FLL1               0x04
 #define NAU8825_REG_FLL2               0x05
 
 /* HSD_CTRL (0xc) */
 #define NAU8825_HSD_AUTO_MODE  (1 << 6)
-/* 0 - short to GND, 1 - open */
+/* 0 - open, 1 - short to GND */
 #define NAU8825_SPKR_DWN1R     (1 << 1)
 #define NAU8825_SPKR_DWN1L     (1 << 0)
 
 /* DACR_CTRL (0x34) */
 #define NAU8825_DACR_CH_SEL_SFT        9
 
+/* CLASSG_CTRL (0x50) */
+#define NAU8825_CLASSG_TIMER_SFT       8
+#define NAU8825_CLASSG_TIMER_MASK      (0x3f << NAU8825_CLASSG_TIMER_SFT)
+#define NAU8825_CLASSG_EN              (1 << 0)
+
 /* I2C_DEVICE_ID (0x58) */
 #define NAU8825_GPIO2JD1       (1 << 7)
 #define NAU8825_SOFTWARE_ID_MASK       0x3
 #define NAU8825_SOFTWARE_ID_NAU8825    0x0
 
 /* BIAS_ADJ (0x66) */
+#define NAU8825_BIAS_TESTDAC_EN        (0x3 << 8)
 #define NAU8825_BIAS_VMID      (1 << 6)
 #define NAU8825_BIAS_VMID_SEL_SFT      4
 #define NAU8825_BIAS_VMID_SEL_MASK     (3 << NAU8825_BIAS_VMID_SEL_SFT)
 #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB      (3 << 8)
 #define NAU8825_POWERUP_ADCL   (1 << 6)
 
+/* RDAC (0x73) */
+#define NAU8825_RDAC_CLK_DELAY_SFT     4
+#define NAU8825_RDAC_CLK_DELAY_MASK    (0x7 << NAU8825_RDAC_CLK_DELAY_SFT)
+#define NAU8825_RDAC_VREF_SFT  2
+#define NAU8825_RDAC_VREF_MASK (0x3 << NAU8825_RDAC_VREF_SFT)
+
 /* MIC_BIAS (0x74) */
 #define NAU8825_MICBIAS_JKSLV  (1 << 14)
 #define NAU8825_MICBIAS_JKR2   (1 << 12)
 /* BOOST (0x76) */
 #define NAU8825_PRECHARGE_DIS  (1 << 13)
 #define NAU8825_GLOBAL_BIAS_EN (1 << 12)
+#define NAU8825_HP_BOOST_DIS           (1 << 9)
 #define NAU8825_HP_BOOST_G_DIS (1 << 8)
 #define NAU8825_SHORT_SHUTDOWN_EN      (1 << 6)
 
diff --git a/sound/soc/codecs/pcm179x-i2c.c b/sound/soc/codecs/pcm179x-i2c.c
new file mode 100644 (file)
index 0000000..4118106
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * PCM179X ASoC I2C driver
+ *
+ * Copyright (c) Teenage Engineering AB 2016
+ *
+ *     Jacob Siverskog <jacob@teenage.engineering>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include "pcm179x.h"
+
+static int pcm179x_i2c_probe(struct i2c_client *client,
+                             const struct i2c_device_id *id)
+{
+       struct regmap *regmap;
+       int ret;
+
+       regmap = devm_regmap_init_i2c(client, &pcm179x_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret);
+               return ret;
+       }
+
+       return pcm179x_common_init(&client->dev, regmap);
+}
+
+static int pcm179x_i2c_remove(struct i2c_client *client)
+{
+       return pcm179x_common_exit(&client->dev);
+}
+
+static const struct of_device_id pcm179x_of_match[] = {
+       { .compatible = "ti,pcm1792a", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pcm179x_of_match);
+
+static const struct i2c_device_id pcm179x_i2c_ids[] = {
+       { "pcm179x", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcm179x_i2c_ids);
+
+static struct i2c_driver pcm179x_i2c_driver = {
+       .driver = {
+               .name   = "pcm179x",
+               .of_match_table = of_match_ptr(pcm179x_of_match),
+       },
+       .id_table       = pcm179x_i2c_ids,
+       .probe          = pcm179x_i2c_probe,
+       .remove         = pcm179x_i2c_remove,
+};
+
+module_i2c_driver(pcm179x_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC PCM179X I2C driver");
+MODULE_AUTHOR("Jacob Siverskog <jacob@teenage.engineering>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm179x-spi.c b/sound/soc/codecs/pcm179x-spi.c
new file mode 100644 (file)
index 0000000..da924d4
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * PCM179X ASoC SPI driver
+ *
+ * Copyright (c) Amarula Solutions B.V. 2013
+ *
+ *     Michael Trimarchi <michael@amarulasolutions.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+#include "pcm179x.h"
+
+static int pcm179x_spi_probe(struct spi_device *spi)
+{
+       struct regmap *regmap;
+       int ret;
+
+       regmap = devm_regmap_init_spi(spi, &pcm179x_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&spi->dev, "Failed to allocate regmap: %d\n", ret);
+               return ret;
+       }
+
+       return pcm179x_common_init(&spi->dev, regmap);
+}
+
+static int pcm179x_spi_remove(struct spi_device *spi)
+{
+       return pcm179x_common_exit(&spi->dev);
+}
+
+static const struct of_device_id pcm179x_of_match[] = {
+       { .compatible = "ti,pcm1792a", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pcm179x_of_match);
+
+static const struct spi_device_id pcm179x_spi_ids[] = {
+       { "pcm179x", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, pcm179x_spi_ids);
+
+static struct spi_driver pcm179x_spi_driver = {
+       .driver = {
+               .name = "pcm179x",
+               .of_match_table = of_match_ptr(pcm179x_of_match),
+       },
+       .id_table = pcm179x_spi_ids,
+       .probe = pcm179x_spi_probe,
+       .remove = pcm179x_spi_remove,
+};
+
+module_spi_driver(pcm179x_spi_driver);
+
+MODULE_DESCRIPTION("ASoC PCM179X SPI driver");
+MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
+MODULE_LICENSE("GPL");
index a56c7b767d900cf8298d6f9f095b86740a74ca10..06a66579ca6d34964044c0ac297333a805b2a3c3 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/spi/spi.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -29,7 +28,6 @@
 #include <sound/soc.h>
 #include <sound/tlv.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 
 #include "pcm179x.h"
 
@@ -189,18 +187,14 @@ static struct snd_soc_dai_driver pcm179x_dai = {
                .stream_name = "Playback",
                .channels_min = 2,
                .channels_max = 2,
-               .rates = PCM1792A_RATES,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 10000,
+               .rate_max = 200000,
                .formats = PCM1792A_FORMATS, },
        .ops = &pcm179x_dai_ops,
 };
 
-static const struct of_device_id pcm179x_of_match[] = {
-       { .compatible = "ti,pcm1792a", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, pcm179x_of_match);
-
-static const struct regmap_config pcm179x_regmap = {
+const struct regmap_config pcm179x_regmap_config = {
        .reg_bits               = 8,
        .val_bits               = 8,
        .max_register           = 23,
@@ -209,6 +203,7 @@ static const struct regmap_config pcm179x_regmap = {
        .writeable_reg          = pcm179x_writeable_reg,
        .readable_reg           = pcm179x_accessible_reg,
 };
+EXPORT_SYMBOL_GPL(pcm179x_regmap_config);
 
 static struct snd_soc_codec_driver soc_codec_dev_pcm179x = {
        .controls               = pcm179x_controls,
@@ -219,52 +214,29 @@ static struct snd_soc_codec_driver soc_codec_dev_pcm179x = {
        .num_dapm_routes        = ARRAY_SIZE(pcm179x_dapm_routes),
 };
 
-static int pcm179x_spi_probe(struct spi_device *spi)
+int pcm179x_common_init(struct device *dev, struct regmap *regmap)
 {
        struct pcm179x_private *pcm179x;
-       int ret;
 
-       pcm179x = devm_kzalloc(&spi->dev, sizeof(struct pcm179x_private),
+       pcm179x = devm_kzalloc(dev, sizeof(struct pcm179x_private),
                                GFP_KERNEL);
        if (!pcm179x)
                return -ENOMEM;
 
-       spi_set_drvdata(spi, pcm179x);
-
-       pcm179x->regmap = devm_regmap_init_spi(spi, &pcm179x_regmap);
-       if (IS_ERR(pcm179x->regmap)) {
-               ret = PTR_ERR(pcm179x->regmap);
-               dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
-               return ret;
-       }
+       pcm179x->regmap = regmap;
+       dev_set_drvdata(dev, pcm179x);
 
-       return snd_soc_register_codec(&spi->dev,
+       return snd_soc_register_codec(dev,
                        &soc_codec_dev_pcm179x, &pcm179x_dai, 1);
 }
+EXPORT_SYMBOL_GPL(pcm179x_common_init);
 
-static int pcm179x_spi_remove(struct spi_device *spi)
+int pcm179x_common_exit(struct device *dev)
 {
-       snd_soc_unregister_codec(&spi->dev);
+       snd_soc_unregister_codec(dev);
        return 0;
 }
-
-static const struct spi_device_id pcm179x_spi_ids[] = {
-       { "pcm179x", 0 },
-       { },
-};
-MODULE_DEVICE_TABLE(spi, pcm179x_spi_ids);
-
-static struct spi_driver pcm179x_codec_driver = {
-       .driver = {
-               .name = "pcm179x",
-               .of_match_table = of_match_ptr(pcm179x_of_match),
-       },
-       .id_table = pcm179x_spi_ids,
-       .probe = pcm179x_spi_probe,
-       .remove = pcm179x_spi_remove,
-};
-
-module_spi_driver(pcm179x_codec_driver);
+EXPORT_SYMBOL_GPL(pcm179x_common_exit);
 
 MODULE_DESCRIPTION("ASoC PCM179X driver");
 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
index c6fdc062a497ef080ee3e4225ba90328e1c390cc..11e331268aae27c2523a9e12dfb4c44ce3967dd0 100644 (file)
 #ifndef __PCM179X_H__
 #define __PCM179X_H__
 
-#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \
-                       SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
-                       SNDRV_PCM_RATE_192000)
-
 #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
                          SNDRV_PCM_FMTBIT_S16_LE)
 
+extern const struct regmap_config pcm179x_regmap_config;
+
+int pcm179x_common_init(struct device *dev, struct regmap *regmap);
+int pcm179x_common_exit(struct device *dev);
+
 #endif
index 44b268aa4dd88e0cee6ac4c4a60663d51df0d1ab..992a77edcd5d1ff90d8857860972dadc4b86d7d7 100644 (file)
@@ -299,10 +299,15 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
                                  int clk_id, unsigned int freq, int dir)
 {
        struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(dai->codec);
+       int ret;
 
        if (freq > PCM1368A_MAX_SYSCLK)
                return -EINVAL;
 
+       ret = clk_set_rate(pcm3168a->scki, freq);
+       if (ret)
+               return ret;
+
        pcm3168a->sysclk = freq;
 
        return 0;
@@ -395,13 +400,12 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
        struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec);
        bool tx, master_mode;
        u32 val, mask, shift, reg;
-       unsigned int rate, channels, fmt, ratio, max_ratio;
+       unsigned int rate, fmt, ratio, max_ratio;
        int i, min_frame_size;
        snd_pcm_format_t format;
 
        rate = params_rate(params);
        format = params_format(params);
-       channels = params_channels(params);
 
        ratio = pcm3168a->sysclk / rate;
 
index 93e8c9017633f97ed264cd9e54c4aaab606d54f3..7af5e7380d61e45658feb4ba190b2e2a7cd8efec 100644 (file)
@@ -1674,7 +1674,7 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on)
                                regmap_write(rt5645->regmap, RT5645_PR_BASE +
                                        RT5645_MAMP_INT_REG2, 0xfc00);
                                snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140);
-                               msleep(70);
+                               msleep(90);
                                rt5645->hp_on = true;
                        } else {
                                /* depop parameters */
@@ -3029,13 +3029,18 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec,
                        RT5645_PWR_BG | RT5645_PWR_VREF2,
                        RT5645_PWR_VREF1 | RT5645_PWR_MB |
                        RT5645_PWR_BG | RT5645_PWR_VREF2);
+               mdelay(10);
                snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
                        RT5645_PWR_FV1 | RT5645_PWR_FV2,
                        RT5645_PWR_FV1 | RT5645_PWR_FV2);
-               if (rt5645->en_button_func &&
-                       snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
-                       queue_delayed_work(system_power_efficient_wq,
-                               &rt5645->jack_detect_work, msecs_to_jiffies(0));
+               if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
+                       snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140);
+                       msleep(40);
+                       if (rt5645->en_button_func)
+                               queue_delayed_work(system_power_efficient_wq,
+                                       &rt5645->jack_detect_work,
+                                       msecs_to_jiffies(0));
+               }
                break;
 
        case SND_SOC_BIAS_OFF:
index 781398fb2841565f20d2f7e7a4f893d840e3e7ae..f7a6ce7e5fb12b7ab183428b28d6c69409676d08 100644 (file)
@@ -446,7 +446,7 @@ static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = dac33->fifo_mode;
+       ucontrol->value.enumerated.item[0] = dac33->fifo_mode;
 
        return 0;
 }
@@ -458,17 +458,16 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       if (dac33->fifo_mode == ucontrol->value.integer.value[0])
+       if (dac33->fifo_mode == ucontrol->value.enumerated.item[0])
                return 0;
        /* Do not allow changes while stream is running*/
        if (snd_soc_codec_is_active(codec))
                return -EPERM;
 
-       if (ucontrol->value.integer.value[0] < 0 ||
-           ucontrol->value.integer.value[0] >= DAC33_FIFO_LAST_MODE)
+       if (ucontrol->value.enumerated.item[0] >= DAC33_FIFO_LAST_MODE)
                ret = -EINVAL;
        else
-               dac33->fifo_mode = ucontrol->value.integer.value[0];
+               dac33->fifo_mode = ucontrol->value.enumerated.item[0];
 
        return ret;
 }
index 7693c1129babf0e42c58b5ca93832052374cb426..1b79778098d29ffbb377efc24576825cdfe8038c 100644 (file)
@@ -175,7 +175,7 @@ static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = wl1273->mode;
+       ucontrol->value.enumerated.item[0] = wl1273->mode;
 
        return 0;
 }
@@ -193,18 +193,17 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
-       if (wl1273->mode == ucontrol->value.integer.value[0])
+       if (wl1273->mode == ucontrol->value.enumerated.item[0])
                return 0;
 
        /* Do not allow changes while stream is running */
        if (snd_soc_codec_is_active(codec))
                return -EPERM;
 
-       if (ucontrol->value.integer.value[0] < 0 ||
-           ucontrol->value.integer.value[0] >=  ARRAY_SIZE(wl1273_audio_route))
+       if (ucontrol->value.enumerated.item[0] >=  ARRAY_SIZE(wl1273_audio_route))
                return -EINVAL;
 
-       wl1273->mode = ucontrol->value.integer.value[0];
+       wl1273->mode = ucontrol->value.enumerated.item[0];
 
        return 1;
 }
@@ -219,7 +218,7 @@ static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
 
        dev_dbg(codec->dev, "%s: enter.\n", __func__);
 
-       ucontrol->value.integer.value[0] = wl1273->core->audio_mode;
+       ucontrol->value.enumerated.item[0] = wl1273->core->audio_mode;
 
        return 0;
 }
@@ -233,7 +232,7 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
 
        dev_dbg(codec->dev, "%s: enter.\n", __func__);
 
-       val = ucontrol->value.integer.value[0];
+       val = ucontrol->value.enumerated.item[0];
        if (wl1273->core->audio_mode == val)
                return 0;
 
index 64637d1cf4e5673f17145b13d7c12681bed21d48..a8b3e3f701f964bdd3b54869a655d9cbfec74264 100644 (file)
@@ -619,7 +619,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
        struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
-       unsigned int v;
+       unsigned int v = 0;
        int ret;
 
        switch (event) {
@@ -654,7 +654,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
                break;
        }
 
-       return wm_adsp2_early_event(w, kcontrol, event);
+       return wm_adsp2_early_event(w, kcontrol, event, v);
 }
 
 static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
@@ -1408,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
 ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
 ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
 
-WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev),
+WM_ADSP2("DSP1", 0, wm5102_adsp_power_ev),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1599,6 +1599,9 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "Slim2 Capture", NULL, "SYSCLK" },
        { "Slim3 Capture", NULL, "SYSCLK" },
 
+       { "Audio Trace DSP", NULL, "DSP1" },
+       { "Audio Trace DSP", NULL, "SYSCLK" },
+
        { "IN1L PGA", NULL, "IN1L" },
        { "IN1R PGA", NULL, "IN1R" },
 
@@ -1735,7 +1738,7 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        }
 }
 
-#define WM5102_RATES SNDRV_PCM_RATE_8000_192000
+#define WM5102_RATES SNDRV_PCM_RATE_KNOT
 
 #define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -1864,14 +1867,67 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
                 },
                .ops = &arizona_simple_dai_ops,
        },
+       {
+               .name = "wm5102-cpu-trace",
+               .capture = {
+                       .stream_name = "Audio Trace CPU",
+                       .channels_min = 1,
+                       .channels_max = 6,
+                       .rates = WM5102_RATES,
+                       .formats = WM5102_FORMATS,
+               },
+               .compress_new = snd_soc_new_compress,
+       },
+       {
+               .name = "wm5102-dsp-trace",
+               .capture = {
+                       .stream_name = "Audio Trace DSP",
+                       .channels_min = 1,
+                       .channels_max = 4,
+                       .rates = WM5102_RATES,
+                       .formats = WM5102_FORMATS,
+               },
+       },
 };
 
+static int wm5102_open(struct snd_compr_stream *stream)
+{
+       struct snd_soc_pcm_runtime *rtd = stream->private_data;
+       struct wm5102_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
+
+       return wm_adsp_compr_open(&priv->core.adsp[0], stream);
+}
+
+static irqreturn_t wm5102_adsp2_irq(int irq, void *data)
+{
+       struct wm5102_priv *priv = data;
+       struct arizona *arizona = priv->core.arizona;
+       int ret;
+
+       ret = wm_adsp_compr_handle_irq(&priv->core.adsp[0]);
+       if (ret == -ENODEV) {
+               dev_err(arizona->dev, "Spurious compressed data IRQ\n");
+               return IRQ_NONE;
+       }
+
+       return IRQ_HANDLED;
+}
+
 static int wm5102_codec_probe(struct snd_soc_codec *codec)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
+       struct arizona *arizona = priv->core.arizona;
        int ret;
 
+       ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
+                                 "ADSP2 Compressed IRQ", wm5102_adsp2_irq,
+                                 priv);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
+               return ret;
+       }
+
        ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec);
        if (ret)
                return ret;
@@ -1946,6 +2002,20 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
        .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
 };
 
+static struct snd_compr_ops wm5102_compr_ops = {
+       .open = wm5102_open,
+       .free = wm_adsp_compr_free,
+       .set_params = wm_adsp_compr_set_params,
+       .get_caps = wm_adsp_compr_get_caps,
+       .trigger = wm_adsp_compr_trigger,
+       .pointer = wm_adsp_compr_pointer,
+       .copy = wm_adsp_compr_copy,
+};
+
+static struct snd_soc_platform_driver wm5102_compr_platform = {
+       .compr_ops = &wm5102_compr_ops,
+};
+
 static int wm5102_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
@@ -2005,12 +2075,25 @@ static int wm5102_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_idle(&pdev->dev);
 
-       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102,
+       ret = snd_soc_register_platform(&pdev->dev, &wm5102_compr_platform);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
+               return ret;
+       }
+
+       ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102,
                                      wm5102_dai, ARRAY_SIZE(wm5102_dai));
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
+               snd_soc_unregister_platform(&pdev->dev);
+       }
+
+       return ret;
 }
 
 static int wm5102_remove(struct platform_device *pdev)
 {
+       snd_soc_unregister_platform(&pdev->dev);
        snd_soc_unregister_codec(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
index 97c0f1e2388637dcdc686da1f1a5cf06037a6944..83ba70fe16e69488a473a68bcc97d4cc2408874f 100644 (file)
@@ -191,6 +191,25 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int wm5110_adsp_power_ev(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+       unsigned int v;
+       int ret;
+
+       ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret);
+               return ret;
+       }
+
+       v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+       return wm_adsp2_early_event(w, kcontrol, event, v);
+}
+
 static const struct reg_sequence wm5110_no_dre_left_enable[] = {
        { 0x3024, 0xE410 },
        { 0x3025, 0x0056 },
@@ -1179,10 +1198,10 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
                 NULL, 0),
 
-WM_ADSP2("DSP1", 0),
-WM_ADSP2("DSP2", 1),
-WM_ADSP2("DSP3", 2),
-WM_ADSP2("DSP4", 3),
+WM_ADSP2("DSP1", 0, wm5110_adsp_power_ev),
+WM_ADSP2("DSP2", 1, wm5110_adsp_power_ev),
+WM_ADSP2("DSP3", 2, wm5110_adsp_power_ev),
+WM_ADSP2("DSP4", 3, wm5110_adsp_power_ev),
 
 SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
                 ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
@@ -1809,6 +1828,9 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "Voice Control DSP", NULL, "DSP3" },
        { "Voice Control DSP", NULL, "SYSCLK" },
 
+       { "Audio Trace DSP", NULL, "DSP1" },
+       { "Audio Trace DSP", NULL, "SYSCLK" },
+
        { "IN1L PGA", NULL, "IN1L" },
        { "IN1R PGA", NULL, "IN1R" },
 
@@ -2002,7 +2024,7 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        }
 }
 
-#define WM5110_RATES SNDRV_PCM_RATE_8000_192000
+#define WM5110_RATES SNDRV_PCM_RATE_KNOT
 
 #define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -2152,6 +2174,27 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
                        .formats = WM5110_FORMATS,
                },
        },
+       {
+               .name = "wm5110-cpu-trace",
+               .capture = {
+                       .stream_name = "Audio Trace CPU",
+                       .channels_min = 1,
+                       .channels_max = 6,
+                       .rates = WM5110_RATES,
+                       .formats = WM5110_FORMATS,
+               },
+               .compress_new = snd_soc_new_compress,
+       },
+       {
+               .name = "wm5110-dsp-trace",
+               .capture = {
+                       .stream_name = "Audio Trace DSP",
+                       .channels_min = 1,
+                       .channels_max = 6,
+                       .rates = WM5110_RATES,
+                       .formats = WM5110_FORMATS,
+               },
+       },
 };
 
 static int wm5110_open(struct snd_compr_stream *stream)
@@ -2163,6 +2206,8 @@ static int wm5110_open(struct snd_compr_stream *stream)
 
        if (strcmp(rtd->codec_dai->name, "wm5110-dsp-voicectrl") == 0) {
                n_adsp = 2;
+       } else if (strcmp(rtd->codec_dai->name, "wm5110-dsp-trace") == 0) {
+               n_adsp = 0;
        } else {
                dev_err(arizona->dev,
                        "No suitable compressed stream for DAI '%s'\n",
@@ -2175,12 +2220,21 @@ static int wm5110_open(struct snd_compr_stream *stream)
 
 static irqreturn_t wm5110_adsp2_irq(int irq, void *data)
 {
-       struct wm5110_priv *florida = data;
-       int ret;
+       struct wm5110_priv *priv = data;
+       struct arizona *arizona = priv->core.arizona;
+       int serviced = 0;
+       int i, ret;
 
-       ret = wm_adsp_compr_handle_irq(&florida->core.adsp[2]);
-       if (ret == -ENODEV)
+       for (i = 0; i < WM5110_NUM_ADSP; ++i) {
+               ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]);
+               if (ret != -ENODEV)
+                       serviced++;
+       }
+
+       if (!serviced) {
+               dev_err(arizona->dev, "Spurious compressed data IRQ\n");
                return IRQ_NONE;
+       }
 
        return IRQ_HANDLED;
 }
@@ -2366,7 +2420,7 @@ static int wm5110_probe(struct platform_device *pdev)
        ret = snd_soc_register_platform(&pdev->dev, &wm5110_compr_platform);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
-               goto error;
+               return ret;
        }
 
        ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
@@ -2376,7 +2430,6 @@ static int wm5110_probe(struct platform_device *pdev)
                snd_soc_unregister_platform(&pdev->dev);
        }
 
-error:
        return ret;
 }
 
index 61299ca372ffc1fc3f83dd88fe823151da7b09b8..6f1024f48b193bc7d3127cc8b12d56d14124413b 100644 (file)
@@ -233,7 +233,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = wm8753->dai_func;
+       ucontrol->value.enumerated.item[0] = wm8753->dai_func;
        return 0;
 }
 
@@ -244,7 +244,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
        u16 ioctl;
 
-       if (wm8753->dai_func == ucontrol->value.integer.value[0])
+       if (wm8753->dai_func == ucontrol->value.enumerated.item[0])
                return 0;
 
        if (snd_soc_codec_is_active(codec))
@@ -252,7 +252,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
 
        ioctl = snd_soc_read(codec, WM8753_IOCTL);
 
-       wm8753->dai_func = ucontrol->value.integer.value[0];
+       wm8753->dai_func = ucontrol->value.enumerated.item[0];
 
        if (((ioctl >> 2) & 0x3) == wm8753->dai_func)
                return 1;
index 8172e499e6ed18f33e6f94b2bec1a1647d1c1788..edd7a77091942cd7b873e9c193baed54dd6186c6 100644 (file)
@@ -396,7 +396,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (value >= pdata->num_drc_cfgs)
                return -EINVAL;
@@ -467,7 +467,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (value >= pdata->num_retune_mobile_cfgs)
                return -EINVAL;
index c799cca5abeb704645687b863ccedfc6749e9ac2..6b864c0fc2b676cc83f9d03d2218815e7e805919 100644 (file)
@@ -459,7 +459,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
@@ -549,7 +549,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
@@ -582,7 +582,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
@@ -749,7 +749,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
index 7350ff654bbf37fe660e2b7a75cc5a15b5d63c68..0c002a5712cb4f261cd84454f38e24a89836519a 100644 (file)
@@ -497,9 +497,9 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
 
        reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
        if (reg & WM8983_EQ3DMODE)
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
 
        return 0;
 }
@@ -511,18 +511,18 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        unsigned int regpwr2, regpwr3;
        unsigned int reg_eq;
 
-       if (ucontrol->value.integer.value[0] != 0
-           && ucontrol->value.integer.value[0] != 1)
+       if (ucontrol->value.enumerated.item[0] != 0
+           && ucontrol->value.enumerated.item[0] != 1)
                return -EINVAL;
 
        reg_eq = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
        switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) {
        case 0:
-               if (!ucontrol->value.integer.value[0])
+               if (!ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        case 1:
-               if (ucontrol->value.integer.value[0])
+               if (ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        }
@@ -537,7 +537,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        /* set the desired eqmode */
        snd_soc_update_bits(codec, WM8983_EQ1_LOW_SHELF,
                            WM8983_EQ3DMODE_MASK,
-                           ucontrol->value.integer.value[0]
+                           ucontrol->value.enumerated.item[0]
                            << WM8983_EQ3DMODE_SHIFT);
        /* restore DAC/ADC configuration */
        snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, regpwr2);
index 9918152a03c7518e5c0c2e299a35145abd808a14..6ac76fe116b028db34c8cdbf3691babeb2a68844 100644 (file)
@@ -531,9 +531,9 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
 
        reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
        if (reg & WM8985_EQ3DMODE)
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
 
        return 0;
 }
@@ -545,18 +545,18 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        unsigned int regpwr2, regpwr3;
        unsigned int reg_eq;
 
-       if (ucontrol->value.integer.value[0] != 0
-                       && ucontrol->value.integer.value[0] != 1)
+       if (ucontrol->value.enumerated.item[0] != 0
+                       && ucontrol->value.enumerated.item[0] != 1)
                return -EINVAL;
 
        reg_eq = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
        switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) {
        case 0:
-               if (!ucontrol->value.integer.value[0])
+               if (!ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        case 1:
-               if (ucontrol->value.integer.value[0])
+               if (ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        }
@@ -573,7 +573,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        /* set the desired eqmode */
        snd_soc_update_bits(codec, WM8985_EQ1_LOW_SHELF,
                            WM8985_EQ3DMODE_MASK,
-                           ucontrol->value.integer.value[0]
+                           ucontrol->value.enumerated.item[0]
                            << WM8985_EQ3DMODE_SHIFT);
        /* restore DAC/ADC configuration */
        snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, regpwr2);
index 2ccbb322df775b803d40fe765958f439d855d41f..a18aecb4993590e6a7bd936b238fee544462a6bc 100644 (file)
@@ -362,7 +362,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
        struct wm8994 *control = wm8994->wm8994;
        struct wm8994_pdata *pdata = &control->pdata;
        int drc = wm8994_get_drc(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (drc < 0)
                return drc;
@@ -469,7 +469,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct wm8994 *control = wm8994->wm8994;
        struct wm8994_pdata *pdata = &control->pdata;
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (block < 0)
                return block;
index 8d7d6c01a2f7264905e7a8e29888a417f44fb515..f99b34f7647b092a657fbbc3a70fd01219837351 100644 (file)
@@ -416,7 +416,7 @@ static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        struct wm8996_pdata *pdata = &wm8996->pdata;
        int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (block < 0)
                return block;
index b4dba3a02abafd73044724146601fade748637b4..52d766efe14f0d318844d43bc19df2dcf16bee0d 100644 (file)
@@ -943,7 +943,7 @@ static int wm8997_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        }
 }
 
-#define WM8997_RATES SNDRV_PCM_RATE_8000_192000
+#define WM8997_RATES SNDRV_PCM_RATE_KNOT
 
 #define WM8997_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
index 7719bc509e50b182a0c63b3280154bac4de277fe..012396074a8a6da52d416d5edf10cc092bed16e5 100644 (file)
@@ -1170,7 +1170,7 @@ static const struct snd_soc_dapm_route wm8998_dapm_routes[] = {
        { "DRC1 Signal Activity", NULL, "DRC1R" },
 };
 
-#define WM8998_RATES SNDRV_PCM_RATE_8000_192000
+#define WM8998_RATES SNDRV_PCM_RATE_KNOT
 
 #define WM8998_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
index ccb3b15139ad9dacd41ad801201471d1ed696997..363b3b6676163e8c0b110efd165c5eccd7ec9e1a 100644 (file)
@@ -344,9 +344,9 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol,
 
        reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
        if (reg & WM9081_SPK_MODE)
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
 
        return 0;
 }
@@ -365,7 +365,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
        unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
 
        /* Are we changing anything? */
-       if (ucontrol->value.integer.value[0] ==
+       if (ucontrol->value.enumerated.item[0] ==
            ((reg2 & WM9081_SPK_MODE) != 0))
                return 0;
 
@@ -373,7 +373,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
        if (reg_pwr & WM9081_SPK_ENA)
                return -EINVAL;
 
-       if (ucontrol->value.integer.value[0]) {
+       if (ucontrol->value.enumerated.item[0]) {
                /* Class AB */
                reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
                reg2 |= WM9081_SPK_MODE;
index 79e143625ac3d9c14ca72f96dc11acb6a970efdb..9849643ef8099c7f3340a719cf160c8ce633f9c5 100644 (file)
@@ -1212,7 +1212,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
        if (IS_ERR(wm9713->ac97))
                return PTR_ERR(wm9713->ac97);
 
-       regmap = devm_regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
+       regmap = regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
        if (IS_ERR(regmap)) {
                snd_soc_free_ac97_codec(wm9713->ac97);
                return PTR_ERR(regmap);
index 33806d487b8ae00711dddd4ec400393dbff59b1f..d3b1cb15e7f0766111b6ced6fbe36d65571703aa 100644 (file)
@@ -32,9 +32,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include <linux/mfd/arizona/registers.h>
-
-#include "arizona.h"
 #include "wm_adsp.h"
 
 #define adsp_crit(_dsp, fmt, ...) \
@@ -295,6 +292,8 @@ struct wm_adsp_compr {
 
        u32 *raw_buf;
        unsigned int copied_total;
+
+       unsigned int sample_rate;
 };
 
 #define WM_ADSP_DATA_WORD_SIZE         3
@@ -328,7 +327,7 @@ struct wm_adsp_buffer_region_def {
        unsigned int size_offset;
 };
 
-static struct wm_adsp_buffer_region_def ez2control_regions[] = {
+static const struct wm_adsp_buffer_region_def default_regions[] = {
        {
                .mem_type = WMFW_ADSP2_XM,
                .base_offset = HOST_BUFFER_FIELD(X_buf_base),
@@ -350,10 +349,10 @@ struct wm_adsp_fw_caps {
        u32 id;
        struct snd_codec_desc desc;
        int num_regions;
-       struct wm_adsp_buffer_region_def *region_defs;
+       const struct wm_adsp_buffer_region_def *region_defs;
 };
 
-static const struct wm_adsp_fw_caps ez2control_caps[] = {
+static const struct wm_adsp_fw_caps ctrl_caps[] = {
        {
                .id = SND_AUDIOCODEC_BESPOKE,
                .desc = {
@@ -362,8 +361,26 @@ static const struct wm_adsp_fw_caps ez2control_caps[] = {
                        .num_sample_rates = 1,
                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
                },
-               .num_regions = ARRAY_SIZE(ez2control_regions),
-               .region_defs = ez2control_regions,
+               .num_regions = ARRAY_SIZE(default_regions),
+               .region_defs = default_regions,
+       },
+};
+
+static const struct wm_adsp_fw_caps trace_caps[] = {
+       {
+               .id = SND_AUDIOCODEC_BESPOKE,
+               .desc = {
+                       .max_ch = 8,
+                       .sample_rates = {
+                               4000, 8000, 11025, 12000, 16000, 22050,
+                               24000, 32000, 44100, 48000, 64000, 88200,
+                               96000, 176400, 192000
+                       },
+                       .num_sample_rates = 15,
+                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+               },
+               .num_regions = ARRAY_SIZE(default_regions),
+               .region_defs = default_regions,
        },
 };
 
@@ -382,11 +399,16 @@ static const struct {
        [WM_ADSP_FW_CTRL] =     {
                .file = "ctrl",
                .compr_direction = SND_COMPRESS_CAPTURE,
-               .num_caps = ARRAY_SIZE(ez2control_caps),
-               .caps = ez2control_caps,
+               .num_caps = ARRAY_SIZE(ctrl_caps),
+               .caps = ctrl_caps,
        },
        [WM_ADSP_FW_ASR] =      { .file = "asr" },
-       [WM_ADSP_FW_TRACE] =    { .file = "trace" },
+       [WM_ADSP_FW_TRACE] =    {
+               .file = "trace",
+               .compr_direction = SND_COMPRESS_CAPTURE,
+               .num_caps = ARRAY_SIZE(trace_caps),
+               .caps = trace_caps,
+       },
        [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
        [WM_ADSP_FW_MISC] =     { .file = "misc" },
 };
@@ -586,7 +608,7 @@ static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = dsp[e->shift_l].fw;
+       ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
 
        return 0;
 }
@@ -599,10 +621,10 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
        struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       if (ucontrol->value.integer.value[0] == dsp[e->shift_l].fw)
+       if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
                return 0;
 
-       if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
+       if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
                return -EINVAL;
 
        mutex_lock(&dsp[e->shift_l].pwr_lock);
@@ -610,7 +632,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
        if (dsp[e->shift_l].running || dsp[e->shift_l].compr)
                ret = -EBUSY;
        else
-               dsp[e->shift_l].fw = ucontrol->value.integer.value[0];
+               dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
 
        mutex_unlock(&dsp[e->shift_l].pwr_lock);
 
@@ -719,19 +741,19 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
        reg = ctl->alg_region.base + ctl->offset;
        reg = wm_adsp_region_to_reg(mem, reg);
 
-       scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA);
+       scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
        if (!scratch)
                return -ENOMEM;
 
        ret = regmap_raw_write(dsp->regmap, reg, scratch,
-                              ctl->len);
+                              len);
        if (ret) {
                adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
-                        ctl->len, reg, ret);
+                        len, reg, ret);
                kfree(scratch);
                return ret;
        }
-       adsp_dbg(dsp, "Wrote %zu bytes to %x\n", ctl->len, reg);
+       adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
 
        kfree(scratch);
 
@@ -778,20 +800,20 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
        reg = ctl->alg_region.base + ctl->offset;
        reg = wm_adsp_region_to_reg(mem, reg);
 
-       scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA);
+       scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
        if (!scratch)
                return -ENOMEM;
 
-       ret = regmap_raw_read(dsp->regmap, reg, scratch, ctl->len);
+       ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
        if (ret) {
                adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
-                        ctl->len, reg, ret);
+                        len, reg, ret);
                kfree(scratch);
                return ret;
        }
-       adsp_dbg(dsp, "Read %zu bytes from %x\n", ctl->len, reg);
+       adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
 
-       memcpy(buf, scratch, ctl->len);
+       memcpy(buf, scratch, len);
        kfree(scratch);
 
        return 0;
@@ -855,17 +877,18 @@ static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
                        kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_READ;
                if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
                        kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+       } else {
+               kcontrol->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+               kcontrol->access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
        }
 
-       ret = snd_soc_add_card_controls(dsp->card,
-                                       kcontrol, 1);
+       ret = snd_soc_add_card_controls(dsp->card, kcontrol, 1);
        if (ret < 0)
                goto err_kcontrol;
 
        kfree(kcontrol);
 
-       ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card,
-                                                 ctl->name);
+       ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card, ctl->name);
 
        return 0;
 
@@ -885,9 +908,7 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
                if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
                        continue;
 
-               ret = wm_coeff_read_control(ctl,
-                                           ctl->cache,
-                                           ctl->len);
+               ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
                if (ret < 0)
                        return ret;
        }
@@ -904,9 +925,7 @@ static int wm_coeff_sync_controls(struct wm_adsp *dsp)
                if (!ctl->enabled)
                        continue;
                if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
-                       ret = wm_coeff_write_control(ctl,
-                                                    ctl->cache,
-                                                    ctl->len);
+                       ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
                        if (ret < 0)
                                return ret;
                }
@@ -1502,8 +1521,7 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
 
        ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2);
        if (ret != 0) {
-               adsp_err(dsp, "Failed to read algorithm list: %d\n",
-                       ret);
+               adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
                kfree(alg);
                return ERR_PTR(ret);
        }
@@ -2002,8 +2020,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                                goto err_mutex;
                        }
 
-                       val = (val & dsp->sysclk_mask)
-                               >> dsp->sysclk_shift;
+                       val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
 
                        ret = regmap_update_bits(dsp->regmap,
                                                 dsp->base + ADSP1_CONTROL_31,
@@ -2096,8 +2113,7 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
 
        /* Wait for the RAM to start, should be near instantaneous */
        for (count = 0; count < 10; ++count) {
-               ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
-                                 &val);
+               ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
                if (ret != 0)
                        return ret;
 
@@ -2123,30 +2139,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
                                           struct wm_adsp,
                                           boot_work);
        int ret;
-       unsigned int val;
 
        mutex_lock(&dsp->pwr_lock);
 
-       /*
-        * For simplicity set the DSP clock rate to be the
-        * SYSCLK rate rather than making it configurable.
-        */
-       ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
-       if (ret != 0) {
-               adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
-               goto err_mutex;
-       }
-       val = (val & ARIZONA_SYSCLK_FREQ_MASK)
-               >> ARIZONA_SYSCLK_FREQ_SHIFT;
-
-       ret = regmap_update_bits_async(dsp->regmap,
-                                      dsp->base + ADSP2_CLOCKING,
-                                      ADSP2_CLK_SEL_MASK, val);
-       if (ret != 0) {
-               adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
-               goto err_mutex;
-       }
-
        ret = wm_adsp2_ena(dsp);
        if (ret != 0)
                goto err_mutex;
@@ -2186,8 +2181,21 @@ err_mutex:
        mutex_unlock(&dsp->pwr_lock);
 }
 
+static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
+{
+       int ret;
+
+       ret = regmap_update_bits_async(dsp->regmap,
+                                      dsp->base + ADSP2_CLOCKING,
+                                      ADSP2_CLK_SEL_MASK,
+                                      freq << ADSP2_CLK_SEL_SHIFT);
+       if (ret != 0)
+               adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
+}
+
 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
-                  struct snd_kcontrol *kcontrol, int event)
+                        struct snd_kcontrol *kcontrol, int event,
+                        unsigned int freq)
 {
        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
@@ -2197,6 +2205,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
+               wm_adsp2_set_dspclk(dsp, freq);
                queue_work(system_unbound_wq, &dsp->boot_work);
                break;
        default:
@@ -2471,6 +2480,8 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
        if (!compr->raw_buf)
                return -ENOMEM;
 
+       compr->sample_rate = params->codec.sample_rate;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
@@ -2810,7 +2821,6 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
        mutex_lock(&dsp->pwr_lock);
 
        if (!buf) {
-               adsp_err(dsp, "Spurious buffer IRQ\n");
                ret = -ENODEV;
                goto out;
        }
@@ -2841,7 +2851,7 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
                goto out;
        }
 
-       if (compr->stream)
+       if (compr && compr->stream)
                snd_compr_fragment_elapsed(compr->stream);
 
 out:
@@ -2911,6 +2921,7 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
 
        tstamp->copied_total = compr->copied_total;
        tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
+       tstamp->sampling_rate = compr->sample_rate;
 
 out:
        mutex_unlock(&dsp->pwr_lock);
index 1a928ec547411b6d38bcec2718d2dcc09d1f6cac..b61cb57e600fb6447798e5cf9684c51f641d094e 100644 (file)
@@ -80,7 +80,7 @@ struct wm_adsp {
        SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
                wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
 
-#define WM_ADSP2_E(wname, num, event_fn) \
+#define WM_ADSP2(wname, num, event_fn) \
 {      .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
        .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \
        .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \
@@ -88,9 +88,6 @@ struct wm_adsp {
        .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
        .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
 
-#define WM_ADSP2(wname, num) \
-       WM_ADSP2_E(wname, num, wm_adsp2_early_event)
-
 extern const struct snd_kcontrol_new wm_adsp_fw_controls[];
 
 int wm_adsp1_init(struct wm_adsp *dsp);
@@ -100,7 +97,8 @@ int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec);
 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
-                        struct snd_kcontrol *kcontrol, int event);
+                        struct snd_kcontrol *kcontrol, int event,
+                        unsigned int freq);
 int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
 
index 3736d9aabc563c9b006c9c00a6abea196e3e5daf..50ca291cc225321fb82090c31a5edae523ee9b0d 100644 (file)
@@ -5,7 +5,7 @@ config SND_DAVINCI_SOC
 
 config SND_EDMA_SOC
        tristate "SoC Audio for Texas Instruments chips using eDMA"
-       depends on SOC_AM33XX || SOC_AM43XX || ARCH_DAVINCI
+       depends on TI_EDMA
        select SND_SOC_GENERIC_DMAENGINE_PCM
        help
          Say Y or M here if you want audio support for TI SoC which uses eDMA.
@@ -13,6 +13,7 @@ config SND_EDMA_SOC
          - daVinci devices
          - AM335x
          - AM437x/AM438x
+         - DRA7xx family
 
 config SND_DAVINCI_SOC_I2S
        tristate
index 2ccb8bccc9d4cc4a79c6a94abe4dfb1566872737..e1324989bd6b9a498d35698f9748f5dae14ffe07 100644 (file)
@@ -77,6 +77,7 @@ struct davinci_mcasp {
        u32 fifo_base;
        struct device *dev;
        struct snd_pcm_substream *substreams[2];
+       unsigned int dai_fmt;
 
        /* McASP specific data */
        int     tdm_slots;
@@ -398,6 +399,9 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        bool fs_pol_rising;
        bool inv_fs = false;
 
+       if (!fmt)
+               return 0;
+
        pm_runtime_get_sync(mcasp->dev);
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_A:
@@ -529,6 +533,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
                mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
        }
+
+       mcasp->dai_fmt = fmt;
 out:
        pm_runtime_put(mcasp->dev);
        return ret;
@@ -1026,6 +1032,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        int period_size = params_period_size(params);
        int ret;
 
+       ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt);
+       if (ret)
+               return ret;
+
        /*
         * If mcasp is BCLK master, and a BCLK divider was not provided by
         * the machine driver, we need to calculate the ratio.
@@ -1517,6 +1527,8 @@ static int mcasp_reparent_fck(struct platform_device *pdev)
        if (!parent_name)
                return 0;
 
+       dev_warn(&pdev->dev, "Update the bindings to use assigned-clocks!\n");
+
        gfclk = clk_get(&pdev->dev, "fck");
        if (IS_ERR(gfclk)) {
                dev_err(&pdev->dev, "failed to get fck\n");
index 14dfdee05fd5ae842bebdd0092e47bd4bc88f605..35aabf9dc503b8f4ac78bba4df86343585aaf8fb 100644 (file)
@@ -292,8 +292,8 @@ config SND_SOC_FSL_ASOC_CARD
        select SND_SOC_FSL_SSI
        help
         ALSA SoC Audio support with ASRC feature for Freescale SoCs that have
-        ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888
-        and SGTL5000.
+        ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888,
+        CS4271, CS4272 and SGTL5000.
         Say Y if you want to add support for Freescale Generic ASoC Sound Card.
 
 endif # SND_IMX_SOC
index 562b3bd22d9ac1f86de0a7d08fe64d8145445db8..dffd549a0e2abdc05d0b218669d34ec13f136ee6 100644 (file)
@@ -28,6 +28,8 @@
 #include "../codecs/wm8962.h"
 #include "../codecs/wm8960.h"
 
+#define CS427x_SYSCLK_MCLK 0
+
 #define RX 0
 #define TX 1
 
@@ -99,19 +101,26 @@ struct fsl_asoc_card_priv {
 /**
  * This dapm route map exsits for DPCM link only.
  * The other routes shall go through Device Tree.
+ *
+ * Note: keep all ASRC routes in the second half
+ *      to drop them easily for non-ASRC cases.
  */
 static const struct snd_soc_dapm_route audio_map[] = {
-       {"CPU-Playback",  NULL, "ASRC-Playback"},
+       /* 1st half -- Normal DAPM routes */
        {"Playback",  NULL, "CPU-Playback"},
-       {"ASRC-Capture",  NULL, "CPU-Capture"},
        {"CPU-Capture",  NULL, "Capture"},
+       /* 2nd half -- ASRC DAPM routes */
+       {"CPU-Playback",  NULL, "ASRC-Playback"},
+       {"ASRC-Capture",  NULL, "CPU-Capture"},
 };
 
 static const struct snd_soc_dapm_route audio_map_ac97[] = {
-       {"AC97 Playback",  NULL, "ASRC-Playback"},
+       /* 1st half -- Normal DAPM routes */
        {"Playback",  NULL, "AC97 Playback"},
-       {"ASRC-Capture",  NULL, "AC97 Capture"},
        {"AC97 Capture",  NULL, "Capture"},
+       /* 2nd half -- ASRC DAPM routes */
+       {"AC97 Playback",  NULL, "ASRC-Playback"},
+       {"ASRC-Capture",  NULL, "AC97 Capture"},
 };
 
 /* Add all possible widgets into here without being redundant */
@@ -528,6 +537,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
                priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
                priv->cpu_priv.slot_width = 32;
                priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+       } else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) {
+               codec_dai_name = "cs4271-hifi";
+               priv->codec_priv.mclk_id = CS427x_SYSCLK_MCLK;
+               priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
        } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) {
                codec_dai_name = "sgtl5000";
                priv->codec_priv.mclk_id = SGTL5000_SYSCLK;
@@ -593,6 +606,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
        priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets;
        priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets);
 
+       /* Drop the second half of DAPM routes -- ASRC */
+       if (!asrc_pdev)
+               priv->card.num_dapm_routes /= 2;
+
        memcpy(priv->dai_link, fsl_asoc_card_dai,
               sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
 
@@ -681,6 +698,7 @@ fail:
 static const struct of_device_id fsl_asoc_card_dt_ids[] = {
        { .compatible = "fsl,imx-audio-ac97", },
        { .compatible = "fsl,imx-audio-cs42888", },
+       { .compatible = "fsl,imx-audio-cs427x", },
        { .compatible = "fsl,imx-audio-sgtl5000", },
        { .compatible = "fsl,imx-audio-wm8962", },
        { .compatible = "fsl,imx-audio-wm8960", },
index fef264d27fd3378d726a77209647ccc8098ec6a0..0754df771e3b4c8a945c29e8c3c99f5c23403719 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_address.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
+#include <linux/time.h>
 #include <sound/core.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm_params.h>
@@ -919,7 +920,7 @@ static int fsl_sai_resume(struct device *dev)
        regcache_cache_only(sai->regmap, false);
        regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR);
        regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR);
-       msleep(1);
+       usleep_range(1000, 2000);
        regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
        regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
        return regcache_sync(sai->regmap);
index 0bab76051fd830dd0bc0a3d993341ad8cd759afe..243700cc29e618417d2e3561f6c554031229d531 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
+#include <linux/time.h>
 
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -127,7 +128,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
 
        mutex_unlock(&psc_dma->mutex);
 
-       msleep(1);
+       usleep_range(1000, 2000);
        psc_ac97_warm_reset(ac97);
 }
 
index 7d7c872c280dbd62b0b1b66209e1e1cfe75791ee..b3e6c230045792555fcb7f5a6cab38edd65266d4 100644 (file)
@@ -163,6 +163,7 @@ config SND_SOC_INTEL_SKYLAKE
        tristate
        select SND_HDA_EXT_CORE
        select SND_SOC_TOPOLOGY
+       select SND_HDA_I915
        select SND_SOC_INTEL_SST
 
 config SND_SOC_INTEL_SKL_RT286_MACH
@@ -172,6 +173,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH
        select SND_SOC_INTEL_SKYLAKE
        select SND_SOC_RT286
        select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
        help
           This adds support for ASoC machine driver for Skylake platforms
           with RT286 I2S audio codec.
@@ -186,6 +188,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
        select SND_SOC_NAU8825
        select SND_SOC_SSM4567
        select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
        help
          This adds support for ASoC Onboard Codec I2S machine driver. This will
          create an alsa sound card for NAU88L25 + SSM4567.
@@ -200,6 +203,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
        select SND_SOC_NAU8825
        select SND_SOC_MAX98357A
        select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
        help
          This adds support for ASoC Onboard Codec I2S machine driver. This will
          create an alsa sound card for NAU88L25 + MAX98357A.
index 4fce03fc1870b55ba0a44c4999e266ed19ae7bbf..3bc4b63b2f9daaefe7d135dd2100e1ea94f479b4 100644 (file)
@@ -342,6 +342,10 @@ static struct sst_acpi_mach sst_acpi_chv[] = {
                                                &chv_platform_data },
        {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
                                                &chv_platform_data },
+       /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
+       {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL,
+                                               &chv_platform_data },
+
        {},
 };
 
index 3dc7358828b374a6a4f5e8c5f45f588a1d1daaa5..8afa6fe7b0b0023e7877717bad8bbbcfbcce2ec4 100644 (file)
@@ -318,7 +318,6 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx,
        union ipc_header_high msg_high;
        u32 msg_low;
        struct ipc_dsp_hdr *dsp_hdr;
-       unsigned int cmd_id;
 
        msg_high = msg->mrfld_header.p.header_high;
        msg_low = msg->mrfld_header.p.header_low_payload;
@@ -357,7 +356,6 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx,
                        return;
                /* Copy command id so that we can use to put sst to reset */
                dsp_hdr = (struct ipc_dsp_hdr *)data;
-               cmd_id = dsp_hdr->cmd_id;
                dev_dbg(sst_drv_ctx->dev, "cmd_id %d\n", dsp_hdr->cmd_id);
                if (sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
                                msg_high.part.drv_id,
index 9a1752df45a9feacf7687fdd65d8a276c7c9d9ab..032a2e753f0bfbdbee9814af8dd173bf8be51cf4 100644 (file)
 #include "../atom/sst-atom-controls.h"
 #include "../common/sst-acpi.h"
 
+enum {
+       BYT_RT5640_DMIC1_MAP,
+       BYT_RT5640_DMIC2_MAP,
+       BYT_RT5640_IN1_MAP,
+};
+
+#define BYT_RT5640_MAP(quirk)  ((quirk) & 0xff)
+#define BYT_RT5640_DMIC_EN     BIT(16)
+
+static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
+                                       BYT_RT5640_DMIC_EN;
+
 static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
        SND_SOC_DAPM_HP("Headphone", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
@@ -70,18 +82,6 @@ static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
        {"IN1P", NULL, "Internal Mic"},
 };
 
-enum {
-       BYT_RT5640_DMIC1_MAP,
-       BYT_RT5640_DMIC2_MAP,
-       BYT_RT5640_IN1_MAP,
-};
-
-#define BYT_RT5640_MAP(quirk)  ((quirk) & 0xff)
-#define BYT_RT5640_DMIC_EN     BIT(16)
-
-static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
-                                       BYT_RT5640_DMIC_EN;
-
 static const struct snd_kcontrol_new byt_rt5640_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -174,7 +174,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
                return ret;
        }
 
-       dmi_check_system(byt_rt5640_quirk_table);
        switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
        case BYT_RT5640_IN1_MAP:
                custom_map = byt_rt5640_intmic_in1_map;
@@ -341,15 +340,34 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
 {
        int ret_val = 0;
        struct sst_acpi_mach *mach;
+       const char *i2c_name = NULL;
+       int i;
+       int dai_index;
 
        /* register the soc card */
        byt_rt5640_card.dev = &pdev->dev;
        mach = byt_rt5640_card.dev->platform_data;
 
+       /* fix index of codec dai */
+       dai_index = MERR_DPCM_COMPR + 1;
+       for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
+               if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) {
+                       dai_index = i;
+                       break;
+               }
+       }
+
        /* fixup codec name based on HID */
-       snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
-                "%s%s%s", "i2c-", mach->id, ":00");
-       byt_rt5640_dais[MERR_DPCM_COMPR+1].codec_name = byt_rt5640_codec_name;
+       i2c_name = sst_acpi_find_name_from_hid(mach->id);
+       if (i2c_name != NULL) {
+               snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
+                       "%s%s", "i2c-", i2c_name);
+
+               byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name;
+       }
+
+       /* check quirks before creating card */
+       dmi_check_system(byt_rt5640_quirk_table);
 
        ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
 
index 90588d6e64fc7869a4a4a210b0f188a01e7907b8..e609f089593a935984c101cb6e78fe7a0966e314 100644 (file)
@@ -287,33 +287,20 @@ static struct snd_soc_card snd_soc_card_cht = {
        .num_controls = ARRAY_SIZE(cht_mc_controls),
 };
 
-static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level,
-                                               void *context, void **ret)
-{
-       *(bool *)context = true;
-       return AE_OK;
-}
-
 static int snd_cht_mc_probe(struct platform_device *pdev)
 {
        int ret_val = 0;
-       bool found = false;
        struct cht_mc_private *drv;
 
        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
        if (!drv)
                return -ENOMEM;
 
-       if (ACPI_SUCCESS(acpi_get_devices(
-                                       "104C227E",
-                                       snd_acpi_codec_match,
-                                       &found, NULL)) && found) {
-               drv->ts3a227e_present = true;
-       } else {
+       drv->ts3a227e_present = acpi_dev_present("104C227E");
+       if (!drv->ts3a227e_present) {
                /* no need probe TI jack detection chip */
                snd_soc_card_cht.aux_dev = NULL;
                snd_soc_card_cht.num_aux_devs = 0;
-               drv->ts3a227e_present = false;
        }
 
        /* register the soc card */
index 2d3afddb0a2e8c83fef54b36eed42d7ff6b69878..2a6f80843bc9656b8303a4b9f1d67e4f9b49df45 100644 (file)
@@ -147,6 +147,17 @@ static const struct snd_kcontrol_new cht_mc_controls[] = {
        SOC_DAPM_PIN_SWITCH("Ext Spk"),
 };
 
+static struct snd_soc_jack_pin cht_bsw_jack_pins[] = {
+       {
+               .pin    = "Headphone",
+               .mask   = SND_JACK_HEADPHONE,
+       },
+       {
+               .pin    = "Headset Mic",
+               .mask   = SND_JACK_MICROPHONE,
+       },
+};
+
 static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -202,9 +213,9 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
        else
                jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE;
 
-       ret = snd_soc_card_jack_new(runtime->card, "Headset Jack",
+       ret = snd_soc_card_jack_new(runtime->card, "Headset",
                                    jack_type, &ctx->jack,
-                                   NULL, 0);
+                                   cht_bsw_jack_pins, ARRAY_SIZE(cht_bsw_jack_pins));
        if (ret) {
                dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
                return ret;
@@ -333,20 +344,12 @@ static struct cht_acpi_card snd_soc_cards[] = {
        {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
 };
 
-static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level,
-                                      void *context, void **ret)
-{
-       *(bool *)context = true;
-       return AE_OK;
-}
-
 static int snd_cht_mc_probe(struct platform_device *pdev)
 {
        int ret_val = 0;
        int i;
        struct cht_mc_private *drv;
        struct snd_soc_card *card = snd_soc_cards[0].soc_card;
-       bool found = false;
        char codec_name[16];
 
        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
@@ -354,10 +357,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
-               if (ACPI_SUCCESS(acpi_get_devices(
-                                               snd_soc_cards[i].codec_id,
-                                               snd_acpi_codec_match,
-                                               &found, NULL)) && found) {
+               if (acpi_dev_present(snd_soc_cards[i].codec_id)) {
                        dev_dbg(&pdev->dev,
                                "found codec %s\n", snd_soc_cards[i].codec_id);
                        card = snd_soc_cards[i].soc_card;
@@ -367,8 +367,12 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        }
        card->dev = &pdev->dev;
        sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
+
        /* set correct codec name */
-       strcpy((char *)card->dai_link[2].codec_name, codec_name);
+       for (i = 0; i < ARRAY_SIZE(cht_dailink); i++)
+               if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00"))
+                       card->dai_link[i].codec_name = kstrdup(codec_name, GFP_KERNEL);
+
        snd_soc_card_set_drvdata(card, drv);
        ret_val = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret_val) {
index 49c09a0add797ff95101bee1923b62254e3928a0..34f46c72a0e27cff8cd37108d27b71029cd088c6 100644 (file)
@@ -94,7 +94,7 @@ static const struct soc_enum lo_enum =
 static int headset_get_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = hs_switch;
+       ucontrol->value.enumerated.item[0] = hs_switch;
        return 0;
 }
 
@@ -104,12 +104,12 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        struct snd_soc_dapm_context *dapm = &card->dapm;
 
-       if (ucontrol->value.integer.value[0] == hs_switch)
+       if (ucontrol->value.enumerated.item[0] == hs_switch)
                return 0;
 
        snd_soc_dapm_mutex_lock(dapm);
 
-       if (ucontrol->value.integer.value[0]) {
+       if (ucontrol->value.enumerated.item[0]) {
                pr_debug("hs_set HS path\n");
                snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones");
                snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
@@ -123,7 +123,7 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
 
        snd_soc_dapm_mutex_unlock(dapm);
 
-       hs_switch = ucontrol->value.integer.value[0];
+       hs_switch = ucontrol->value.enumerated.item[0];
 
        return 0;
 }
@@ -148,7 +148,7 @@ static void lo_enable_out_pins(struct snd_soc_dapm_context *dapm)
 static int lo_get_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = lo_dac;
+       ucontrol->value.enumerated.item[0] = lo_dac;
        return 0;
 }
 
@@ -158,7 +158,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        struct snd_soc_dapm_context *dapm = &card->dapm;
 
-       if (ucontrol->value.integer.value[0] == lo_dac)
+       if (ucontrol->value.enumerated.item[0] == lo_dac)
                return 0;
 
        snd_soc_dapm_mutex_lock(dapm);
@@ -168,7 +168,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
         */
        lo_enable_out_pins(dapm);
 
-       switch (ucontrol->value.integer.value[0]) {
+       switch (ucontrol->value.enumerated.item[0]) {
        case 0:
                pr_debug("set vibra path\n");
                snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT");
@@ -202,7 +202,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
 
        snd_soc_dapm_mutex_unlock(dapm);
 
-       lo_dac = ucontrol->value.integer.value[0];
+       lo_dac = ucontrol->value.enumerated.item[0];
        return 0;
 }
 
index ab7da9c304b2049ceec9c06eb53ce25e1a809382..72176b79a18d6c61c02afabdcfab6bf5b3f4f932 100644 (file)
@@ -22,6 +22,7 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include "../../codecs/nau8825.h"
+#include "../../codecs/hdac_hdmi.h"
 
 #define SKL_NUVOTON_CODEC_DAI  "nau8825-hifi"
 #define SKL_MAXIM_CODEC_DAI "HiFi"
 static struct snd_soc_jack skylake_headset;
 static struct snd_soc_card skylake_audio_card;
 
+enum {
+       SKL_DPCM_AUDIO_PB = 0,
+       SKL_DPCM_AUDIO_CP,
+       SKL_DPCM_AUDIO_REF_CP,
+       SKL_DPCM_AUDIO_DMIC_CP,
+       SKL_DPCM_AUDIO_HDMI1_PB,
+       SKL_DPCM_AUDIO_HDMI2_PB,
+       SKL_DPCM_AUDIO_HDMI3_PB,
+};
+
 static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card)
 {
        struct snd_soc_pcm_runtime *rtd;
@@ -87,7 +98,6 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
        SND_SOC_DAPM_SPK("Spk", NULL),
        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-       SND_SOC_DAPM_SINK("WoV Sink"),
        SND_SOC_DAPM_SPK("DP", NULL),
        SND_SOC_DAPM_SPK("HDMI", NULL),
        SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
@@ -107,7 +117,6 @@ static const struct snd_soc_dapm_route skylake_map[] = {
        { "MIC", NULL, "Headset Mic" },
        { "DMic", NULL, "SoC DMIC" },
 
-       {"WoV Sink", NULL, "hwd_in sink"},
        {"HDMI", NULL, "hif5 Output"},
        {"DP", NULL, "hif6 Output"},
 
@@ -124,8 +133,14 @@ static const struct snd_soc_dapm_route skylake_map[] = {
        /* DMIC */
        { "dmic01_hifi", NULL, "DMIC01 Rx" },
        { "DMIC01 Rx", NULL, "DMIC AIF" },
-       { "hifi1", NULL, "iDisp Tx"},
-       { "iDisp Tx", NULL, "iDisp_out"},
+
+       { "hifi3", NULL, "iDisp3 Tx"},
+       { "iDisp3 Tx", NULL, "iDisp3_out"},
+       { "hifi2", NULL, "iDisp2 Tx"},
+       { "iDisp2 Tx", NULL, "iDisp2_out"},
+       { "hifi1", NULL, "iDisp1 Tx"},
+       { "iDisp1 Tx", NULL, "iDisp1_out"},
+
        { "Headphone Jack", NULL, "Platform Clock" },
        { "Headset Mic", NULL, "Platform Clock" },
 };
@@ -171,11 +186,31 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
        nau8825_enable_jack_detect(codec, &skylake_headset);
 
        snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
-       snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
 
        return ret;
 }
 
+static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI1_PB);
+}
+
+static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI2_PB);
+}
+
+static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI3_PB);
+}
+
 static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_dapm_context *dapm;
@@ -318,7 +353,7 @@ static struct snd_soc_ops skylaye_refcap_ops = {
 /* skylake digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link skylake_dais[] = {
        /* Front End DAI links */
-       {
+       [SKL_DPCM_AUDIO_PB] = {
                .name = "Skl Audio Port",
                .stream_name = "Audio",
                .cpu_dai_name = "System Pin",
@@ -333,7 +368,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dpcm_playback = 1,
                .ops = &skylake_nau8825_fe_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_CP] = {
                .name = "Skl Audio Capture Port",
                .stream_name = "Audio Record",
                .cpu_dai_name = "System Pin",
@@ -347,7 +382,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dpcm_capture = 1,
                .ops = &skylake_nau8825_fe_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_REF_CP] = {
                .name = "Skl Audio Reference cap",
                .stream_name = "Wake on Voice",
                .cpu_dai_name = "Reference Pin",
@@ -361,7 +396,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dynamic = 1,
                .ops = &skylaye_refcap_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_DMIC_CP] = {
                .name = "Skl Audio DMIC cap",
                .stream_name = "dmiccap",
                .cpu_dai_name = "DMIC Pin",
@@ -374,15 +409,45 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dynamic = 1,
                .ops = &skylake_dmic_ops,
        },
-       {
-               .name = "Skl HDMI Port",
-               .stream_name = "Hdmi",
-               .cpu_dai_name = "HDMI Pin",
+       [SKL_DPCM_AUDIO_HDMI1_PB] = {
+               .name = "Skl HDMI Port1",
+               .stream_name = "Hdmi1",
+               .cpu_dai_name = "HDMI1 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [SKL_DPCM_AUDIO_HDMI2_PB] = {
+               .name = "Skl HDMI Port2",
+               .stream_name = "Hdmi2",
+               .cpu_dai_name = "HDMI2 Pin",
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .platform_name = "0000:00:1f.3",
                .dpcm_playback = 1,
                .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [SKL_DPCM_AUDIO_HDMI3_PB] = {
+               .name = "Skl HDMI Port3",
+               .stream_name = "Hdmi3",
+               .cpu_dai_name = "HDMI3 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dpcm_playback = 1,
+               .init = NULL,
                .nonatomic = 1,
                .dynamic = 1,
        },
@@ -407,7 +472,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
        {
                /* SSP1 - Codec */
                .name = "SSP1-Codec",
-               .be_id = 0,
+               .be_id = 1,
                .cpu_dai_name = "SSP1 Pin",
                .platform_name = "0000:00:1f.3",
                .no_pcm = 1,
@@ -424,7 +489,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
        },
        {
                .name = "dmic01",
-               .be_id = 1,
+               .be_id = 2,
                .cpu_dai_name = "DMIC01 Pin",
                .codec_name = "dmic-codec",
                .codec_dai_name = "dmic-hifi",
@@ -435,13 +500,36 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .no_pcm = 1,
        },
        {
-               .name = "iDisp",
+               .name = "iDisp1",
                .be_id = 3,
-               .cpu_dai_name = "iDisp Pin",
+               .cpu_dai_name = "iDisp1 Pin",
                .codec_name = "ehdaudio0D2",
                .codec_dai_name = "intel-hdmi-hifi1",
                .platform_name = "0000:00:1f.3",
                .dpcm_playback = 1,
+               .init = skylake_hdmi1_init,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp2",
+               .be_id = 4,
+               .cpu_dai_name = "iDisp2 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi2",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi2_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp3",
+               .be_id = 5,
+               .cpu_dai_name = "iDisp3 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi3",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi3_init,
+               .dpcm_playback = 1,
                .no_pcm = 1,
        },
 };
index c071812f31e5a01ecd899f02024f60a428567e10..5f1ca99ae9b0d03dc51045af7a3489ee3a20b830 100644 (file)
@@ -26,6 +26,7 @@
 #include <sound/jack.h>
 #include <sound/pcm_params.h>
 #include "../../codecs/nau8825.h"
+#include "../../codecs/hdac_hdmi.h"
 
 #define SKL_NUVOTON_CODEC_DAI  "nau8825-hifi"
 #define SKL_SSM_CODEC_DAI      "ssm4567-hifi"
 static struct snd_soc_jack skylake_headset;
 static struct snd_soc_card skylake_audio_card;
 
+enum {
+       SKL_DPCM_AUDIO_PB = 0,
+       SKL_DPCM_AUDIO_CP,
+       SKL_DPCM_AUDIO_REF_CP,
+       SKL_DPCM_AUDIO_DMIC_CP,
+       SKL_DPCM_AUDIO_HDMI1_PB,
+       SKL_DPCM_AUDIO_HDMI2_PB,
+       SKL_DPCM_AUDIO_HDMI3_PB,
+};
+
 static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card)
 {
        struct snd_soc_pcm_runtime *rtd;
@@ -92,7 +103,6 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
        SND_SOC_DAPM_SPK("Left Speaker", NULL),
        SND_SOC_DAPM_SPK("Right Speaker", NULL),
        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-       SND_SOC_DAPM_SINK("WoV Sink"),
        SND_SOC_DAPM_SPK("DP", NULL),
        SND_SOC_DAPM_SPK("HDMI", NULL),
        SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
@@ -113,8 +123,6 @@ static const struct snd_soc_dapm_route skylake_map[] = {
        {"MIC", NULL, "Headset Mic"},
        {"DMic", NULL, "SoC DMIC"},
 
-       {"WoV Sink", NULL, "hwd_in sink"},
-
        {"HDMI", NULL, "hif5 Output"},
        {"DP", NULL, "hif6 Output"},
        /* CODEC BE connections */
@@ -122,6 +130,11 @@ static const struct snd_soc_dapm_route skylake_map[] = {
        { "Right Playback", NULL, "ssp0 Tx"},
        { "ssp0 Tx", NULL, "codec0_out"},
 
+       /* IV feedback path */
+       { "codec0_lp_in", NULL, "ssp0 Rx"},
+       { "ssp0 Rx", NULL, "Left Capture Sense" },
+       { "ssp0 Rx", NULL, "Right Capture Sense" },
+
        { "Playback", NULL, "ssp1 Tx"},
        { "ssp1 Tx", NULL, "codec1_out"},
 
@@ -131,8 +144,14 @@ static const struct snd_soc_dapm_route skylake_map[] = {
        /* DMIC */
        { "dmic01_hifi", NULL, "DMIC01 Rx" },
        { "DMIC01 Rx", NULL, "DMIC AIF" },
-       { "hifi1", NULL, "iDisp Tx"},
-       { "iDisp Tx", NULL, "iDisp_out"},
+
+       { "hifi3", NULL, "iDisp3 Tx"},
+       { "iDisp3 Tx", NULL, "iDisp3_out"},
+       { "hifi2", NULL, "iDisp2 Tx"},
+       { "iDisp2 Tx", NULL, "iDisp2_out"},
+       { "hifi1", NULL, "iDisp1 Tx"},
+       { "iDisp1 Tx", NULL, "iDisp1_out"},
+
        { "Headphone Jack", NULL, "Platform Clock" },
        { "Headset Mic", NULL, "Platform Clock" },
 };
@@ -197,11 +216,32 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
        nau8825_enable_jack_detect(codec, &skylake_headset);
 
        snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
-       snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
 
        return ret;
 }
 
+static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI1_PB);
+}
+
+static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI2_PB);
+}
+
+
+static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI3_PB);
+}
+
 static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_dapm_context *dapm;
@@ -362,7 +402,7 @@ static struct snd_soc_ops skylaye_refcap_ops = {
 /* skylake digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link skylake_dais[] = {
        /* Front End DAI links */
-       {
+       [SKL_DPCM_AUDIO_PB] = {
                .name = "Skl Audio Port",
                .stream_name = "Audio",
                .cpu_dai_name = "System Pin",
@@ -377,7 +417,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dpcm_playback = 1,
                .ops = &skylake_nau8825_fe_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_CP] = {
                .name = "Skl Audio Capture Port",
                .stream_name = "Audio Record",
                .cpu_dai_name = "System Pin",
@@ -391,7 +431,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dpcm_capture = 1,
                .ops = &skylake_nau8825_fe_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_REF_CP] = {
                .name = "Skl Audio Reference cap",
                .stream_name = "Wake on Voice",
                .cpu_dai_name = "Reference Pin",
@@ -405,7 +445,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dynamic = 1,
                .ops = &skylaye_refcap_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_DMIC_CP] = {
                .name = "Skl Audio DMIC cap",
                .stream_name = "dmiccap",
                .cpu_dai_name = "DMIC Pin",
@@ -418,13 +458,43 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .dynamic = 1,
                .ops = &skylake_dmic_ops,
        },
-       {
-               .name = "Skl HDMI Port",
-               .stream_name = "Hdmi",
-               .cpu_dai_name = "HDMI Pin",
+       [SKL_DPCM_AUDIO_HDMI1_PB] = {
+               .name = "Skl HDMI Port1",
+               .stream_name = "Hdmi1",
+               .cpu_dai_name = "HDMI1 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [SKL_DPCM_AUDIO_HDMI2_PB] = {
+               .name = "Skl HDMI Port2",
+               .stream_name = "Hdmi2",
+               .cpu_dai_name = "HDMI2 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [SKL_DPCM_AUDIO_HDMI3_PB] = {
+               .name = "Skl HDMI Port3",
+               .stream_name = "Hdmi3",
+               .cpu_dai_name = "HDMI3 Pin",
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .platform_name = "0000:00:1f.3",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
                .dpcm_playback = 1,
                .init = NULL,
                .nonatomic = 1,
@@ -448,11 +518,12 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .ignore_pmdown_time = 1,
                .be_hw_params_fixup = skylake_ssp_fixup,
                .dpcm_playback = 1,
+               .dpcm_capture = 1,
        },
        {
                /* SSP1 - Codec */
                .name = "SSP1-Codec",
-               .be_id = 0,
+               .be_id = 1,
                .cpu_dai_name = "SSP1 Pin",
                .platform_name = "0000:00:1f.3",
                .no_pcm = 1,
@@ -469,7 +540,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
        },
        {
                .name = "dmic01",
-               .be_id = 1,
+               .be_id = 2,
                .cpu_dai_name = "DMIC01 Pin",
                .codec_name = "dmic-codec",
                .codec_dai_name = "dmic-hifi",
@@ -480,13 +551,36 @@ static struct snd_soc_dai_link skylake_dais[] = {
                .no_pcm = 1,
        },
        {
-               .name = "iDisp",
+               .name = "iDisp1",
                .be_id = 3,
-               .cpu_dai_name = "iDisp Pin",
+               .cpu_dai_name = "iDisp1 Pin",
                .codec_name = "ehdaudio0D2",
                .codec_dai_name = "intel-hdmi-hifi1",
                .platform_name = "0000:00:1f.3",
                .dpcm_playback = 1,
+               .init = skylake_hdmi1_init,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp2",
+               .be_id = 4,
+               .cpu_dai_name = "iDisp2 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi2",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi2_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp3",
+               .be_id = 5,
+               .cpu_dai_name = "iDisp3 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi3",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi3_init,
+               .dpcm_playback = 1,
                .no_pcm = 1,
        },
 };
index 2cbcbe4126611d0d1660d86279329da5bec504b1..2016397a8e755e5cdeb72b26b270c0203aaec4b9 100644 (file)
 #include <sound/jack.h>
 #include <sound/pcm_params.h>
 #include "../../codecs/rt286.h"
+#include "../../codecs/hdac_hdmi.h"
 
 static struct snd_soc_jack skylake_headset;
+
+enum {
+       SKL_DPCM_AUDIO_PB = 0,
+       SKL_DPCM_AUDIO_CP,
+       SKL_DPCM_AUDIO_REF_CP,
+       SKL_DPCM_AUDIO_DMIC_CP,
+       SKL_DPCM_AUDIO_HDMI1_PB,
+       SKL_DPCM_AUDIO_HDMI2_PB,
+       SKL_DPCM_AUDIO_HDMI3_PB,
+};
+
 /* Headset jack detection DAPM pins */
 static struct snd_soc_jack_pin skylake_headset_pins[] = {
        {
@@ -52,7 +64,9 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
        SND_SOC_DAPM_MIC("Mic Jack", NULL),
        SND_SOC_DAPM_MIC("DMIC2", NULL),
        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
-       SND_SOC_DAPM_SINK("WoV Sink"),
+       SND_SOC_DAPM_SPK("HDMI1", NULL),
+       SND_SOC_DAPM_SPK("HDMI2", NULL),
+       SND_SOC_DAPM_SPK("HDMI3", NULL),
 };
 
 static const struct snd_soc_dapm_route skylake_rt286_map[] = {
@@ -70,7 +84,9 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
        {"DMIC1 Pin", NULL, "DMIC2"},
        {"DMic", NULL, "SoC DMIC"},
 
-       {"WoV Sink", NULL, "hwd_in sink"},
+       {"HDMI1", NULL, "hif5 Output"},
+       {"HDMI2", NULL, "hif6 Output"},
+       {"HDMI3", NULL, "hif7 Output"},
 
        /* CODEC BE connections */
        { "AIF1 Playback", NULL, "ssp0 Tx"},
@@ -84,8 +100,12 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
        { "dmic01_hifi", NULL, "DMIC01 Rx" },
        { "DMIC01 Rx", NULL, "DMIC AIF" },
 
-       { "hif1", NULL, "iDisp Tx"},
-       { "iDisp Tx", NULL, "iDisp_out"},
+       { "hifi3", NULL, "iDisp3 Tx"},
+       { "iDisp3 Tx", NULL, "iDisp3_out"},
+       { "hifi2", NULL, "iDisp2 Tx"},
+       { "iDisp2 Tx", NULL, "iDisp2_out"},
+       { "hifi1", NULL, "iDisp1 Tx"},
+       { "iDisp1 Tx", NULL, "iDisp1_out"},
 
 };
 
@@ -116,11 +136,17 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
        rt286_mic_detect(codec, &skylake_headset);
 
        snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
-       snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
 
        return 0;
 }
 
+static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI1_PB + dai->id);
+}
+
 static unsigned int rates[] = {
        48000,
 };
@@ -249,7 +275,7 @@ static struct snd_soc_ops skylake_dmic_ops = {
 /* skylake digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link skylake_rt286_dais[] = {
        /* Front End DAI links */
-       {
+       [SKL_DPCM_AUDIO_PB] = {
                .name = "Skl Audio Port",
                .stream_name = "Audio",
                .cpu_dai_name = "System Pin",
@@ -266,7 +292,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
                .dpcm_playback = 1,
                .ops = &skylake_rt286_fe_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_CP] = {
                .name = "Skl Audio Capture Port",
                .stream_name = "Audio Record",
                .cpu_dai_name = "System Pin",
@@ -282,7 +308,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
                .dpcm_capture = 1,
                .ops = &skylake_rt286_fe_ops,
        },
-       {
+       [SKL_DPCM_AUDIO_REF_CP] = {
                .name = "Skl Audio Reference cap",
                .stream_name = "refcap",
                .cpu_dai_name = "Reference Pin",
@@ -295,7 +321,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
                .nonatomic = 1,
                .dynamic = 1,
        },
-       {
+       [SKL_DPCM_AUDIO_DMIC_CP] = {
                .name = "Skl Audio DMIC cap",
                .stream_name = "dmiccap",
                .cpu_dai_name = "DMIC Pin",
@@ -308,6 +334,42 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
                .dynamic = 1,
                .ops = &skylake_dmic_ops,
        },
+       [SKL_DPCM_AUDIO_HDMI1_PB] = {
+               .name = "Skl HDMI Port1",
+               .stream_name = "Hdmi1",
+               .cpu_dai_name = "HDMI1 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [SKL_DPCM_AUDIO_HDMI2_PB] = {
+               .name = "Skl HDMI Port2",
+               .stream_name = "Hdmi2",
+               .cpu_dai_name = "HDMI2 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [SKL_DPCM_AUDIO_HDMI3_PB] = {
+               .name = "Skl HDMI Port3",
+               .stream_name = "Hdmi3",
+               .cpu_dai_name = "HDMI3 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
 
        /* Back End DAI links */
        {
@@ -341,6 +403,39 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
                .dpcm_capture = 1,
                .no_pcm = 1,
        },
+       {
+               .name = "iDisp1",
+               .be_id = 2,
+               .cpu_dai_name = "iDisp1 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi1",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp2",
+               .be_id = 3,
+               .cpu_dai_name = "iDisp2 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi2",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp3",
+               .be_id = 4,
+               .cpu_dai_name = "iDisp3 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi3",
+               .platform_name = "0000:00:1f.3",
+               .init = skylake_hdmi_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
 };
 
 /* skylake audio machine driver for SPT + RT286S */
index 3ee3b7ab5d037b053e2f862ffbaa19c25b3f8e11..4dcfb7e5ed7099abc8436e4156e2a552c4137f18 100644 (file)
@@ -14,6 +14,9 @@
 
 #include <linux/acpi.h>
 
+/* translation fron HID to I2C name, needed for DAI codec_name */
+const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]);
+
 /* acpi match */
 struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines);
 
index 81aa1ed6420116dce01d6a5f12fbf36fa5bb961b..97dc1ae05e69d60858f78ab1c6702dee629aaadf 100644 (file)
@@ -317,6 +317,7 @@ struct sst_dsp {
        struct skl_cl_dev cl_dev;
        u32 intr_status;
        const struct firmware *fw;
+       struct snd_dma_buffer dmab;
 };
 
 /* Size optimised DRAM/IRAM memcpy */
index 3b4539d21492484ac2ba15cec78a36f4e135aee6..789843307a4950ad503d3cabda82300489d8e8d0 100644 (file)
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  */
-#include <linux/acpi.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
 
 #include "sst-acpi.h"
 
+static acpi_status sst_acpi_find_name(acpi_handle handle, u32 level,
+                                     void *context, void **ret)
+{
+       struct acpi_device *adev;
+       const char *name = NULL;
+
+       if (acpi_bus_get_device(handle, &adev))
+               return AE_OK;
+
+       if (adev->status.present && adev->status.functional) {
+               name = acpi_dev_name(adev);
+               *(const char **)ret = name;
+               return AE_CTRL_TERMINATE;
+       }
+
+       return AE_OK;
+}
+
+const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
+{
+       const char *name = NULL;
+       acpi_status status;
+
+       status = acpi_get_devices(hid, sst_acpi_find_name, NULL,
+                                 (void **)&name);
+
+       if (ACPI_FAILURE(status) || name[0] == '\0')
+               return NULL;
+
+       return name;
+}
+EXPORT_SYMBOL_GPL(sst_acpi_find_name_from_hid);
+
 static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
                                       void *context, void **ret)
 {
+       unsigned long long sta;
+       acpi_status status;
+
        *(bool *)context = true;
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
+               *(bool *)context = false;
+
        return AE_OK;
 }
 
@@ -37,7 +73,6 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
                                                  sst_acpi_mach_match,
                                                  &found, NULL)) && found)
                        return mach;
-
        return NULL;
 }
 EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
index 4629372d7c8e0b728c9ec0467ae34208532fa48b..79c5089b85d6483efab2ffb25b2959bf8210ab5e 100644 (file)
@@ -72,17 +72,47 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable)
        skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask);
 }
 
+static struct skl_dsp_loader_ops skl_get_loader_ops(void)
+{
+       struct skl_dsp_loader_ops loader_ops;
+
+       memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops));
+
+       loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
+       loader_ops.free_dma_buf = skl_free_dma_buf;
+
+       return loader_ops;
+};
+
+static const struct skl_dsp_ops dsp_ops[] = {
+       {
+               .id = 0x9d70,
+               .loader_ops = skl_get_loader_ops,
+               .init = skl_sst_dsp_init,
+               .cleanup = skl_sst_dsp_cleanup
+       },
+};
+
+static int skl_get_dsp_ops(int pci_id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) {
+               if (dsp_ops[i].id == pci_id)
+                       return i;
+       }
+
+       return -EINVAL;
+}
+
 int skl_init_dsp(struct skl *skl)
 {
        void __iomem *mmio_base;
        struct hdac_ext_bus *ebus = &skl->ebus;
        struct hdac_bus *bus = ebus_to_hbus(ebus);
-       int irq = bus->irq;
        struct skl_dsp_loader_ops loader_ops;
-       int ret;
-
-       loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
-       loader_ops.free_dma_buf = skl_free_dma_buf;
+       int irq = bus->irq;
+       int ret, index;
 
        /* enable ppcap interrupt */
        snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true);
@@ -95,8 +125,14 @@ int skl_init_dsp(struct skl *skl)
                return -ENXIO;
        }
 
-       ret = skl_sst_dsp_init(bus->dev, mmio_base, irq,
+       index  = skl_get_dsp_ops(skl->pci->device);
+       if (index  < 0)
+               return -EINVAL;
+
+       loader_ops = dsp_ops[index].loader_ops();
+       ret = dsp_ops[index].init(bus->dev, mmio_base, irq,
                        skl->fw_name, loader_ops, &skl->skl_sst);
+
        if (ret < 0)
                return ret;
 
@@ -106,18 +142,26 @@ int skl_init_dsp(struct skl *skl)
        return ret;
 }
 
-void skl_free_dsp(struct skl *skl)
+int skl_free_dsp(struct skl *skl)
 {
        struct hdac_ext_bus *ebus = &skl->ebus;
        struct hdac_bus *bus = ebus_to_hbus(ebus);
-       struct skl_sst *ctx =  skl->skl_sst;
+       struct skl_sst *ctx = skl->skl_sst;
+       int index;
 
        /* disable  ppcap interrupt */
        snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false);
 
-       skl_sst_dsp_cleanup(bus->dev, ctx);
+       index = skl_get_dsp_ops(skl->pci->device);
+       if (index  < 0)
+               return -EIO;
+
+       dsp_ops[index].cleanup(bus->dev, ctx);
+
        if (ctx->dsp->addr.lpe)
                iounmap(ctx->dsp->addr.lpe);
+
+       return 0;
 }
 
 int skl_suspend_dsp(struct skl *skl)
@@ -238,9 +282,8 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
  * Calculate the gatewat settings required for copier module, type of
  * gateway and index of gateway to use
  */
-static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
-                       struct skl_module_cfg *mconfig,
-                       struct skl_cpr_cfg *cpr_mconfig)
+static u32 skl_get_node_id(struct skl_sst *ctx,
+                       struct skl_module_cfg *mconfig)
 {
        union skl_connector_node_id node_id = {0};
        union skl_ssp_dma_node ssp_node  = {0};
@@ -289,13 +332,24 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
                break;
 
        default:
-               cpr_mconfig->gtw_cfg.node_id = SKL_NON_GATEWAY_CPR_NODE_ID;
+               node_id.val = 0xFFFFFFFF;
+               break;
+       }
+
+       return node_id.val;
+}
+
+static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
+                       struct skl_module_cfg *mconfig,
+                       struct skl_cpr_cfg *cpr_mconfig)
+{
+       cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig);
+
+       if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) {
                cpr_mconfig->cpr_feature_mask = 0;
                return;
        }
 
-       cpr_mconfig->gtw_cfg.node_id = node_id.val;
-
        if (SKL_CONN_SOURCE == mconfig->hw_conn_type)
                cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs;
        else
@@ -307,6 +361,46 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
        skl_copy_copier_caps(mconfig, cpr_mconfig);
 }
 
+#define DMA_CONTROL_ID 5
+
+int skl_dsp_set_dma_control(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
+{
+       struct skl_dma_control *dma_ctrl;
+       struct skl_i2s_config_blob config_blob;
+       struct skl_ipc_large_config_msg msg = {0};
+       int err = 0;
+
+
+       /*
+        * if blob size is same as capablity size, then no dma control
+        * present so return
+        */
+       if (mconfig->formats_config.caps_size == sizeof(config_blob))
+               return 0;
+
+       msg.large_param_id = DMA_CONTROL_ID;
+       msg.param_data_size = sizeof(struct skl_dma_control) +
+                               mconfig->formats_config.caps_size;
+
+       dma_ctrl = kzalloc(msg.param_data_size, GFP_KERNEL);
+       if (dma_ctrl == NULL)
+               return -ENOMEM;
+
+       dma_ctrl->node_id = skl_get_node_id(ctx, mconfig);
+
+       /* size in dwords */
+       dma_ctrl->config_length = sizeof(config_blob) / 4;
+
+       memcpy(dma_ctrl->config_data, mconfig->formats_config.caps,
+                               mconfig->formats_config.caps_size);
+
+       err = skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)dma_ctrl);
+
+       kfree(dma_ctrl);
+
+       return err;
+}
+
 static void skl_setup_out_format(struct skl_sst *ctx,
                        struct skl_module_cfg *mconfig,
                        struct skl_audio_data_format *out_fmt)
index 6e4b21cdb1bd9bff4b6606103bd41629c0ab2b7f..14d1916ea9f843af75622cd50c93dcf5d426fd68 100644 (file)
@@ -145,3 +145,37 @@ struct nhlt_specific_cfg
 
        return NULL;
 }
+
+static void skl_nhlt_trim_space(struct skl *skl)
+{
+       char *s = skl->tplg_name;
+       int cnt;
+       int i;
+
+       cnt = 0;
+       for (i = 0; s[i]; i++) {
+               if (!isspace(s[i]))
+                       s[cnt++] = s[i];
+       }
+
+       s[cnt] = '\0';
+}
+
+int skl_nhlt_update_topology_bin(struct skl *skl)
+{
+       struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
+       struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
+       struct device *dev = bus->dev;
+
+       dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n",
+               nhlt->header.oem_id, nhlt->header.oem_table_id,
+               nhlt->header.oem_revision);
+
+       snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s",
+               skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id,
+               nhlt->header.oem_revision, "-tplg.bin");
+
+       skl_nhlt_trim_space(skl);
+
+       return 0;
+}
index b6e6b61d10ec22349650ee5c1db3074068a180e4..dab0900eef26c13f6f9c8ac85d5f6b6a40cdf35b 100644 (file)
@@ -206,6 +206,23 @@ static int skl_get_format(struct snd_pcm_substream *substream,
        return format_val;
 }
 
+static int skl_be_prepare(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct skl *skl = get_skl_ctx(dai->dev);
+       struct skl_sst *ctx = skl->skl_sst;
+       struct skl_module_cfg *mconfig;
+
+       if ((dai->playback_active > 1) || (dai->capture_active > 1))
+               return 0;
+
+       mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
+       if (mconfig == NULL)
+               return -EINVAL;
+
+       return skl_dsp_set_dma_control(ctx, mconfig);
+}
+
 static int skl_pcm_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
@@ -458,7 +475,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
        struct hdac_ext_stream *link_dev;
        struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct skl_dma_params *dma_params;
+       struct hdac_ext_dma_params *dma_params;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct skl_pipe_params p_params = {0};
 
@@ -470,11 +487,9 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
        snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
 
        /* set the stream tag in the codec dai dma params  */
-       dma_params = (struct skl_dma_params *)
-                       snd_soc_dai_get_dma_data(codec_dai, substream);
+       dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
        if (dma_params)
                dma_params->stream_tag =  hdac_stream(link_dev)->stream_tag;
-       snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params);
 
        p_params.s_fmt = snd_pcm_format_width(params_format(params));
        p_params.ch = params_channels(params);
@@ -588,6 +603,7 @@ static struct snd_soc_dai_ops skl_dmic_dai_ops = {
 
 static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
        .hw_params = skl_be_hw_params,
+       .prepare = skl_be_prepare,
 };
 
 static struct snd_soc_dai_ops skl_link_dai_ops = {
@@ -660,6 +676,51 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
        },
 },
+{
+       .name = "HDMI1 Pin",
+       .ops = &skl_pcm_dai_ops,
+       .playback = {
+               .stream_name = "HDMI1 Playback",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                       SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+                       SNDRV_PCM_FMTBIT_S32_LE,
+       },
+},
+{
+       .name = "HDMI2 Pin",
+       .ops = &skl_pcm_dai_ops,
+       .playback = {
+               .stream_name = "HDMI2 Playback",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                       SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+                       SNDRV_PCM_FMTBIT_S32_LE,
+       },
+},
+{
+       .name = "HDMI3 Pin",
+       .ops = &skl_pcm_dai_ops,
+       .playback = {
+               .stream_name = "HDMI3 Playback",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                       SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
+                       SNDRV_PCM_FMTBIT_S32_LE,
+       },
+},
 
 /* BE CPU  Dais */
 {
@@ -699,14 +760,41 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
        },
 },
 {
-       .name = "iDisp Pin",
+       .name = "iDisp1 Pin",
        .ops = &skl_link_dai_ops,
        .playback = {
-               .stream_name = "iDisp Tx",
+               .stream_name = "iDisp1 Tx",
                .channels_min = HDA_STEREO,
                .channels_max = HDA_STEREO,
                .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE,
+       },
+},
+{
+       .name = "iDisp2 Pin",
+       .ops = &skl_link_dai_ops,
+       .playback = {
+               .stream_name = "iDisp2 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
+                       SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE,
+       },
+},
+{
+       .name = "iDisp3 Pin",
+       .ops = &skl_link_dai_ops,
+       .playback = {
+               .stream_name = "iDisp3 Tx",
+               .channels_min = HDA_STEREO,
+               .channels_max = HDA_STEREO,
+               .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
+                       SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S24_LE,
        },
 },
 {
@@ -863,7 +951,9 @@ static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus,
                else
                        delay += hstream->bufsize;
        }
-       delay = (hstream->bufsize == delay) ? 0 : delay;
+
+       if (hstream->bufsize == delay)
+               delay = 0;
 
        if (delay >= hstream->period_bytes) {
                dev_info(bus->dev,
index 1bfb7f63b5724d98e8acf1446364fafec01e115f..a5267e8a96e0533bd8671f595f35ce53268b0a7e 100644 (file)
@@ -34,7 +34,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
        mutex_unlock(&ctx->mutex);
 }
 
-static int skl_dsp_core_set_reset_state(struct sst_dsp  *ctx)
+static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
 {
        int ret;
 
@@ -60,7 +60,7 @@ static int skl_dsp_core_set_reset_state(struct sst_dsp  *ctx)
        return ret;
 }
 
-static int skl_dsp_core_unset_reset_state(struct sst_dsp  *ctx)
+static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
 {
        int ret;
 
@@ -87,7 +87,7 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp  *ctx)
        return ret;
 }
 
-static bool is_skl_dsp_core_enable(struct sst_dsp  *ctx)
+static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
 {
        int val;
        bool is_enable;
@@ -140,7 +140,7 @@ static int skl_dsp_start_core(struct sst_dsp *ctx)
        return ret;
 }
 
-static int skl_dsp_core_power_up(struct sst_dsp  *ctx)
+static int skl_dsp_core_power_up(struct sst_dsp *ctx)
 {
        int ret;
 
@@ -166,7 +166,7 @@ static int skl_dsp_core_power_up(struct sst_dsp  *ctx)
        return ret;
 }
 
-static int skl_dsp_core_power_down(struct sst_dsp  *ctx)
+static int skl_dsp_core_power_down(struct sst_dsp *ctx)
 {
        /* update bits */
        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
@@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp  *ctx)
                        "Power down");
 }
 
-static int skl_dsp_enable_core(struct sst_dsp  *ctx)
+int skl_dsp_enable_core(struct sst_dsp *ctx)
 {
        int ret;
 
@@ -195,7 +195,7 @@ static int skl_dsp_enable_core(struct sst_dsp  *ctx)
        return skl_dsp_start_core(ctx);
 }
 
-int skl_dsp_disable_core(struct sst_dsp  *ctx)
+int skl_dsp_disable_core(struct sst_dsp *ctx)
 {
        int ret;
 
index cbb40751c37e297227edff2a9f411df2ec998c53..b6e310d49dd682c239dcfcbeacebe875b365de40 100644 (file)
@@ -53,6 +53,10 @@ struct sst_dsp_device;
 /* HIPCT */
 #define SKL_ADSP_REG_HIPCT_BUSY                BIT(31)
 
+/* FW base IDs */
+#define SKL_INSTANCE_ID                        0
+#define SKL_BASE_FW_MODULE_ID          0
+
 /* Intel HD Audio SRAM Window 1 */
 #define SKL_ADSP_SRAM1_BASE            0xA000
 
@@ -144,7 +148,8 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
 void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state);
 struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
                struct sst_dsp_device *sst_dev, int irq);
-int skl_dsp_disable_core(struct sst_dsp  *ctx);
+int skl_dsp_enable_core(struct sst_dsp *ctx);
+int skl_dsp_disable_core(struct sst_dsp *ctx);
 bool is_skl_dsp_running(struct sst_dsp *ctx);
 irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
 int skl_dsp_wake(struct sst_dsp *ctx);
index e26f4746afb7e58a306ea453da996c77571a5431..348a734f8e24258a1782392a4d324b3b2a6dc794 100644 (file)
@@ -35,9 +35,6 @@
 #define SKL_ADSP_FW_STATUS     SKL_ADSP_SRAM0_BASE
 #define SKL_ADSP_ERROR_CODE    (SKL_ADSP_FW_STATUS + 0x4)
 
-#define SKL_INSTANCE_ID                0
-#define SKL_BASE_FW_MODULE_ID  0
-
 #define SKL_NUM_MODULES                1
 
 static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
index a294fee431f07363f965a81b4c9ef42eb3a42f58..545b4e77b8aaeaaaa72662d1953281e0d3440c7a 100644 (file)
@@ -260,6 +260,65 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
                                multiplier;
 }
 
+static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
+                                               struct skl_sst *ctx)
+{
+       struct skl_module_cfg *m_cfg = w->priv;
+       int link_type, dir;
+       u32 ch, s_freq, s_fmt;
+       struct nhlt_specific_cfg *cfg;
+       struct skl *skl = get_skl_ctx(ctx->dev);
+
+       /* check if we already have blob */
+       if (m_cfg->formats_config.caps_size > 0)
+               return 0;
+
+       dev_dbg(ctx->dev, "Applying default cfg blob\n");
+       switch (m_cfg->dev_type) {
+       case SKL_DEVICE_DMIC:
+               link_type = NHLT_LINK_DMIC;
+               dir = SNDRV_PCM_STREAM_CAPTURE;
+               s_freq = m_cfg->in_fmt[0].s_freq;
+               s_fmt = m_cfg->in_fmt[0].bit_depth;
+               ch = m_cfg->in_fmt[0].channels;
+               break;
+
+       case SKL_DEVICE_I2S:
+               link_type = NHLT_LINK_SSP;
+               if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) {
+                       dir = SNDRV_PCM_STREAM_PLAYBACK;
+                       s_freq = m_cfg->out_fmt[0].s_freq;
+                       s_fmt = m_cfg->out_fmt[0].bit_depth;
+                       ch = m_cfg->out_fmt[0].channels;
+               } else {
+                       dir = SNDRV_PCM_STREAM_CAPTURE;
+                       s_freq = m_cfg->in_fmt[0].s_freq;
+                       s_fmt = m_cfg->in_fmt[0].bit_depth;
+                       ch = m_cfg->in_fmt[0].channels;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* update the blob based on virtual bus_id and default params */
+       cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
+                                       s_fmt, ch, s_freq, dir);
+       if (cfg) {
+               m_cfg->formats_config.caps_size = cfg->size;
+               m_cfg->formats_config.caps = (u32 *) &cfg->caps;
+       } else {
+               dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n",
+                                       m_cfg->vbus_id, link_type, dir);
+               dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n",
+                                       ch, s_freq, s_fmt);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w,
                                                        struct skl_sst *ctx)
 {
@@ -433,6 +492,9 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
                                return ret;
                }
 
+               /* update blob if blob is null for be with default value */
+               skl_tplg_update_be_blob(w, ctx);
+
                /*
                 * apply fix/conversion to module params based on
                 * FE/BE params
@@ -545,6 +607,66 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+/*
+ * Some modules require params to be set after the module is bound to
+ * all pins connected.
+ *
+ * The module provider initializes set_param flag for such modules and we
+ * send params after binding
+ */
+static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
+                       struct skl_module_cfg *mcfg, struct skl_sst *ctx)
+{
+       int i, ret;
+       struct skl_module_cfg *mconfig = w->priv;
+       const struct snd_kcontrol_new *k;
+       struct soc_bytes_ext *sb;
+       struct skl_algo_data *bc;
+       struct skl_specific_cfg *sp_cfg;
+
+       /*
+        * check all out/in pins are in bind state.
+        * if so set the module param
+        */
+       for (i = 0; i < mcfg->max_out_queue; i++) {
+               if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE)
+                       return 0;
+       }
+
+       for (i = 0; i < mcfg->max_in_queue; i++) {
+               if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE)
+                       return 0;
+       }
+
+       if (mconfig->formats_config.caps_size > 0 &&
+               mconfig->formats_config.set_params == SKL_PARAM_BIND) {
+               sp_cfg = &mconfig->formats_config;
+               ret = skl_set_module_params(ctx, sp_cfg->caps,
+                                       sp_cfg->caps_size,
+                                       sp_cfg->param_id, mconfig);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 0; i < w->num_kcontrols; i++) {
+               k = &w->kcontrol_news[i];
+               if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+                       sb = (void *) k->private_value;
+                       bc = (struct skl_algo_data *)sb->dobj.private;
+
+                       if (bc->set_params == SKL_PARAM_BIND) {
+                               ret = skl_set_module_params(ctx,
+                                               (u32 *)bc->params, bc->max,
+                                               bc->param_id, mconfig);
+                               if (ret < 0)
+                                       return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
                                struct skl *skl,
                                struct snd_soc_dapm_widget *src_w,
@@ -579,11 +701,19 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
                        sink = p->sink;
                        sink_mconfig = sink->priv;
 
+                       if (src_mconfig->m_state == SKL_MODULE_UNINIT ||
+                               sink_mconfig->m_state == SKL_MODULE_UNINIT)
+                               continue;
+
                        /* Bind source to sink, mixin is always source */
                        ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig);
                        if (ret)
                                return ret;
 
+                       /* set module params after bind */
+                       skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx);
+                       skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
+
                        /* Start sinks pipe first */
                        if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
                                if (sink_mconfig->pipe->conn_type !=
@@ -714,6 +844,10 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
                if (ret)
                        return ret;
 
+               /* set module params after bind */
+               skl_tplg_set_module_bind_params(source, src_mconfig, ctx);
+               skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
+
                if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
                        ret = skl_run_pipe(ctx, sink_mconfig->pipe);
        }
@@ -978,7 +1112,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
                                return -EFAULT;
                } else {
                        if (copy_from_user(ac->params,
-                                          data + 2 * sizeof(u32), size))
+                                          data + 2, size))
                                return -EFAULT;
                }
 
@@ -1091,6 +1225,66 @@ skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream)
        return NULL;
 }
 
+static struct skl_module_cfg *skl_get_mconfig_pb_cpr(
+               struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
+{
+       struct snd_soc_dapm_path *p;
+       struct skl_module_cfg *mconfig = NULL;
+
+       snd_soc_dapm_widget_for_each_source_path(w, p) {
+               if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) {
+                       if (p->connect &&
+                                   (p->sink->id == snd_soc_dapm_aif_out) &&
+                                   p->source->priv) {
+                               mconfig = p->source->priv;
+                               return mconfig;
+                       }
+                       mconfig = skl_get_mconfig_pb_cpr(dai, p->source);
+                       if (mconfig)
+                               return mconfig;
+               }
+       }
+       return mconfig;
+}
+
+static struct skl_module_cfg *skl_get_mconfig_cap_cpr(
+               struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
+{
+       struct snd_soc_dapm_path *p;
+       struct skl_module_cfg *mconfig = NULL;
+
+       snd_soc_dapm_widget_for_each_sink_path(w, p) {
+               if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) {
+                       if (p->connect &&
+                                   (p->source->id == snd_soc_dapm_aif_in) &&
+                                   p->sink->priv) {
+                               mconfig = p->sink->priv;
+                               return mconfig;
+                       }
+                       mconfig = skl_get_mconfig_cap_cpr(dai, p->sink);
+                       if (mconfig)
+                               return mconfig;
+               }
+       }
+       return mconfig;
+}
+
+struct skl_module_cfg *
+skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream)
+{
+       struct snd_soc_dapm_widget *w;
+       struct skl_module_cfg *mconfig;
+
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               w = dai->playback_widget;
+               mconfig = skl_get_mconfig_pb_cpr(dai, w);
+       } else {
+               w = dai->capture_widget;
+               mconfig = skl_get_mconfig_cap_cpr(dai, w);
+       }
+       return mconfig;
+}
+
 static u8 skl_tplg_be_link_type(int dev_type)
 {
        int ret;
@@ -1464,8 +1658,7 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
                if (!ac->params)
                        return -ENOMEM;
 
-               if (dfw_ac->params)
-                       memcpy(ac->params, dfw_ac->params, ac->max);
+               memcpy(ac->params, dfw_ac->params, ac->max);
        }
 
        be->dobj.private  = ac;
@@ -1523,11 +1716,16 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
        struct hdac_bus *bus = ebus_to_hbus(ebus);
        struct skl *skl = ebus_to_skl(ebus);
 
-       ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
+       ret = request_firmware(&fw, skl->tplg_name, bus->dev);
        if (ret < 0) {
                dev_err(bus->dev, "tplg fw %s load failed with %d\n",
-                               "dfw_sst.bin", ret);
-               return ret;
+                               skl->tplg_name, ret);
+               ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
+               if (ret < 0) {
+                       dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n",
+                                       "dfw_sst.bin", ret);
+                       return ret;
+               }
        }
 
        /*
index 9aa2a2b6598a3ede5dff38f0570c5b16e30bcb70..de3c401284d9df312b13d8a1549f274a08f5a754 100644 (file)
@@ -113,6 +113,29 @@ struct skl_cpr_gtw_cfg {
        u32 config_data[1];
 } __packed;
 
+struct skl_i2s_config_blob {
+       u32 gateway_attrib;
+       u32 tdm_ts_group[8];
+       u32 ssc0;
+       u32 ssc1;
+       u32 sscto;
+       u32 sspsp;
+       u32 sstsa;
+       u32 ssrsa;
+       u32 ssc2;
+       u32 sspsp2;
+       u32 ssc3;
+       u32 ssioc;
+       u32 mdivc;
+       u32 mdivr;
+} __packed;
+
+struct skl_dma_control {
+       u32 node_id;
+       u32 config_length;
+       u32 config_data[1];
+} __packed;
+
 struct skl_cpr_cfg {
        struct skl_base_cfg base_cfg;
        struct skl_audio_data_format out_fmt;
@@ -313,6 +336,8 @@ static inline struct skl *get_skl_ctx(struct device *dev)
 
 int skl_tplg_be_update_params(struct snd_soc_dai *dai,
        struct skl_pipe_params *params);
+int skl_dsp_set_dma_control(struct skl_sst *ctx,
+               struct skl_module_cfg *mconfig);
 void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai,
        struct skl_pipe_params *params, int stream);
 int skl_tplg_init(struct snd_soc_platform *platform,
@@ -345,5 +370,7 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size,
 int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size,
                          u32 param_id, struct skl_module_cfg *mcfg);
 
+struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai,
+                                                               int stream);
 enum skl_bitdepth skl_get_bit_depth(int params);
 #endif
index c9ae010b3cc8dc1df5a359a67987a44186e588cc..1db88a63ac1787f6862d62b53a141481dbb60cb8 100644 (file)
@@ -144,7 +144,8 @@ enum module_pin_type {
 enum skl_module_param_type {
        SKL_PARAM_DEFAULT = 0,
        SKL_PARAM_INIT,
-       SKL_PARAM_SET
+       SKL_PARAM_SET,
+       SKL_PARAM_BIND
 };
 
 struct skl_dfw_module_pin {
index 092705e73db497fb1d75c1c9b45a3c2aaaa34507..ab5e25aaeee38f1284701873946a81d48163fd23 100644 (file)
@@ -28,6 +28,9 @@
 #include <linux/firmware.h>
 #include <sound/pcm.h>
 #include "../common/sst-acpi.h"
+#include <sound/hda_register.h>
+#include <sound/hdaudio.h>
+#include <sound/hda_i915.h>
 #include "skl.h"
 #include "skl-sst-dsp.h"
 #include "skl-sst-ipc.h"
@@ -243,6 +246,16 @@ static int skl_resume(struct device *dev)
        struct hdac_bus *bus = ebus_to_hbus(ebus);
        int ret;
 
+       /* Turned OFF in HDMI codec driver after codec reconfiguration */
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               ret = snd_hdac_display_power(bus, true);
+               if (ret < 0) {
+                       dev_err(bus->dev,
+                               "Cannot turn on display power on i915\n");
+                       return ret;
+               }
+       }
+
        /*
         * resume only when we are not in suspend active, otherwise need to
         * restore the device
@@ -481,6 +494,27 @@ static int skl_create(struct pci_dev *pci,
        return 0;
 }
 
+static int skl_i915_init(struct hdac_bus *bus)
+{
+       int err;
+
+       /*
+        * The HDMI codec is in GPU so we need to ensure that it is powered
+        * up and ready for probe
+        */
+       err = snd_hdac_i915_init(bus);
+       if (err < 0)
+               return err;
+
+       err = snd_hdac_display_power(bus, true);
+       if (err < 0) {
+               dev_err(bus->dev, "Cannot turn on display power on i915\n");
+               return err;
+       }
+
+       return err;
+}
+
 static int skl_first_init(struct hdac_ext_bus *ebus)
 {
        struct skl *skl = ebus_to_skl(ebus);
@@ -543,6 +577,12 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
        /* initialize chip */
        skl_init_pci(skl);
 
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = skl_i915_init(bus);
+               if (err < 0)
+                       return err;
+       }
+
        skl_init_chip(bus, true);
 
        /* codec detection */
@@ -573,11 +613,15 @@ static int skl_probe(struct pci_dev *pci,
        if (err < 0)
                goto out_free;
 
+       skl->pci_id = pci->device;
+
        skl->nhlt = skl_nhlt_init(bus->dev);
 
        if (skl->nhlt == NULL)
                goto out_free;
 
+       skl_nhlt_update_topology_bin(skl);
+
        pci_set_drvdata(skl->pci, ebus);
 
        /* check if dsp is there */
@@ -613,6 +657,14 @@ static int skl_probe(struct pci_dev *pci,
        if (err < 0)
                goto out_unregister;
 
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = snd_hdac_display_power(bus, false);
+               if (err < 0) {
+                       dev_err(bus->dev, "Cannot turn off display power on i915\n");
+                       return err;
+               }
+       }
+
        /*configure PM */
        pm_runtime_put_noidle(bus->dev);
        pm_runtime_allow(bus->dev);
@@ -634,6 +686,31 @@ out_free:
        return err;
 }
 
+static void skl_shutdown(struct pci_dev *pci)
+{
+       struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct hdac_stream *s;
+       struct hdac_ext_stream *stream;
+       struct skl *skl;
+
+       if (ebus == NULL)
+               return;
+
+       skl = ebus_to_skl(ebus);
+
+       if (skl->init_failed)
+               return;
+
+       snd_hdac_ext_stop_streams(ebus);
+       list_for_each_entry(s, &bus->stream_list, list) {
+               stream = stream_to_hdac_ext_stream(s);
+               snd_hdac_ext_stream_decouple(ebus, stream, false);
+       }
+
+       snd_hdac_bus_stop_chip(bus);
+}
+
 static void skl_remove(struct pci_dev *pci)
 {
        struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
@@ -642,6 +719,9 @@ static void skl_remove(struct pci_dev *pci)
        if (skl->tplg)
                release_firmware(skl->tplg);
 
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+               snd_hdac_i915_exit(&ebus->bus);
+
        if (pci_dev_run_wake(pci))
                pm_runtime_get_noresume(&pci->dev);
        pci_dev_put(pci);
@@ -662,11 +742,18 @@ static struct sst_acpi_mach sst_skl_devdata[] = {
        {}
 };
 
+static struct sst_acpi_mach sst_bxtp_devdata[] = {
+       { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
+};
+
 /* PCI IDs */
 static const struct pci_device_id skl_ids[] = {
        /* Sunrise Point-LP */
        { PCI_DEVICE(0x8086, 0x9d70),
                .driver_data = (unsigned long)&sst_skl_devdata},
+       /* BXT-P */
+       { PCI_DEVICE(0x8086, 0x5a98),
+               .driver_data = (unsigned long)&sst_bxtp_devdata},
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, skl_ids);
@@ -677,6 +764,7 @@ static struct pci_driver skl_driver = {
        .id_table = skl_ids,
        .probe = skl_probe,
        .remove = skl_remove,
+       .shutdown = skl_shutdown,
        .driver = {
                .pm = &skl_pm,
        },
index 4d18293b5537e78b286921bddcedb5b18407b5ee..39e16fa7a92b1a6921d8032ed279e88319061a4e 100644 (file)
@@ -73,6 +73,8 @@ struct skl {
        struct list_head ppl_list;
 
        const char *fw_name;
+       char tplg_name[64];
+       unsigned short pci_id;
        const struct firmware *tplg;
 
        int supend_active;
@@ -88,6 +90,16 @@ struct skl_dma_params {
        u8 stream_tag;
 };
 
+struct skl_dsp_ops {
+       int id;
+       struct skl_dsp_loader_ops (*loader_ops)(void);
+       int (*init)(struct device *dev, void __iomem *mmio_base,
+                       int irq, const char *fw_name,
+                       struct skl_dsp_loader_ops loader_ops,
+                       struct skl_sst **skl_sst);
+       void (*cleanup)(struct device *dev, struct skl_sst *ctx);
+};
+
 int skl_platform_unregister(struct device *dev);
 int skl_platform_register(struct device *dev);
 
@@ -96,8 +108,9 @@ void skl_nhlt_free(void *addr);
 struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
                        u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);
 
+int skl_nhlt_update_topology_bin(struct skl *skl);
 int skl_init_dsp(struct skl *skl);
-void skl_free_dsp(struct skl *skl);
+int skl_free_dsp(struct skl *skl);
 int skl_suspend_dsp(struct skl *skl);
 int skl_resume_dsp(struct skl *skl);
 #endif /* __SOUND_SOC_SKL_H */
index 9769676753878b833513d0e863dab776bdaae635..f7e789e97fbca5fcefafb4c7fa061b0dfd3ef6c8 100644 (file)
@@ -17,6 +17,27 @@ config SND_SOC_MT8173_MAX98090
          Select Y if you have such device.
          If unsure select "N".
 
+config SND_SOC_MT8173_RT5650
+       tristate "ASoC Audio driver for MT8173 with RT5650 codec"
+       depends on SND_SOC_MEDIATEK && I2C
+       select SND_SOC_RT5645
+       help
+         This adds ASoC driver for Mediatek MT8173 boards
+         with the RT5650 audio codec.
+         Select Y if you have such device.
+         If unsure select "N".
+
+config SND_SOC_MT8173_RT5650_RT5514
+       tristate "ASoC Audio driver for MT8173 with RT5650 RT5514 codecs"
+       depends on SND_SOC_MEDIATEK && I2C
+       select SND_SOC_RT5645
+       select SND_SOC_RT5514
+       help
+         This adds ASoC driver for Mediatek MT8173 boards
+         with the RT5650 and RT5514 codecs.
+         Select Y if you have such device.
+         If unsure select "N".
+
 config SND_SOC_MT8173_RT5650_RT5676
        tristate "ASoC Audio driver for MT8173 with RT5650 RT5676 codecs"
        depends on SND_SOC_MEDIATEK && I2C
@@ -27,4 +48,3 @@ config SND_SOC_MT8173_RT5650_RT5676
          with the RT5650 and RT5676 codecs.
          Select Y if you have such device.
          If unsure select "N".
-
index 75effbec438d4ebbcc9b6551755c5c171b169477..d486860c0a88e832f44b78f02d1579b550844d0b 100644 (file)
@@ -2,4 +2,6 @@
 obj-$(CONFIG_SND_SOC_MEDIATEK) += mtk-afe-pcm.o
 # Machine support
 obj-$(CONFIG_SND_SOC_MT8173_MAX98090) += mt8173-max98090.o
+obj-$(CONFIG_SND_SOC_MT8173_RT5650) += mt8173-rt5650.o
+obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5514) += mt8173-rt5650-rt5514.o
 obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5676) += mt8173-rt5650-rt5676.o
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173-rt5650-rt5514.c
new file mode 100644 (file)
index 0000000..58e0836
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * mt8173-rt5650-rt5514.c  --  MT8173 machine driver with RT5650/5514 codecs
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Koro Chen <koro.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include "../codecs/rt5645.h"
+
+#define MCLK_FOR_CODECS                12288000
+
+static const struct snd_soc_dapm_widget mt8173_rt5650_rt5514_widgets[] = {
+       SND_SOC_DAPM_SPK("Speaker", NULL),
+       SND_SOC_DAPM_MIC("Int Mic", NULL),
+       SND_SOC_DAPM_HP("Headphone", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mt8173_rt5650_rt5514_routes[] = {
+       {"Speaker", NULL, "SPOL"},
+       {"Speaker", NULL, "SPOR"},
+       {"Sub DMIC1L", NULL, "Int Mic"},
+       {"Sub DMIC1R", NULL, "Int Mic"},
+       {"Headphone", NULL, "HPOL"},
+       {"Headphone", NULL, "HPOR"},
+       {"Headset Mic", NULL, "micbias1"},
+       {"Headset Mic", NULL, "micbias2"},
+       {"IN1P", NULL, "Headset Mic"},
+       {"IN1N", NULL, "Headset Mic"},
+};
+
+static const struct snd_kcontrol_new mt8173_rt5650_rt5514_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Speaker"),
+       SOC_DAPM_PIN_SWITCH("Int Mic"),
+       SOC_DAPM_PIN_SWITCH("Headphone"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream,
+                                         struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int i, ret;
+
+       for (i = 0; i < rtd->num_codecs; i++) {
+               struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+
+               /* pll from mclk 12.288M */
+               ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS,
+                                         params_rate(params) * 512);
+               if (ret)
+                       return ret;
+
+               /* sysclk from pll */
+               ret = snd_soc_dai_set_sysclk(codec_dai, 1,
+                                            params_rate(params) * 512,
+                                            SND_SOC_CLOCK_IN);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static struct snd_soc_ops mt8173_rt5650_rt5514_ops = {
+       .hw_params = mt8173_rt5650_rt5514_hw_params,
+};
+
+static struct snd_soc_jack mt8173_rt5650_rt5514_jack;
+
+static int mt8173_rt5650_rt5514_init(struct snd_soc_pcm_runtime *runtime)
+{
+       struct snd_soc_card *card = runtime->card;
+       struct snd_soc_codec *codec = runtime->codec_dais[0]->codec;
+       int ret;
+
+       rt5645_sel_asrc_clk_src(codec,
+                               RT5645_DA_STEREO_FILTER |
+                               RT5645_AD_STEREO_FILTER,
+                               RT5645_CLK_SEL_I2S1_ASRC);
+
+       /* enable jack detection */
+       ret = snd_soc_card_jack_new(card, "Headset Jack",
+                                   SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
+                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                                   SND_JACK_BTN_2 | SND_JACK_BTN_3,
+                                   &mt8173_rt5650_rt5514_jack, NULL, 0);
+       if (ret) {
+               dev_err(card->dev, "Can't new Headset Jack %d\n", ret);
+               return ret;
+       }
+
+       return rt5645_set_jack_detect(codec,
+                                     &mt8173_rt5650_rt5514_jack,
+                                     &mt8173_rt5650_rt5514_jack,
+                                     &mt8173_rt5650_rt5514_jack);
+}
+
+static struct snd_soc_dai_link_component mt8173_rt5650_rt5514_codecs[] = {
+       {
+               .dai_name = "rt5645-aif1",
+       },
+       {
+               .dai_name = "rt5514-aif1",
+       },
+};
+
+enum {
+       DAI_LINK_PLAYBACK,
+       DAI_LINK_CAPTURE,
+       DAI_LINK_CODEC_I2S,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = {
+       /* Front End DAI links */
+       [DAI_LINK_PLAYBACK] = {
+               .name = "rt5650_rt5514 Playback",
+               .stream_name = "rt5650_rt5514 Playback",
+               .cpu_dai_name = "DL1",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dynamic = 1,
+               .dpcm_playback = 1,
+       },
+       [DAI_LINK_CAPTURE] = {
+               .name = "rt5650_rt5514 Capture",
+               .stream_name = "rt5650_rt5514 Capture",
+               .cpu_dai_name = "VUL",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dynamic = 1,
+               .dpcm_capture = 1,
+       },
+       /* Back End DAI links */
+       [DAI_LINK_CODEC_I2S] = {
+               .name = "Codec",
+               .cpu_dai_name = "I2S",
+               .no_pcm = 1,
+               .codecs = mt8173_rt5650_rt5514_codecs,
+               .num_codecs = 2,
+               .init = mt8173_rt5650_rt5514_init,
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBS_CFS,
+               .ops = &mt8173_rt5650_rt5514_ops,
+               .ignore_pmdown_time = 1,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+       },
+};
+
+static struct snd_soc_codec_conf mt8173_rt5650_rt5514_codec_conf[] = {
+       {
+               .name_prefix = "Sub",
+       },
+};
+
+static struct snd_soc_card mt8173_rt5650_rt5514_card = {
+       .name = "mtk-rt5650-rt5514",
+       .owner = THIS_MODULE,
+       .dai_link = mt8173_rt5650_rt5514_dais,
+       .num_links = ARRAY_SIZE(mt8173_rt5650_rt5514_dais),
+       .codec_conf = mt8173_rt5650_rt5514_codec_conf,
+       .num_configs = ARRAY_SIZE(mt8173_rt5650_rt5514_codec_conf),
+       .controls = mt8173_rt5650_rt5514_controls,
+       .num_controls = ARRAY_SIZE(mt8173_rt5650_rt5514_controls),
+       .dapm_widgets = mt8173_rt5650_rt5514_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_rt5514_widgets),
+       .dapm_routes = mt8173_rt5650_rt5514_routes,
+       .num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_rt5514_routes),
+};
+
+static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &mt8173_rt5650_rt5514_card;
+       struct device_node *platform_node;
+       int i, ret;
+
+       platform_node = of_parse_phandle(pdev->dev.of_node,
+                                        "mediatek,platform", 0);
+       if (!platform_node) {
+               dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < card->num_links; i++) {
+               if (mt8173_rt5650_rt5514_dais[i].platform_name)
+                       continue;
+               mt8173_rt5650_rt5514_dais[i].platform_of_node = platform_node;
+       }
+
+       mt8173_rt5650_rt5514_codecs[0].of_node =
+               of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);
+       if (!mt8173_rt5650_rt5514_codecs[0].of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'audio-codec' missing or invalid\n");
+               return -EINVAL;
+       }
+       mt8173_rt5650_rt5514_codecs[1].of_node =
+               of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1);
+       if (!mt8173_rt5650_rt5514_codecs[1].of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'audio-codec' missing or invalid\n");
+               return -EINVAL;
+       }
+       mt8173_rt5650_rt5514_codec_conf[0].of_node =
+               mt8173_rt5650_rt5514_codecs[1].of_node;
+
+       card->dev = &pdev->dev;
+       platform_set_drvdata(pdev, card);
+
+       ret = devm_snd_soc_register_card(&pdev->dev, card);
+       if (ret)
+               dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+                       __func__, ret);
+       return ret;
+}
+
+static const struct of_device_id mt8173_rt5650_rt5514_dt_match[] = {
+       { .compatible = "mediatek,mt8173-rt5650-rt5514", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mt8173_rt5650_rt5514_dt_match);
+
+static struct platform_driver mt8173_rt5650_rt5514_driver = {
+       .driver = {
+                  .name = "mtk-rt5650-rt5514",
+                  .of_match_table = mt8173_rt5650_rt5514_dt_match,
+#ifdef CONFIG_PM
+                  .pm = &snd_soc_pm_ops,
+#endif
+       },
+       .probe = mt8173_rt5650_rt5514_dev_probe,
+};
+
+module_platform_driver(mt8173_rt5650_rt5514_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8173 RT5650 and RT5514 SoC machine driver");
+MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mtk-rt5650-rt5514");
+
index 50ba538eccb3f771da9c08685d4e33aa0cbfa80b..5c4c58c69c516aa32b76ae1e141f01685a6f0f62 100644 (file)
@@ -131,10 +131,17 @@ static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = {
        },
 };
 
+enum {
+       DAI_LINK_PLAYBACK,
+       DAI_LINK_CAPTURE,
+       DAI_LINK_CODEC_I2S,
+       DAI_LINK_INTERCODEC
+};
+
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
        /* Front End DAI links */
-       {
+       [DAI_LINK_PLAYBACK] = {
                .name = "rt5650_rt5676 Playback",
                .stream_name = "rt5650_rt5676 Playback",
                .cpu_dai_name = "DL1",
@@ -144,7 +151,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
                .dynamic = 1,
                .dpcm_playback = 1,
        },
-       {
+       [DAI_LINK_CAPTURE] = {
                .name = "rt5650_rt5676 Capture",
                .stream_name = "rt5650_rt5676 Capture",
                .cpu_dai_name = "VUL",
@@ -156,7 +163,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
        },
 
        /* Back End DAI links */
-       {
+       [DAI_LINK_CODEC_I2S] = {
                .name = "Codec",
                .cpu_dai_name = "I2S",
                .no_pcm = 1,
@@ -170,7 +177,8 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
                .dpcm_playback = 1,
                .dpcm_capture = 1,
        },
-       { /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
+       /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
+       [DAI_LINK_INTERCODEC] = {
                .name = "rt5650_rt5676 intercodec",
                .stream_name = "rt5650_rt5676 intercodec",
                .cpu_dai_name = "snd-soc-dummy-dai",
@@ -240,7 +248,7 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)
        mt8173_rt5650_rt5676_codec_conf[0].of_node =
                mt8173_rt5650_rt5676_codecs[1].of_node;
 
-       mt8173_rt5650_rt5676_dais[3].codec_of_node =
+       mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node =
                mt8173_rt5650_rt5676_codecs[1].of_node;
 
        card->dev = &pdev->dev;
diff --git a/sound/soc/mediatek/mt8173-rt5650.c b/sound/soc/mediatek/mt8173-rt5650.c
new file mode 100644 (file)
index 0000000..bb09bb1
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * mt8173-rt5650.c  --  MT8173 machine driver with RT5650 codecs
+ *
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Koro Chen <koro.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include "../codecs/rt5645.h"
+
+#define MCLK_FOR_CODECS                12288000
+
+static const struct snd_soc_dapm_widget mt8173_rt5650_widgets[] = {
+       SND_SOC_DAPM_SPK("Speaker", NULL),
+       SND_SOC_DAPM_MIC("Int Mic", NULL),
+       SND_SOC_DAPM_HP("Headphone", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mt8173_rt5650_routes[] = {
+       {"Speaker", NULL, "SPOL"},
+       {"Speaker", NULL, "SPOR"},
+       {"DMIC L1", NULL, "Int Mic"},
+       {"DMIC R1", NULL, "Int Mic"},
+       {"Headphone", NULL, "HPOL"},
+       {"Headphone", NULL, "HPOR"},
+       {"Headset Mic", NULL, "micbias1"},
+       {"Headset Mic", NULL, "micbias2"},
+       {"IN1P", NULL, "Headset Mic"},
+       {"IN1N", NULL, "Headset Mic"},
+};
+
+static const struct snd_kcontrol_new mt8173_rt5650_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Speaker"),
+       SOC_DAPM_PIN_SWITCH("Int Mic"),
+       SOC_DAPM_PIN_SWITCH("Headphone"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream,
+                                  struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int i, ret;
+
+       for (i = 0; i < rtd->num_codecs; i++) {
+               struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+
+               /* pll from mclk 12.288M */
+               ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS,
+                                         params_rate(params) * 512);
+               if (ret)
+                       return ret;
+
+               /* sysclk from pll */
+               ret = snd_soc_dai_set_sysclk(codec_dai, 1,
+                                            params_rate(params) * 512,
+                                            SND_SOC_CLOCK_IN);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static struct snd_soc_ops mt8173_rt5650_ops = {
+       .hw_params = mt8173_rt5650_hw_params,
+};
+
+static struct snd_soc_jack mt8173_rt5650_jack;
+
+static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime)
+{
+       struct snd_soc_card *card = runtime->card;
+       struct snd_soc_codec *codec = runtime->codec_dais[0]->codec;
+       int ret;
+
+       rt5645_sel_asrc_clk_src(codec,
+                               RT5645_DA_STEREO_FILTER |
+                               RT5645_AD_STEREO_FILTER,
+                               RT5645_CLK_SEL_I2S1_ASRC);
+       /* enable jack detection */
+       ret = snd_soc_card_jack_new(card, "Headset Jack",
+                                   SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
+                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                                   SND_JACK_BTN_2 | SND_JACK_BTN_3,
+                                   &mt8173_rt5650_jack, NULL, 0);
+       if (ret) {
+               dev_err(card->dev, "Can't new Headset Jack %d\n", ret);
+               return ret;
+       }
+
+       return rt5645_set_jack_detect(codec,
+                                     &mt8173_rt5650_jack,
+                                     &mt8173_rt5650_jack,
+                                     &mt8173_rt5650_jack);
+}
+
+static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = {
+       {
+               .dai_name = "rt5645-aif1",
+       },
+};
+
+enum {
+       DAI_LINK_PLAYBACK,
+       DAI_LINK_CAPTURE,
+       DAI_LINK_CODEC_I2S,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link mt8173_rt5650_dais[] = {
+       /* Front End DAI links */
+       [DAI_LINK_PLAYBACK] = {
+               .name = "rt5650 Playback",
+               .stream_name = "rt5650 Playback",
+               .cpu_dai_name = "DL1",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dynamic = 1,
+               .dpcm_playback = 1,
+       },
+       [DAI_LINK_CAPTURE] = {
+               .name = "rt5650 Capture",
+               .stream_name = "rt5650 Capture",
+               .cpu_dai_name = "VUL",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dynamic = 1,
+               .dpcm_capture = 1,
+       },
+       /* Back End DAI links */
+       [DAI_LINK_CODEC_I2S] = {
+               .name = "Codec",
+               .cpu_dai_name = "I2S",
+               .no_pcm = 1,
+               .codecs = mt8173_rt5650_codecs,
+               .num_codecs = 1,
+               .init = mt8173_rt5650_init,
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBS_CFS,
+               .ops = &mt8173_rt5650_ops,
+               .ignore_pmdown_time = 1,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+       },
+};
+
+static struct snd_soc_card mt8173_rt5650_card = {
+       .name = "mtk-rt5650",
+       .owner = THIS_MODULE,
+       .dai_link = mt8173_rt5650_dais,
+       .num_links = ARRAY_SIZE(mt8173_rt5650_dais),
+       .controls = mt8173_rt5650_controls,
+       .num_controls = ARRAY_SIZE(mt8173_rt5650_controls),
+       .dapm_widgets = mt8173_rt5650_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_widgets),
+       .dapm_routes = mt8173_rt5650_routes,
+       .num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_routes),
+};
+
+static int mt8173_rt5650_dev_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &mt8173_rt5650_card;
+       struct device_node *platform_node;
+       int i, ret;
+
+       platform_node = of_parse_phandle(pdev->dev.of_node,
+                                        "mediatek,platform", 0);
+       if (!platform_node) {
+               dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < card->num_links; i++) {
+               if (mt8173_rt5650_dais[i].platform_name)
+                       continue;
+               mt8173_rt5650_dais[i].platform_of_node = platform_node;
+       }
+
+       mt8173_rt5650_codecs[0].of_node =
+               of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);
+       if (!mt8173_rt5650_codecs[0].of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'audio-codec' missing or invalid\n");
+               return -EINVAL;
+       }
+       card->dev = &pdev->dev;
+       platform_set_drvdata(pdev, card);
+
+       ret = devm_snd_soc_register_card(&pdev->dev, card);
+       if (ret)
+               dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+                       __func__, ret);
+       return ret;
+}
+
+static const struct of_device_id mt8173_rt5650_dt_match[] = {
+       { .compatible = "mediatek,mt8173-rt5650", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mt8173_rt5650_dt_match);
+
+static struct platform_driver mt8173_rt5650_driver = {
+       .driver = {
+                  .name = "mtk-rt5650",
+                  .of_match_table = mt8173_rt5650_dt_match,
+#ifdef CONFIG_PM
+                  .pm = &snd_soc_pm_ops,
+#endif
+       },
+       .probe = mt8173_rt5650_dev_probe,
+};
+
+module_platform_driver(mt8173_rt5650_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8173 RT5650 SoC machine driver");
+MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mtk-rt5650");
+
index 9b1af1a7087480c95f931a3b9e020d0f33ac8e46..f341f623e887f2d2d169e33ef89903a6705c186c 100644 (file)
@@ -87,6 +87,7 @@ struct mtk_afe_memif_data {
        int irq_en_shift;
        int irq_fs_shift;
        int irq_clr_shift;
+       int msb_shift;
 };
 
 struct mtk_afe_memif {
index 08af9f5dc4ab2117bb81501b0381930f9cf483b5..f1c58a2c12fbbd8420614c576f75a19cf90c08e6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <sound/soc.h>
 #include "mtk-afe-common.h"
 #define AFE_I2S_CON1           0x0034
 #define AFE_I2S_CON2           0x0038
 #define AFE_CONN_24BIT         0x006c
+#define AFE_MEMIF_MSB          0x00cc
 
 #define AFE_CONN1              0x0024
 #define AFE_CONN2              0x0028
+#define AFE_CONN3              0x002c
 #define AFE_CONN7              0x0460
 #define AFE_CONN8              0x0464
 #define AFE_HDMI_CONN0         0x0390
@@ -61,6 +64,7 @@
 #define AFE_HDMI_OUT_CUR       0x0378
 #define AFE_HDMI_OUT_END       0x037c
 
+#define AFE_ADDA_TOP_CON0      0x0120
 #define AFE_ADDA2_TOP_CON0     0x0600
 
 #define AFE_HDMI_OUT_CON0      0x0370
@@ -257,6 +261,7 @@ static int mtk_afe_set_i2s(struct mtk_afe *afe, unsigned int rate)
                return -EINVAL;
 
        /* from external ADC */
+       regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
        regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1);
 
        /* set input */
@@ -281,20 +286,13 @@ static void mtk_afe_set_i2s_enable(struct mtk_afe *afe, bool enable)
 
        regmap_read(afe->regmap, AFE_I2S_CON2, &val);
        if (!!(val & AFE_I2S_CON2_EN) == enable)
-               return; /* must skip soft reset */
-
-       /* I2S soft reset begin */
-       regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0x4);
+               return;
 
        /* input */
        regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable);
 
        /* output */
        regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable);
-
-       /* I2S soft reset end */
-       udelay(1);
-       regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0);
 }
 
 static int mtk_afe_dais_enable_clks(struct mtk_afe *afe,
@@ -363,6 +361,7 @@ static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream,
                return 0;
 
        mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
+       mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
        regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
                           AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
        return 0;
@@ -382,6 +381,7 @@ static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream,
                           AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
                           AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
        mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
+       mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
 }
 
 static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
@@ -395,6 +395,9 @@ static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
        mtk_afe_dais_set_clks(afe,
                              afe->clocks[MTK_CLK_I2S1_M], runtime->rate * 256,
                              NULL, 0);
+       mtk_afe_dais_set_clks(afe,
+                             afe->clocks[MTK_CLK_I2S2_M], runtime->rate * 256,
+                             NULL, 0);
        /* config I2S */
        ret = mtk_afe_set_i2s(afe, substream->runtime->rate);
        if (ret)
@@ -592,6 +595,7 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
        struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
+       int msb_at_bit33 = 0;
        int ret;
 
        dev_dbg(afe->dev,
@@ -603,7 +607,8 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       memif->phys_buf_addr = substream->runtime->dma_addr;
+       msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0;
+       memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr);
        memif->buffer_size = substream->runtime->dma_bytes;
 
        /* start */
@@ -614,6 +619,11 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
                     memif->data->reg_ofs_base + AFE_BASE_END_OFFSET,
                     memif->phys_buf_addr + memif->buffer_size - 1);
 
+       /* set MSB to 33-bit */
+       regmap_update_bits(afe->regmap, AFE_MEMIF_MSB,
+                          1 << memif->data->msb_shift,
+                          msb_at_bit33 << memif->data->msb_shift);
+
        /* set channel */
        if (memif->data->mono_shift >= 0) {
                unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
@@ -894,15 +904,19 @@ static const struct snd_kcontrol_new mtk_afe_o04_mix[] = {
 };
 
 static const struct snd_kcontrol_new mtk_afe_o09_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 0, 1, 0),
        SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0),
 };
 
 static const struct snd_kcontrol_new mtk_afe_o10_mix[] = {
+       SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN3, 3, 1, 0),
        SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0),
 };
 
 static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = {
        /* inter-connections */
+       SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -925,12 +939,16 @@ static const struct snd_soc_dapm_route mtk_afe_pcm_routes[] = {
        {"I2S Playback", NULL, "O04"},
        {"VUL", NULL, "O09"},
        {"VUL", NULL, "O10"},
+       {"I03", NULL, "I2S Capture"},
+       {"I04", NULL, "I2S Capture"},
        {"I17", NULL, "I2S Capture"},
        {"I18", NULL, "I2S Capture"},
        { "O03", "I05 Switch", "I05" },
        { "O04", "I06 Switch", "I06" },
        { "O09", "I17 Switch", "I17" },
+       { "O09", "I03 Switch", "I03" },
        { "O10", "I18 Switch", "I18" },
+       { "O10", "I04 Switch", "I04" },
 };
 
 static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = {
@@ -978,6 +996,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 0,
                .irq_fs_shift = 4,
                .irq_clr_shift = 0,
+               .msb_shift = 0,
        }, {
                .name = "DL2",
                .id = MTK_AFE_MEMIF_DL2,
@@ -991,6 +1010,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 2,
                .irq_fs_shift = 16,
                .irq_clr_shift = 2,
+               .msb_shift = 1,
        }, {
                .name = "VUL",
                .id = MTK_AFE_MEMIF_VUL,
@@ -1004,6 +1024,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 1,
                .irq_fs_shift = 8,
                .irq_clr_shift = 1,
+               .msb_shift = 6,
        }, {
                .name = "DAI",
                .id = MTK_AFE_MEMIF_DAI,
@@ -1017,6 +1038,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 3,
                .irq_fs_shift = 20,
                .irq_clr_shift = 3,
+               .msb_shift = 5,
        }, {
                .name = "AWB",
                .id = MTK_AFE_MEMIF_AWB,
@@ -1030,6 +1052,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 14,
                .irq_fs_shift = 24,
                .irq_clr_shift = 6,
+               .msb_shift = 3,
        }, {
                .name = "MOD_DAI",
                .id = MTK_AFE_MEMIF_MOD_DAI,
@@ -1043,6 +1066,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 3,
                .irq_fs_shift = 20,
                .irq_clr_shift = 3,
+               .msb_shift = 4,
        }, {
                .name = "HDMI",
                .id = MTK_AFE_MEMIF_HDMI,
@@ -1056,6 +1080,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
                .irq_en_shift = 12,
                .irq_fs_shift = -1,
                .irq_clr_shift = 4,
+               .msb_shift = 8,
        },
 };
 
@@ -1189,6 +1214,10 @@ static int mtk_afe_pcm_dev_probe(struct platform_device *pdev)
        struct mtk_afe *afe;
        struct resource *res;
 
+       ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33));
+       if (ret)
+               return ret;
+
        afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
        if (!afe)
                return -ENOMEM;
index a6c7b8d87cd2f15198334840b9013980f87313c0..13631003cb7c6796d49f5278834eb5924aea294c 100644 (file)
@@ -418,7 +418,7 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
        }
 
        stat = __raw_readl(saif->base + SAIF_STAT);
-       if (stat & BM_SAIF_STAT_BUSY) {
+       if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) {
                dev_err(cpu_dai->dev, "error: busy\n");
                return -EBUSY;
        }
index 190f868e78b24af37d8442d378c06aeb8ec6aaf2..fdecb70431745bf23c7113bf7abcede1cd5306ef 100644 (file)
@@ -133,7 +133,7 @@ static struct snd_soc_ops n810_ops = {
 static int n810_get_spk(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = n810_spk_func;
+       ucontrol->value.enumerated.item[0] = n810_spk_func;
 
        return 0;
 }
@@ -143,10 +143,10 @@ static int n810_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (n810_spk_func == ucontrol->value.integer.value[0])
+       if (n810_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       n810_spk_func = ucontrol->value.integer.value[0];
+       n810_spk_func = ucontrol->value.enumerated.item[0];
        n810_ext_control(&card->dapm);
 
        return 1;
@@ -155,7 +155,7 @@ static int n810_set_spk(struct snd_kcontrol *kcontrol,
 static int n810_get_jack(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = n810_jack_func;
+       ucontrol->value.enumerated.item[0] = n810_jack_func;
 
        return 0;
 }
@@ -165,10 +165,10 @@ static int n810_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (n810_jack_func == ucontrol->value.integer.value[0])
+       if (n810_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       n810_jack_func = ucontrol->value.integer.value[0];
+       n810_jack_func = ucontrol->value.enumerated.item[0];
        n810_ext_control(&card->dapm);
 
        return 1;
@@ -177,7 +177,7 @@ static int n810_set_jack(struct snd_kcontrol *kcontrol,
 static int n810_get_input(struct snd_kcontrol *kcontrol,
                          struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = n810_dmic_func;
+       ucontrol->value.enumerated.item[0] = n810_dmic_func;
 
        return 0;
 }
@@ -187,10 +187,10 @@ static int n810_set_input(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (n810_dmic_func == ucontrol->value.integer.value[0])
+       if (n810_dmic_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       n810_dmic_func = ucontrol->value.integer.value[0];
+       n810_dmic_func = ucontrol->value.enumerated.item[0];
        n810_ext_control(&card->dapm);
 
        return 1;
index f83cc2bc0fc41a3434e0dca238569e613e3bad22..64425d352962f889989ad59d73a71f18cfae53e2 100644 (file)
@@ -345,6 +345,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev)
                dai_drv = &omap4_hdmi_dai;
                break;
        case OMAPDSS_VER_OMAP5:
+       case OMAPDSS_VER_DRA7xx:
                dai_drv = &omap5_hdmi_dai;
                break;
        default:
index 5e21f08579d804c5f7895a22e87de6cdff8b79ef..54949242bc7075587e6a73a7235049db2e108734 100644 (file)
@@ -132,7 +132,7 @@ static struct snd_soc_ops rx51_ops = {
 static int rx51_get_spk(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = rx51_spk_func;
+       ucontrol->value.enumerated.item[0] = rx51_spk_func;
 
        return 0;
 }
@@ -142,10 +142,10 @@ static int rx51_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (rx51_spk_func == ucontrol->value.integer.value[0])
+       if (rx51_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       rx51_spk_func = ucontrol->value.integer.value[0];
+       rx51_spk_func = ucontrol->value.enumerated.item[0];
        rx51_ext_control(&card->dapm);
 
        return 1;
@@ -180,7 +180,7 @@ static int rx51_hp_event(struct snd_soc_dapm_widget *w,
 static int rx51_get_input(struct snd_kcontrol *kcontrol,
                          struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = rx51_dmic_func;
+       ucontrol->value.enumerated.item[0] = rx51_dmic_func;
 
        return 0;
 }
@@ -190,10 +190,10 @@ static int rx51_set_input(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (rx51_dmic_func == ucontrol->value.integer.value[0])
+       if (rx51_dmic_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       rx51_dmic_func = ucontrol->value.integer.value[0];
+       rx51_dmic_func = ucontrol->value.enumerated.item[0];
        rx51_ext_control(&card->dapm);
 
        return 1;
@@ -202,7 +202,7 @@ static int rx51_set_input(struct snd_kcontrol *kcontrol,
 static int rx51_get_jack(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = rx51_jack_func;
+       ucontrol->value.enumerated.item[0] = rx51_jack_func;
 
        return 0;
 }
@@ -212,10 +212,10 @@ static int rx51_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (rx51_jack_func == ucontrol->value.integer.value[0])
+       if (rx51_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       rx51_jack_func = ucontrol->value.integer.value[0];
+       rx51_jack_func = ucontrol->value.enumerated.item[0];
        rx51_ext_control(&card->dapm);
 
        return 1;
index 416ea646c3b1606b7bbc499c50bd447046f6a23b..ec522e94b0e219408c359a0059b7ee0ce6c7b79c 100644 (file)
@@ -52,7 +52,6 @@ static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int freq_out, sspa_mclk, sysclk;
-       int sspa_div;
 
        if (params_rate(params) > 11025) {
                freq_out  = params_rate(params) * 512;
@@ -63,7 +62,6 @@ static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
                sysclk    = params_rate(params) * 512;
                sspa_mclk = params_rate(params) * 64;
        }
-       sspa_div = freq_out / sspa_mclk;
 
        snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0);
        snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk);
index c97dc13d36087628433de516a1b2217df02b492b..dcbb7aa9830c0347af6f7bd2c198639e52d9e24e 100644 (file)
@@ -163,7 +163,7 @@ static struct snd_soc_ops corgi_ops = {
 static int corgi_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = corgi_jack_func;
+       ucontrol->value.enumerated.item[0] = corgi_jack_func;
        return 0;
 }
 
@@ -172,10 +172,10 @@ static int corgi_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (corgi_jack_func == ucontrol->value.integer.value[0])
+       if (corgi_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       corgi_jack_func = ucontrol->value.integer.value[0];
+       corgi_jack_func = ucontrol->value.enumerated.item[0];
        corgi_ext_control(&card->dapm);
        return 1;
 }
@@ -183,7 +183,7 @@ static int corgi_set_jack(struct snd_kcontrol *kcontrol,
 static int corgi_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = corgi_spk_func;
+       ucontrol->value.enumerated.item[0] = corgi_spk_func;
        return 0;
 }
 
@@ -192,10 +192,10 @@ static int corgi_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (corgi_spk_func == ucontrol->value.integer.value[0])
+       if (corgi_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       corgi_spk_func = ucontrol->value.integer.value[0];
+       corgi_spk_func = ucontrol->value.enumerated.item[0];
        corgi_ext_control(&card->dapm);
        return 1;
 }
index 241d0be42d7a0c6779bb6459c5165728cbedb302..62b8377a9d2b93c81f06a8df4c0b5ed2cd7a567f 100644 (file)
@@ -308,17 +308,17 @@ static int magician_set_spk(struct snd_kcontrol *kcontrol,
 static int magician_get_input(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = magician_in_sel;
+       ucontrol->value.enumerated.item[0] = magician_in_sel;
        return 0;
 }
 
 static int magician_set_input(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
-       if (magician_in_sel == ucontrol->value.integer.value[0])
+       if (magician_in_sel == ucontrol->value.enumerated.item[0])
                return 0;
 
-       magician_in_sel = ucontrol->value.integer.value[0];
+       magician_in_sel = ucontrol->value.enumerated.item[0];
 
        switch (magician_in_sel) {
        case MAGICIAN_MIC:
index 84d0e2e508088a260b54911bca03236a50046203..4b3b714f5ee7a67e5538b191a9da99bac86e56f8 100644 (file)
@@ -138,7 +138,7 @@ static struct snd_soc_ops poodle_ops = {
 static int poodle_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = poodle_jack_func;
+       ucontrol->value.enumerated.item[0] = poodle_jack_func;
        return 0;
 }
 
@@ -147,10 +147,10 @@ static int poodle_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (poodle_jack_func == ucontrol->value.integer.value[0])
+       if (poodle_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       poodle_jack_func = ucontrol->value.integer.value[0];
+       poodle_jack_func = ucontrol->value.enumerated.item[0];
        poodle_ext_control(&card->dapm);
        return 1;
 }
@@ -158,7 +158,7 @@ static int poodle_set_jack(struct snd_kcontrol *kcontrol,
 static int poodle_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = poodle_spk_func;
+       ucontrol->value.enumerated.item[0] = poodle_spk_func;
        return 0;
 }
 
@@ -167,10 +167,10 @@ static int poodle_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (poodle_spk_func == ucontrol->value.integer.value[0])
+       if (poodle_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       poodle_spk_func = ucontrol->value.integer.value[0];
+       poodle_spk_func = ucontrol->value.enumerated.item[0];
        poodle_ext_control(&card->dapm);
        return 1;
 }
index b00222620fd01be5cf00d4118d44f18832ad3bdc..0e02634c8b7f6f41764b75344ae850ff7ce586d7 100644 (file)
@@ -164,7 +164,7 @@ static struct snd_soc_ops spitz_ops = {
 static int spitz_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = spitz_jack_func;
+       ucontrol->value.enumerated.item[0] = spitz_jack_func;
        return 0;
 }
 
@@ -173,10 +173,10 @@ static int spitz_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (spitz_jack_func == ucontrol->value.integer.value[0])
+       if (spitz_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       spitz_jack_func = ucontrol->value.integer.value[0];
+       spitz_jack_func = ucontrol->value.enumerated.item[0];
        spitz_ext_control(&card->dapm);
        return 1;
 }
@@ -184,7 +184,7 @@ static int spitz_set_jack(struct snd_kcontrol *kcontrol,
 static int spitz_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = spitz_spk_func;
+       ucontrol->value.enumerated.item[0] = spitz_spk_func;
        return 0;
 }
 
@@ -193,10 +193,10 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (spitz_spk_func == ucontrol->value.integer.value[0])
+       if (spitz_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       spitz_spk_func = ucontrol->value.integer.value[0];
+       spitz_spk_func = ucontrol->value.enumerated.item[0];
        spitz_ext_control(&card->dapm);
        return 1;
 }
index 49518dd642aa18ffd3f0004fe2f425210e820b54..c508f024ecfbc206887aeb9f91943311a279aed7 100644 (file)
@@ -95,7 +95,7 @@ static struct snd_soc_ops tosa_ops = {
 static int tosa_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = tosa_jack_func;
+       ucontrol->value.enumerated.item[0] = tosa_jack_func;
        return 0;
 }
 
@@ -104,10 +104,10 @@ static int tosa_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (tosa_jack_func == ucontrol->value.integer.value[0])
+       if (tosa_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       tosa_jack_func = ucontrol->value.integer.value[0];
+       tosa_jack_func = ucontrol->value.enumerated.item[0];
        tosa_ext_control(&card->dapm);
        return 1;
 }
@@ -115,7 +115,7 @@ static int tosa_set_jack(struct snd_kcontrol *kcontrol,
 static int tosa_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = tosa_spk_func;
+       ucontrol->value.enumerated.item[0] = tosa_spk_func;
        return 0;
 }
 
@@ -124,10 +124,10 @@ static int tosa_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (tosa_spk_func == ucontrol->value.integer.value[0])
+       if (tosa_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       tosa_spk_func = ucontrol->value.integer.value[0];
+       tosa_spk_func = ucontrol->value.enumerated.item[0];
        tosa_ext_control(&card->dapm);
        return 1;
 }
index 84d9e77c0fbe1e8d5e737d26beb492c3ce85883b..70a2559b63f9050bcbb86049717518d022463e2f 100644 (file)
@@ -481,10 +481,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
        unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
        unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
        u32 mod, mask, val = 0;
+       unsigned long flags;
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        switch (clk_id) {
        case SAMSUNG_I2S_OPCLK:
@@ -575,11 +576,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
        mod = (mod & ~mask) | val;
        writel(mod, i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        return 0;
 }
@@ -590,6 +591,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
        struct i2s_dai *i2s = to_info(dai);
        int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
        u32 mod, tmp = 0;
+       unsigned long flags;
 
        lrp_shift = i2s->variant_regs->lrp_off;
        sdf_shift = i2s->variant_regs->sdf_off;
@@ -649,7 +651,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
        /*
         * Don't change the I2S mode if any controller is active on this
@@ -657,7 +659,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
         */
        if (any_active(i2s) &&
                ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
-               spin_unlock(i2s->lock);
+               spin_unlock_irqrestore(i2s->lock, flags);
                dev_err(&i2s->pdev->dev,
                                "%s:%d Other DAI busy\n", __func__, __LINE__);
                return -EAGAIN;
@@ -666,7 +668,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
        mod &= ~(sdf_mask | lrp_rlow | mod_slave);
        mod |= tmp;
        writel(mod, i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        return 0;
 }
@@ -676,6 +678,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 {
        struct i2s_dai *i2s = to_info(dai);
        u32 mod, mask = 0, val = 0;
+       unsigned long flags;
 
        if (!is_secondary(i2s))
                mask |= (MOD_DC2_EN | MOD_DC1_EN);
@@ -744,11 +747,11 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
        mod = (mod & ~mask) | val;
        writel(mod, i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
 
index 790ee2bf1a474b394a286f650b2772c8d3436c05..d2e62b159610bba4dce327a259affc62a92a6cde 100644 (file)
@@ -986,16 +986,16 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
 
        dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
 
-       rtd = soc_new_pcm_runtime(card, dai_link);
-       if (!rtd)
-               return -ENOMEM;
-
        if (soc_is_dai_link_bound(card, dai_link)) {
                dev_dbg(card->dev, "ASoC: dai link %s already bound\n",
                        dai_link->name);
                return 0;
        }
 
+       rtd = soc_new_pcm_runtime(card, dai_link);
+       if (!rtd)
+               return -ENOMEM;
+
        cpu_dai_component.name = dai_link->cpu_name;
        cpu_dai_component.of_node = dai_link->cpu_of_node;
        cpu_dai_component.dai_name = dai_link->cpu_dai_name;
index 0d37079879002d472c538b69ccc3321c0d7772ad..801ae1a81dfd8eab907b1273b641493c74f9ff58 100644 (file)
@@ -2805,7 +2805,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
 int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
                            const struct snd_soc_dapm_route *route, int num)
 {
-       int i, ret = 0;
+       int i;
 
        mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
        for (i = 0; i < num; i++) {
@@ -2814,7 +2814,7 @@ int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
        }
        mutex_unlock(&dapm->card->dapm_mutex);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);
 
@@ -3573,7 +3573,7 @@ static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
 
-       ucontrol->value.integer.value[0] = w->params_select;
+       ucontrol->value.enumerated.item[0] = w->params_select;
 
        return 0;
 }
@@ -3587,13 +3587,13 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
        if (w->power)
                return -EBUSY;
 
-       if (ucontrol->value.integer.value[0] == w->params_select)
+       if (ucontrol->value.enumerated.item[0] == w->params_select)
                return 0;
 
-       if (ucontrol->value.integer.value[0] >= w->num_params)
+       if (ucontrol->value.enumerated.item[0] >= w->num_params)
                return -EINVAL;
 
-       w->params_select = ucontrol->value.integer.value[0];
+       w->params_select = ucontrol->value.enumerated.item[0];
 
        return 0;
 }
index 1af4f23697a781416f89794050ab41fb631f0171..aa99dac31b3bff3ce6bb510b4b07bba637363371 100644 (file)
@@ -1867,18 +1867,6 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
                if (!snd_soc_dpcm_be_can_update(fe, be, stream))
                        continue;
 
-               /* only allow hw_params() if no connected FEs are running */
-               if (!snd_soc_dpcm_can_be_params(fe, be, stream))
-                       continue;
-
-               if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
-                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
-                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
-                       continue;
-
-               dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
-                       dpcm->fe->dai_link->name);
-
                /* copy params for each dpcm */
                memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
                                sizeof(struct snd_pcm_hw_params));
@@ -1895,6 +1883,18 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
                        }
                }
 
+               /* only allow hw_params() if no connected FEs are running */
+               if (!snd_soc_dpcm_can_be_params(fe, be, stream))
+                       continue;
+
+               if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
+                       continue;
+
+               dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
+                       dpcm->fe->dai_link->name);
+
                ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
                if (ret < 0) {
                        dev_err(dpcm->be->dev,
index cc39f63299ef0a1fe58572ab23139f46725f9587..007cf583112154bc56616234d25e92f4e5e8212c 100644 (file)
@@ -2455,7 +2455,6 @@ int snd_usbmidi_create(struct snd_card *card,
        else
                err = snd_usbmidi_create_endpoints(umidi, endpoints);
        if (err < 0) {
-               snd_usbmidi_free(umidi);
                return err;
        }
 
index 4f6ce1cac8e20ef8b504073a6dfcc6236c0cf90c..c458d60d50300823e03e39109b715c94bf44cbbf 100644 (file)
@@ -1124,6 +1124,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
        case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
        case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
        case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+       case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
        case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
        case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
        case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
index 81a2eb77ba7ff56f7558328437fa32e8345051cd..05d815851be19bd40e00672c913a83ad2003175a 100644 (file)
@@ -2068,6 +2068,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
                err = -ENOMEM;
                goto err_free_queues;
        }
+
+       /*
+        * Since this thread will not be kept in any rbtree not in a
+        * list, initialize its list node so that at thread__put() the
+        * current thread lifetime assuption is kept and we don't segfault
+        * at list_del_init().
+        */
+       INIT_LIST_HEAD(&pt->unknown_thread->node);
+
        err = thread__set_comm(pt->unknown_thread, "unknown", 0);
        if (err)
                goto err_delete_thread;
index 4f7b0efdde2fa0c0c9f7cab32c6a20809ea47a4f..813d9b272c813b0dd749470f6209aa3a0a0607b4 100644 (file)
@@ -399,6 +399,9 @@ static void tracepoint_error(struct parse_events_error *e, int err,
 {
        char help[BUFSIZ];
 
+       if (!e)
+               return;
+
        /*
         * We get error directly from syscall errno ( > 0),
         * or from encoded pointer's error ( < 0).
index 2be10fb27172727fe15d5f3822ff194a5ad96d95..4ce5c5e18f48cd43777d2eb9c77aea35944440b8 100644 (file)
@@ -686,8 +686,9 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
                pf->fb_ops = NULL;
 #if _ELFUTILS_PREREQ(0, 142)
        } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
-                  pf->cfi != NULL) {
-               if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
+                  (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
+               if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
+                    (dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
                    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
                        pr_warning("Failed to get call frame on 0x%jx\n",
                                   (uintmax_t)pf->addr);
@@ -1015,8 +1016,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
        return DWARF_CB_OK;
 }
 
-/* Find probe points from debuginfo */
-static int debuginfo__find_probes(struct debuginfo *dbg,
+static int debuginfo__find_probe_location(struct debuginfo *dbg,
                                  struct probe_finder *pf)
 {
        struct perf_probe_point *pp = &pf->pev->point;
@@ -1025,27 +1025,6 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
        Dwarf_Die *diep;
        int ret = 0;
 
-#if _ELFUTILS_PREREQ(0, 142)
-       Elf *elf;
-       GElf_Ehdr ehdr;
-       GElf_Shdr shdr;
-
-       /* Get the call frame information from this dwarf */
-       elf = dwarf_getelf(dbg->dbg);
-       if (elf == NULL)
-               return -EINVAL;
-
-       if (gelf_getehdr(elf, &ehdr) == NULL)
-               return -EINVAL;
-
-       if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
-           shdr.sh_type == SHT_PROGBITS) {
-               pf->cfi = dwarf_getcfi_elf(elf);
-       } else {
-               pf->cfi = dwarf_getcfi(dbg->dbg);
-       }
-#endif
-
        off = 0;
        pf->lcache = intlist__new(NULL);
        if (!pf->lcache)
@@ -1108,6 +1087,39 @@ found:
        return ret;
 }
 
+/* Find probe points from debuginfo */
+static int debuginfo__find_probes(struct debuginfo *dbg,
+                                 struct probe_finder *pf)
+{
+       int ret = 0;
+
+#if _ELFUTILS_PREREQ(0, 142)
+       Elf *elf;
+       GElf_Ehdr ehdr;
+       GElf_Shdr shdr;
+
+       if (pf->cfi_eh || pf->cfi_dbg)
+               return debuginfo__find_probe_location(dbg, pf);
+
+       /* Get the call frame information from this dwarf */
+       elf = dwarf_getelf(dbg->dbg);
+       if (elf == NULL)
+               return -EINVAL;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL)
+               return -EINVAL;
+
+       if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
+           shdr.sh_type == SHT_PROGBITS)
+               pf->cfi_eh = dwarf_getcfi_elf(elf);
+
+       pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
+#endif
+
+       ret = debuginfo__find_probe_location(dbg, pf);
+       return ret;
+}
+
 struct local_vars_finder {
        struct probe_finder *pf;
        struct perf_probe_arg *args;
index bed82716e1b44960a0ebc435d0ba1e94ed30730d..0aec7704e39540b51a449cdf395b6a16ab682fba 100644 (file)
@@ -76,7 +76,10 @@ struct probe_finder {
 
        /* For variable searching */
 #if _ELFUTILS_PREREQ(0, 142)
-       Dwarf_CFI               *cfi;           /* Call Frame Information */
+       /* Call Frame Information from .eh_frame */
+       Dwarf_CFI               *cfi_eh;
+       /* Call Frame Information from .debug_frame */
+       Dwarf_CFI               *cfi_dbg;
 #endif
        Dwarf_Op                *fb_ops;        /* Frame base attribute */
        struct perf_probe_arg   *pvar;          /* Current target variable */
index 2b58edccd56f8bf63c0364d17b5ada656f4f582c..afb0c45eba34ba8db7a6cb6d258326f545f7aca1 100644 (file)
@@ -311,6 +311,16 @@ int perf_stat_process_counter(struct perf_stat_config *config,
 
        aggr->val = aggr->ena = aggr->run = 0;
 
+       /*
+        * We calculate counter's data every interval,
+        * and the display code shows ps->res_stats
+        * avg value. We need to zero the stats for
+        * interval mode, otherwise overall avg running
+        * averages will be shown for each interval.
+        */
+       if (config->interval)
+               init_stats(ps->res_stats);
+
        if (counter->per_pkg)
                zero_per_pkg(counter);
 
index 90bd2ea4103232b68e29e167873ff21a3f76b262..b3281dcd4a5d5502af9f66720dfcdccb1aca4d58 100644 (file)
@@ -217,13 +217,16 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd,
        return rc;
 }
 
+#define NFIT_TEST_ARS_RECORDS 4
+
 static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
                unsigned int buf_len)
 {
        if (buf_len < sizeof(*nd_cmd))
                return -EINVAL;
 
-       nd_cmd->max_ars_out = 256;
+       nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status)
+               + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record);
        nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16;
 
        return 0;
@@ -246,7 +249,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd,
        if (buf_len < sizeof(*nd_cmd))
                return -EINVAL;
 
-       nd_cmd->out_length = 256;
+       nd_cmd->out_length = sizeof(struct nd_cmd_ars_status);
+       /* TODO: emit error records */
        nd_cmd->num_records = 0;
        nd_cmd->address = 0;
        nd_cmd->length = -1ULL;
index 77edcdcc016bbe9e891dbee8ce27c5824caaae63..057278448515a455a17ff2b48af2bf0902c2e7fb 100755 (executable)
@@ -88,7 +88,11 @@ test_delete()
                exit 1
        fi
 
-       rm $file
+       rm $file 2>/dev/null
+       if [ $? -ne 0 ]; then
+               chattr -i $file
+               rm $file
+       fi
 
        if [ -e $file ]; then
                echo "$file couldn't be deleted" >&2
@@ -111,6 +115,7 @@ test_zero_size_delete()
                exit 1
        fi
 
+       chattr -i $file
        printf "$attrs" > $file
 
        if [ -e $file ]; then
@@ -141,7 +146,11 @@ test_valid_filenames()
                        echo "$file could not be created" >&2
                        ret=1
                else
-                       rm $file
+                       rm $file 2>/dev/null
+                       if [ $? -ne 0 ]; then
+                               chattr -i $file
+                               rm $file
+                       fi
                fi
        done
 
@@ -174,7 +183,11 @@ test_invalid_filenames()
 
                if [ -e $file ]; then
                        echo "Creating $file should have failed" >&2
-                       rm $file
+                       rm $file 2>/dev/null
+                       if [ $? -ne 0 ]; then
+                               chattr -i $file
+                               rm $file
+                       fi
                        ret=1
                fi
        done
index 8c0764407b3c349431a6b78ca595e450e2661066..4af74f7330365e668d9e1379f6894f12d974374d 100644 (file)
@@ -1,10 +1,68 @@
+#include <errno.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <linux/fs.h>
+
+static int set_immutable(const char *path, int immutable)
+{
+       unsigned int flags;
+       int fd;
+       int rc;
+       int error;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return fd;
+
+       rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+       if (rc < 0) {
+               error = errno;
+               close(fd);
+               errno = error;
+               return rc;
+       }
+
+       if (immutable)
+               flags |= FS_IMMUTABLE_FL;
+       else
+               flags &= ~FS_IMMUTABLE_FL;
+
+       rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
+       error = errno;
+       close(fd);
+       errno = error;
+       return rc;
+}
+
+static int get_immutable(const char *path)
+{
+       unsigned int flags;
+       int fd;
+       int rc;
+       int error;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return fd;
+
+       rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
+       if (rc < 0) {
+               error = errno;
+               close(fd);
+               errno = error;
+               return rc;
+       }
+       close(fd);
+       if (flags & FS_IMMUTABLE_FL)
+               return 1;
+       return 0;
+}
 
 int main(int argc, char **argv)
 {
@@ -27,7 +85,7 @@ int main(int argc, char **argv)
        buf[4] = 0;
 
        /* create a test variable */
-       fd = open(path, O_WRONLY | O_CREAT);
+       fd = open(path, O_WRONLY | O_CREAT, 0600);
        if (fd < 0) {
                perror("open(O_WRONLY)");
                return EXIT_FAILURE;
@@ -41,6 +99,18 @@ int main(int argc, char **argv)
 
        close(fd);
 
+       rc = get_immutable(path);
+       if (rc < 0) {
+               perror("ioctl(FS_IOC_GETFLAGS)");
+               return EXIT_FAILURE;
+       } else if (rc) {
+               rc = set_immutable(path, 0);
+               if (rc < 0) {
+                       perror("ioctl(FS_IOC_SETFLAGS)");
+                       return EXIT_FAILURE;
+               }
+       }
+
        fd = open(path, O_RDONLY);
        if (fd < 0) {
                perror("open");
index 773e276ff90b982a2bf24a44388f76b6ccdf4e9e..1e1abe0ad354267507dc0514351d651e19fd1fb6 100644 (file)
@@ -39,28 +39,23 @@ instance_slam() {
 }
 
 instance_slam &
-x=`jobs -l`
-p1=`echo $x | cut -d' ' -f2`
+p1=$!
 echo $p1
 
 instance_slam &
-x=`jobs -l | tail -1`
-p2=`echo $x | cut -d' ' -f2`
+p2=$!
 echo $p2
 
 instance_slam &
-x=`jobs -l | tail -1`
-p3=`echo $x | cut -d' ' -f2`
+p3=$!
 echo $p3
 
 instance_slam &
-x=`jobs -l | tail -1`
-p4=`echo $x | cut -d' ' -f2`
+p4=$!
 echo $p4
 
 instance_slam &
-x=`jobs -l | tail -1`
-p5=`echo $x | cut -d' ' -f2`
+p5=$!
 echo $p5
 
 ls -lR >/dev/null
index 69bca185c471d1dec971f02403ae9fd60851f5bd..ea6064696fe43867d1d1baee35059b276d84817b 100644 (file)
@@ -143,7 +143,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
  * Check if there was a change in the timer state (should we raise or lower
  * the line level to the GIC).
  */
-static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
+static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
@@ -154,10 +154,12 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
         * until we call this function from kvm_timer_flush_hwstate.
         */
        if (!vgic_initialized(vcpu->kvm))
-           return;
+               return -ENODEV;
 
        if (kvm_timer_should_fire(vcpu) != timer->irq.level)
                kvm_timer_update_irq(vcpu, !timer->irq.level);
+
+       return 0;
 }
 
 /*
@@ -218,7 +220,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
        bool phys_active;
        int ret;
 
-       kvm_timer_update_state(vcpu);
+       if (kvm_timer_update_state(vcpu))
+               return;
 
        /*
        * If we enter the guest with the virtual input level to the VGIC
index 043032c6a5a4dc6944c5b2bc6277ad6398decd23..00429b392c61cbbd32203877405631f635fc61e3 100644 (file)
@@ -1875,8 +1875,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
 static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-
-       int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8;
+       int nr_longs = BITS_TO_LONGS(nr_irqs - VGIC_NR_PRIVATE_IRQS);
+       int sz = nr_longs * sizeof(unsigned long);
        vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL);
        vgic_cpu->active_shared = kzalloc(sz, GFP_KERNEL);
        vgic_cpu->pend_act_shared = kzalloc(sz, GFP_KERNEL);
index 35315992245600a418874fd371e641ef336a0a22..db2dd3335c6a6de0c2f0dd9fe89e462d16f5ba81 100644 (file)
@@ -172,7 +172,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
         * do alloc nowait since if we are going to sleep anyway we
         * may as well sleep faulting in page
         */
-       work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT);
+       work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT | __GFP_NOWARN);
        if (!work)
                return 0;